Originariamente inviato da xxxAlex83xxx
Ciao a tutti..sto scrivendo una applicazione che mi permetta di disegnare dei grafi (orientati) su una finestra.
Non so se puo' interessare ma sto usando le librerie grafiche Qt (poiche' lavoro sotto linux le ho preferite a tutte le altre per il fatto di essere completamente multipiattaforma)
Riesco a fare quasi tutto... piazzo i nodi (con le rispettive etichette), piazzo gli archi.. ma non so come orientarli! Mi interessa solo la parte grafica, poiche' il mio programma (e gli algoritmi che ho gia' implementato) riescono a capire che e' orientato in un modo invece che in un altro.
Mi spiego meglio.. ho un oggetto edgeItem che eredita le proprieta' e i metodi di un oggetto linea fornitomi con le Qt (QCanvasLine si chiama in particolare)..
Ma come faccio a disegnare la punta ??
Esempio:
Ho due nodi 0 e 1.. (ogni nodo e' rappresentato sullo schermo con un cerchio di diametro 30px ).. l'arco parte dal centro del nodo 0 per finire nel centro del nodo 1. Quindi la punta della freccia dovrebbe stare un po' prima.. cioe' sull'intersezione dell'arco sul nodo di arrivo.. e li disegnare le due lineette che formano la punta!
Non so proprio cosa inventarmi per fare cio'.. mi date qualche consiglio ?
E' un problema che ho avuto anch'io in un algoritmo in cui stampavo un grafo orientato, l'ho risolto applicando un po' di geometria e delle leggi di proporzioni.
prima ti dico come ho strutturato il problema nel mio caso:
- Ho una funzione che, dato il numero di nodi, mi restituisce le coordinate x,y per ogni nodo. Il modo migliore di sistemare i nodi sullo schermo è quello di disporli su di un cerchio, e così ho fatto (se vuoi ti invio anche questa funzione)
- Ora, dato il grafico (matrice di adiacenza) e le coordinate trovate, un'altra funzione si dedica alla stampa dei nodi e degli archi. I nodi li stampo proprio come un cerchio colorato, e per gli archi (che sono orientati) invece di una freccia ho stampato un piccolo cerchietto (la freccia è più complicata orientarla).
Ecco un'immagine di esempio che ho messo nella relazione per far capire:
Noi conosciamo le coordinate dei punti A e B, il problema è calcolare le coordinate di B' .
Ora, possiamo calcolare la distanza (o modulo) tra A e B che è:
dist = radice((A.x - B-x)^2 + (A.y - B-y)^2);
invece la distanza tra B' e B (cioè B'B) non nè altro che il raggio r del cerchio.
Inoltre AC non è altro che |A.x-B.x| e AD = |A.y-B.y|.
Se io trovo le distanza C'C e D'D, allora trovo che
B'.x = C.x - C'C;
B'.y = D.y - D'D;
Ora, per le proporzioni, AB sta a r come AC sta a C'C, quindi
C'C = (r * AC) / AB, analogamente D'D = (r * AD) / AB.
Ecco la mia funzione (il linguaggio è C):
codice:
void stampa_grafo (int *x, int *y, mat_adiac a, int n, int *check)
{
int i,j,frx,fry,nck=0;
stringa st;
float alpha,dist;
stampa_finestra (6,130,619,350,CLINEA,CSFONDO);
setfillstyle (1,0);
// stampa archi
setcolor (CARCO);
for (i=0; i<n; i++)
for (j=0; j<n; j++)
if (a[i][j]) // se c'è un arco
{
dist = sqrt (pow(x[i]-x[j],2) + pow(y[i]-y[j],2));
frx = x[j] - 9 * (x[j]-x[i]) / dist +0;
fry = y[j] - 9 * (y[j]-y[i]) / dist +1;
line (x[i],y[i],x[j],y[j]);
fillellipse (frx,fry,3,3);
}
// stampa nodi ed etichette
settextstyle(2, HORIZ_DIR, 4);
setusercharsize(5,6,5,6);
for (i=0; i<n; i++)
{
setfillstyle (1,(check==NULL || !check[i] ? CNODO1:CNODO2));
fillellipse (x[i],y[i],8,8);
sprintf (st,"%d",i+1);
outtextxy (x[i]-(i<10?2:4),y[i]-4,st);
}
getch();
}