#include "roads.h" void svg_start(int w, int h) { printf(""); printf("", w, h); } void svg_end() { printf(""); } void svg_line(Vertex* a, Vertex* b, short color) { if(color == 0) printf("", a->x, a->y, b->x, b->y); else if(color == 1) printf("", a->x, a->y, b->x, b->y); else if(color == 2) printf("", a->x, a->y, b->x, b->y); else printf("", a->x, a->y, b->x, b->y); } void svg_circle(int x, int y, int r) { printf("",x,y,r); } void roads(Polygon* quartier) { quartier = quartier; Vertex center = { .x=400, .y=300 }; svg_line(¢er, &(quartier[0]),6); } /* Fonctions de Yoann suffixée par "Y" */ /* Initialisation de la liste de routes. */ void initRoadslIst(int nb){ roadsList = (roadPointY**) malloc(sizeof(roadPointY*)*nb); } /* La route est constituée d'une série de points, chaque point contient un nœd de route qui peut-être propre à cette route comme * appartenir à plusieurs routes. Le nœd contient un Vertex qui permet de le positionner sur la carte. Il contient également * le nombre et les portions de routes auxquelles il appartient. */ // Transforme des coordonnées du plan en coordonées du tableau sur x. int toX(Vertex *v) { int x = v->x*(nbXSubDivision)/quarterWidth; if(x >= nbXSubDivision) return 0; return x; } // Transforme des coordonnées du plan en coordonées du tableau sur y. int toY(Vertex *v) { int y = v->y*(nbYSubDivision)/quarterHeight; if(y >= nbYSubDivision) return 0; return y; } /* Convertion de coordonnées polaires en coordonnées cartésiennes. * @param Vertex* origin : Origine du vecteur. * @param short angle : Angle. * @param short length : Taille du vecteur. * @return struct cartesianCoord* : Les coordonnées cartésiennes du point d'arrivée. */ cartesianCoord* ptc(Vertex *origin, short angle, short length) { cartesianCoord *cc = (cartesianCoord*) malloc(sizeof(cartesianCoord)); cc->x = origin->x + cos(M_PI*angle/180)*length; cc->y = origin->y + sin(M_PI*angle/180)*length; return cc; } /* Convertion de coordonnées cartésiennes en coordonnées polaires. * @param Vertex* origin : Origine du vecteur. * @param Vertex* end : Fin du vecteur. * @return struct polarCoord* : Les coordonnées polaires du point d'arrivée. */ polarCoord* ctp(Vertex *origin, Vertex *end) { polarCoord *pc = (polarCoord*) malloc(sizeof(polarCoord)); pc->length = distBetween(origin,end); pc->angle = acos((end->x-origin->x)/pc->length); return pc; } /* Initialise la grille de nœuds. * @param int width : Largeur du quartier à remplir. * @param int height : Hauteur du quartier à remplir. * @param int maxSegmentSize : Taille maximale d'un segment de route. */ void grid_initNodesGrid(int width, int height, int segmentSize) { int xSize, ySize; xSize = (int)(width/segmentSize); ySize = (int)(height/segmentSize); nodesGrid = (roadNodeY****) malloc(sizeof(roadNodeY***)*xSize); int i,j,k; maxSegmentSize = segmentSize; nbXSubDivision = xSize; nbYSubDivision = ySize; quarterWidth = width; quarterHeight = height; for(i=0;ix - va->x; Iy = vb->y - va->y; Jx = ub->x - ua->x; Jy = ub->y - ua->y; m = (float)(-(-Ix*va->y+Ix*ua->y+Iy*va->x-Iy*ua->x))/(float)(Ix*Jy-Iy*Jx); k = (float)(-(va->x*Jy-ua->x*Jy-Jx*va->y+Jx*ua->y))/(float)(Ix*Jy-Iy*Jx); if(m < 1 && m > 0 && k < 1 && k > 0) { inter->x = va->x + k * Ix; inter->y = va->y + k * Iy; } else return NULL; */ return NULL; //return inter; } void grid_drawGrid() { int i, j; for(i=0;iv == NULL) return 0; int i; for(i=0;iv)][toY(rn->v)][i] == NULL) { nodesGrid[toX(rn->v)][toY(rn->v)][i] = rn; return 1; } } return 0; } /* Retourne le nœd le plus proche dans un certain voisinage. Si aucun nœd n'est trouvé alors * la fonction renvoie NULL. * @param Vertex *v : Le nœd pour lequel on souhaite trouver un nœd proche. * @return roadNodeY* : le nœd de route le plus proche. */ roadNodeY* grid_getNearestRoadNode(Vertex *v) { roadNodeY **nr; roadNodeY *nearestNode = NULL; int i,j; int x = toX(v); int y = toY(v); int distance = maxSegmentSize*2; roadNodeY *tmp = NULL; int count = 0; fprintf(stderr,"colones : %d\n",nbXSubDivision); fprintf(stderr,"lignes : %d\n",nbYSubDivision); for(i=x-1; i= 0 && i < nbXSubDivision && y >= 0 && y < nbYSubDivision) { nr = grid_getNearNodes2(i,j); int ind; //tmp = nr[0]; fprintf(stderr,"passage %d\t\t %d %d\n",count,i,j); for(tmp = nr[0], ind = 0; tmp != NULL && ind < maxNodesInGrid; tmp = nr[ind++]) { fprintf(stderr,"noed\n"); int dist = distBetween(v,tmp->v); if(dist < distance) { distance = dist; nearestNode = tmp; } tmp = nr[i]; } } } } return nearestNode; } Vertex* insertRoadSegment(Segment *seg, int lag) { //int segLength = distBetween(seg->u, seg->v); //float coef = ((float)segLength-lag)/(float)segLength; //Vertex *nearestV = NULL; //Vertex tmpEnd; seg = seg; lag = lag; // ------- TODO à compléter et à vérifier. /*Segment **segs = grid_getNearSegments(rpb->rn->v->x,rpb->rn->v->y); Segment *seg = segs[0]; int s = 0; int intersec = 0; // Booléen si intersection = 1 sinon = 0; while(seg != NULL) { Vertex *intersection = intersectionBetween(rpb->rn->v,rne->v,seg->u,seg->v); if(intersection != NULL) { // Créer un nœd, l'insérer au segment qui à causé l'intersection. // Ce nœd deviens le point d'arriver du segment à placer : rne; intersec = 1; } seg = segs[s++]; }*/ // ------- /*if(intersec == 0) { tmpEnd.x = rpb->rn->v->x+coef*(rne->v->x - rpb->rn->v->x); tmpEnd.y = rpb->rn->v->y+coef*(rne->v->y - rpb->rn->v->y); //fprintf(stderr,"segLength : %d\n",segLength); //fprintf(stderr," ostart : %d %d\t oend : %d %d\n",rpb->rn->v->x,rpb->rn->v->y,rne->v->x,rne->v->y); //fprintf(stderr," end : %d %d\n",tmpEnd.x,tmpEnd.y); nearestNode = grid_getNearestRoadNode(&tmpEnd); //fprintf(stderr,"--11\n"); if(nearestNode != NULL && distBetween(nearestNode->v,rne->v) < lag) rne = nearestNode; } grid_insertRoadNode(rne);*/ //rstep = addRoadNode(road,rpb,rne); return NULL; } int distBetween(Vertex *v, Vertex *u) { return sqrt((v->x-u->x)*(v->x-u->x)+(v->y-u->y)*(v->y-u->y)); } roadNodeY** grid_getNearNodes(Vertex *v) { return nodesGrid[toX(v)][toY(v)]; } roadNodeY** grid_getNearNodes2(int x, int y) { return nodesGrid[x][y]; } /* Récupère tout les segement potentiellement sécant avec un segment ayant pour arrivée x et y. */ Segment** grid_getNearSegments(int x, int y) { roadNodeY **nr, *tmpnr; Segment** segs = (Segment**) malloc(sizeof(Segment)*9*maxNodesInGrid); int i, j, s, k, l; s = 0; for(i=x-1;i= 0 && x < nbXSubDivision && y >= 0 && y < nbYSubDivision) { nr = grid_getNearNodes2(i,j); k = 0; tmpnr = nr[0]; // TODO Tester si le segment existe déjà dans la liste pour ne pas l'insérer en double. while(tmpnr != NULL) { for(l=0;lnbIntersec;l++) { if(tmpnr->intersec[l]->next != NULL) { segs[s]->u = tmpnr->v; segs[s]->v = tmpnr->intersec[l]->next->v; } s++; if(tmpnr->intersec[l]->previous != NULL) { segs[s]->u = tmpnr->v; segs[s]->v = tmpnr->intersec[l]->previous->v; } } tmpnr = nr[k++]; } } } } return segs; } // Algo « champs de force » typedef struct FVector { float x; float y; } FVector; inline FVector fVector_substract(FVector a, FVector b) { return (FVector){ .x = a.x - b.x, .y = a.y - b.y }; } inline FVector fVector_add(FVector a, FVector b) { return (FVector){ .x = a.x + b.x, .y = a.y + b.y }; } inline FVector fVector_rotate90(FVector v) { return (FVector){ .x = -v.y, .y = v.x }; } typedef struct FSegment { FVector from; FVector to; } FSegment; inline void fsegment_display(FSegment s) { printf("", s.from.x, s.from.y, s.to.x, s.to.y); } // TODO : dimensionner correctement le tableau. #define FSegmentArray_SIZE 1024 typedef struct FSegmentArray { FSegment seg[FSegmentArray_SIZE]; int firstUnseen; int firstFree; /* + CollisionGrid collision; */ } FSegmentArray; inline void fSegmentArray_push(FSegmentArray* a, FSegment s) { // TODO : check for collisions. if (a->firstFree >= FSegmentArray_SIZE) return; a->seg[a->firstFree++] = s; } inline FSegment fSegmentArray_pop(FSegmentArray* a) { return a->seg[a->firstUnseen++]; } /* Choisir des champs de force. `f(x,y,vecteur)` renvoie tous les * vecteurs de routes qu'on peut faire partir du point `(x,y)`, * lorsqu'on y arrive par la direction `vecteur`. */ // champ de force "ligne droite". // TODO : devrait prendre un segment en paramètre. void f(FSegment s, FSegmentArray* a) { FVector delta = fVector_substract(s.to, s.from); FSegment newS = { .from = s.to, .to = fVector_add(s.to, delta), }; // TODO : s'accrocher aux points proches, et ne pas ajouter le segment à la queue si on s'accroche à un point existant. // TODO : ne pas utiliser des segments dans la file d'attente, mais juste des vertex, dont on peut énumérer les segments. fSegmentArray_push(a, newS); FSegment newS2 = { .from = s.to, .to = fVector_add(s.to, fVector_rotate90(delta)), }; newS2.to.y += 3; fSegmentArray_push(a, newS2); } /* ***************************** */ // Nouvelle version : #define vertices_array_size 1024 #define segments_array_size 1024 typedef struct Map { Vertex vertices[vertices_array_size]; Segment segments[segments_array_size]; int vertices_firstUnseen; int vertices_firstFree; int segments_firstFree; // TODO : champ grid & co. On peut même l'utiliser à la place de // vertices. } Map; void fv(Map* m, Vertex* v) { // TODO : tracer une ou des routes, en utilisant segment_to v=v; m=m; } Vertex* vertex_init(Map* m, int x, int y) { // TODO : s'il y a déjà un point dans la case de la grille pour // `(x,y)`, le renvoyer sans rien modifier. Vertex* v = &(m->vertices[m->vertices_firstFree++]); // TODO : insérer v dans la grille de m. m=m; v->x = x; v->y = y; v->s = NULL; return v; } Segment* segment_init(Map* m, Vertex* u, Vertex* v) { Segment* s = &(m->segments[m->segments_firstFree++]); s->u = u; s->v = v; s->nextU = u->s; s->nextV = v->s; u->s = s; v->s = s; return s; } Segment* segment_to(Map* m, Vertex* u, int x, int y) { Vertex* v = vertex_init(m, x, y); Segment* s = segment_init(m, u, v); return s; } void segment_display(Segment* s) { printf("", s->u->x, s->u->y, s->v->x, s->v->y); } void forceFields() { Map m; m.vertices[0] = (Vertex){ .x = 400, .y = 300, .s = NULL}; m.vertices_firstUnseen = 0; m.vertices_firstFree = 1; m.segments_firstFree = 0; grid_initNodesGrid(800, 600, 40); // TODO : insérer vertices[0] dans la grille. int i; for (i = 0; i < vertices_array_size; i++) { if (m.vertices_firstUnseen >= m.vertices_firstFree) break; fv(&m, &(m.vertices[m.vertices_firstUnseen++])); } grid_drawGrid(); for (i = 0; i < m.segments_firstFree; i++) { segment_display(&(m.segments[i])); } } int main() { Vertex points[] = { { .x=10, .y=10 }, { .x=790, .y=10 }, { .x=600, .y=300 }, { .x=790, .y=590 }, { .x=10, .y=590 }, }; int n = 5; svg_start(800,600); //carreY(); forceFields(); //int i; //for (i = 0; i < n; i++) { // svg_line(&(points[i]), &(points[(i+1)%n])); // } // grid_drawGrid(); n=n; //roads(points); points[0] = points[0]; svg_end(); return 0; }