You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
8.0 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <signal.h>
typedef struct {
double x;
double y;
} Node;
typedef struct {
size_t start;
size_t end;
} Edge;
// Varibili globali
int peso;
int node_count = 0;
int edge_count= 0;
volatile sig_atomic_t stop = 0; // Variabile volatile per indicare l'interruzione
double scaleFactor; // Fattore di scala iniziale
double offsetX; // Offeset iniziale
double offsetY;
void handle_signal(int sig) {
if (sig == SIGINT) {
stop = 1;
}
}
// Prototipi delle funzioni
void handle_signal(int sig);
void drawGraph(SDL_Renderer* renderer, Node *nodes, Edge *edges, int screenWidth, int screenHeight);
void getMaxNodeDimensions(double* maxX, double* maxY, Node *nodes);
// Funzione principale
int main(int argc, char* argv[]) {
if (argc < 2) {
printf("Uso corretto: %s nome_file\n", argv[0]);
return 1; // Esce dal programma con codice di errore
}
char* file_name = argv[1];
FILE* input = fopen(file_name, "r");
if (!input) {
printf("Il file non esiste.\n");
return 1;
}
// Lettura del numero di nodi e peso (che non viene utilizzato qui)
fscanf(input, "%d %*d", &node_count);
// Allocazione dinamica degli array di nodi
Node *nodes = malloc(node_count * sizeof(Node));
// Lettura delle coordinate dei nodi
for (int i = 0; i < node_count; i++) {
fscanf(input, "%*d %lf %lf\n", &nodes[i].x, &nodes[i].y);
}
// Lettura del numero di archi
fscanf(input, "%d", &edge_count);
// Allocazione dinamica degli array di archi
Edge *edges = malloc(edge_count * sizeof(Edge));
// Lettura degli indici degli archi
for (int i = 0; i < edge_count; i++) {
fscanf(input, "%zu %zu\n", &edges[i].start, &edges[i].end);
}
fclose(input);
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
fprintf(stderr, "SDL_Init Error: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
SDL_DisplayMode display_mode;
if (SDL_GetDesktopDisplayMode(0, &display_mode) != 0) {
fprintf(stderr, "SDL_GetDesktopDisplayMode Error: %s\n", SDL_GetError());
SDL_Quit();
exit(EXIT_FAILURE);
}
int screenWidth = display_mode.w - 10;
int screenHeight = display_mode.h - 10;
SDL_Window* window = SDL_CreateWindow("Graph Visualization",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
screenWidth, screenHeight,
SDL_WINDOW_FULLSCREEN);
if (window == NULL) {
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL) {
printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
double maX, maY;
getMaxNodeDimensions(&maX, &maY, nodes);// Calcola le dimensioni massime dei nodi per adattare le dimensioni della finestra
scaleFactor = fmin(screenWidth / (2 * maX), screenHeight / (2 * maY));
offsetX = 0.0;
offsetY = 0.0;
//drawGraph(renderer, &graph, screenWidth, screenHeight); // Disegno il grafico
signal(SIGINT, handle_signal); // Gestore di segnale, chiama handle_signal quando riceve SIGINT
SDL_Event e; // Variabile per ricevere un evento
int quit = 0;
int i = 0;
while (!quit && !stop) {
while (SDL_PollEvent(&e) != 0) { // Controllo se ci sono eventi
if (e.type == SDL_QUIT) {
quit = 1;
} else if (e.type == SDL_MOUSEWHEEL) { // Scorrere con la rotella del mouse
// Zoom in/out
if (e.wheel.y > 0) { // Scroll up
scaleFactor *= 1.1;
} else if (e.wheel.y < 0) { // Scroll down
scaleFactor /= 1.1;
}
//drawGraph(renderer, screenWidth, screenHeight); //Aggiorno il grafico
}else if (e.type == SDL_FINGERMOTION){ // Scroll da touchpad
if (e.tfinger.fingerId == 0 && e.type == SDL_FINGERMOTION) {
// Calcola la differenza di posizione tra due dita
double scrollDistance = sqrt(pow(e.tfinger.dx, 2) + pow(e.tfinger.dy, 2));
// Aggiorna scaleFactor in base a scrollDistance e alla direzione del movimento
scaleFactor *= scrollDistance > 0 ? (1.0 + scrollDistance * 0.01) : 1.0; // Aumento o diminuzione dello scale factor in base alla direzione
//drawGraph(renderer, screenWidth, screenHeight);
}
}
else if (e.type == SDL_KEYDOWN) {
// Gestione del movimento con i tasti freccia
switch (e.key.keysym.sym) {
case SDLK_LEFT:
offsetX += 500.0* (1/scaleFactor); // Spostamento a sinistra di 10 pixel
//drawGraph(renderer, screenWidth, screenHeight); //Aggiorno il grafico
break;
case SDLK_RIGHT:
offsetX -= 500.0* (1/scaleFactor); // Spostamento a destra di 10 pixel
//drawGraph(renderer, screenWidth, screenHeight); //Aggiorno il grafico
break;
case SDLK_UP:
offsetY += 500.0* (1/scaleFactor); // Spostamento verso l'alto di 10 pixel
//drawGraph(renderer, screenWidth, screenHeight); //Aggiorno il grafico
break;
case SDLK_DOWN:
offsetY -= 500.0* (1/scaleFactor); // Spostamento verso il basso di 10 pixel
//drawGraph(renderer, screenWidth, screenHeight); //Aggiorno il grafico
break;
default:
break;
}
}
}
drawGraph(renderer,nodes,edges,screenWidth, screenHeight);
}
// Cleanup SDL
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
void drawGraph(SDL_Renderer* renderer, Node *nodes, Edge *edges, int screenWidth, int screenHeight) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); // Colore bianco
SDL_RenderClear(renderer); // Pulisce lo schermo
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Colore nero per gli archi
for (size_t i = 0; i < edge_count; i++) {
size_t node1 = edges[i].start;
size_t node2 = edges[i].end;
SDL_RenderDrawLine(renderer,
(int)((nodes[node1].x + offsetX) * scaleFactor + screenWidth / 2),
(int)((nodes[node1].y + offsetY) * scaleFactor + screenHeight / 2),
(int)((nodes[node2].x + offsetX) * scaleFactor + screenWidth / 2),
(int)((nodes[node2].y + offsetY) * scaleFactor + screenHeight / 2)); //Disegna la linea tra due punti
}
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); // Colore rosso per i nodi
for (size_t i = 0; i < node_count; i++) {
int x = (int)((nodes[i].x + offsetX) * scaleFactor + screenWidth / 2);
int y = (int)((nodes[i].y + offsetY) * scaleFactor + screenHeight / 2);
SDL_Rect rect = {x - (2* scaleFactor), y - (2* scaleFactor), 4* scaleFactor, 4* scaleFactor};
SDL_RenderFillRect(renderer, &rect); //Disegno i nodi
}
SDL_RenderPresent(renderer); // Disegna su schermo
}
void getMaxNodeDimensions(double* maxX, double* maxY, Node *nodes) { // Trova le coordinate massime dei nodi, in valore assoluto
*maxX = 0.0;
*maxY = 0.0;
for (size_t i = 0; i < node_count; i++) {
if (fabs(nodes[i].x) > *maxX) {
*maxX = fabs(nodes[i].x);
}
if (fabs(nodes[i].y) > *maxY) {
*maxY = fabs(nodes[i].y);
}
}
}