diff --git a/roads.c b/roads.c
index b020dc9..25dc3d5 100644
--- a/roads.c
+++ b/roads.c
@@ -9,19 +9,65 @@ void svg_end() {
printf("");
}
-void svg_line(Vertex* a, Vertex* b) {
- printf("", a->x, a->y, b->x, b->y);
+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]));
+ svg_line(¢er, &(quartier[0]),6);
}
/* Fonctions de Yoann suffixée par "Y" */
+/* !!!!!!!! Modification de façon de gérer les routes.
+ * Au départ :
+ * - Une liste de routes vide.
+ * - Une grille de nœd de routes vide qui contiendra les nœds de de toutes les routes.
+ * Initialisation :
+ * - On initialise la grille avec la taille de la zone à remplir et le nombre max de nœds dans chaque cases.
+ * - On crée une ou plusieurs routes sue l'on insère dans la liste de routes et on place les nœds de
+ * ces routes dans la grille.
+ * Fonctionnement :
+ * -- La fonction addRoadNode :
+ * Ajoute un nœed à la route depuis un certain point de route. Si ce point de route n'est pas le dernier
+ * autrement dit si on crée une division de route alors la nouvelle voie créée constitue une nouvelle route. Et le
+ * point de route situé à l'intersection est le point d'origine de la nouvelle route.
+ */
+ /* ForceField revision :
+ * - Initialisation de la grille en fonction de la zone à couvrir.
+ * - Création d'une ou plusieurs routes de départ et insertion dan sla liste de routes.
+ * - Création d'un file (fifo) permettant l'avancé parrallèle de la création de routes.
+ * Cette liste sera constituée de structures à deux champs, l'identifiant de la route et le nœd où on s'est arrêté.
+ * - Tant que l'on à pas atteint la fin de la file on utilise le premier point de route non vu.
+ * Et on ajoute à la route le ou les nouveau segments retournées par la fonction f potentiellement filtrée.
+ * Ces nouveau morceaux de routes seraont également ajouté dans la file pour qu'il puissent faire l'objet d'un
+ * nouveau départ de route(s). Si une route est créer par division de route existante alors cette route sera ajoutée dans la liste de routes.
+ * ...
+ * !!!!!!!!! */
+
+
+
+/* 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.
@@ -30,23 +76,71 @@ void roads(Polygon* quartier) {
// TODO Fusionner les deux fonctions et retourner une paire de valeurs.
// Transforme des coordonnées du plan en coordonées du tableau sur x.
int toX(Vertex *v) {
- return v->x*(maxSubDivision-1)/quarterSize;
+ 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) {
- return v->x*(maxSubDivision-1)/quarterSize;
+ int y = v->y*(nbYSubDivision)/quarterHeight;
+ if(y >= nbYSubDivision) return 0;
+ return y;
}
-void grid_initNodesGrid(int size) {
- nodesGrid = (roadNodeY****) malloc(sizeof(roadNodeY***)*size);
- int i,j,k;
-
- maxSubDivision = size;
- for(i=0;ix = 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 inter;
+}
+
+
+void grid_drawGrid() {
+ int i, j;
+
+ for(i=0;iv == NULL)
return 0;
@@ -69,47 +212,145 @@ short grid_insertRoadNode(roadNodeY *rn) {
return 0;
}
-void addRoadNode(roadPointY *rp, roadNodeY *rn) {
- if(rp->rn == NULL) {
+
+roadStep* addRoadNode(roadPointY *rp, roadPointY *rpc, roadNodeY *rn) {
+ roadStep * rStep = (roadStep*) malloc(sizeof(roadStep));
+
+ if(rpc == rp) {
rp->next = NULL;
+ rp->previous = NULL;
rp->rn = rn;
- return;
+ rStep->roadId = rp;
+ rStep->rpc = rp;
+ return rStep;
}
- while(rp->next != NULL)
- rp = rp->next;
-
+
roadPointY *rpp = (roadPointY*) malloc(sizeof(roadPointY));
rpp->next = NULL;
- rpp->rn = rn;
- rp->next = rpp;
+
+ if(rpc->next != NULL) {
+ rpp->previous = NULL;
+ rpp->rn = rn;
+ rStep->roadId = rpp;
+ rStep->rpc = rpp;
+ return rStep;
+ }
+ else {
+ rpp->previous = rpc;
+ rpp->rn = rn;
+ rpc->next = rpp;
+ rStep->roadId = rp;
+ rStep->rpc = rpp;
+ }
+
+ return rStep;
+
+ // TODO modif les intersections de previous.
}
-roadNodeY* grid_getNearestRoadNode(Vertex *v) {
- roadNodeY **nr = grid_getNearNodes(v);
- roadNodeY *nearestNode = NULL;
- roadNodeY *tmp = nr[0];
- int distance = distBetween(v,tmp->v);
-
- if(tmp == NULL)
- return NULL;
-
- nearestNode = tmp;
- int i = 0;
- do {
- int dist = distBetween(v,tmp->v);
- if(dist < distance) {
- distance = dist;
- nearestNode = tmp;
+/* 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];
+ }
+ }
}
-
- i++;
- tmp = nr[i];
- } while(tmp != NULL);
+ }
return nearestNode;
}
+
+/* Ajoute un segment de route à la fin d'une route.
+ * Le point d'origine du segment est le dernier de la route actuellement en place. Il est passé en paramètre pour
+ * éviter le parcour de la route entière pour le trouver.
+ * Le point d'arrivé peut-etre modifié suivant deux règles principales.
+ * - Un nœd de route existe proche de l'endroit ou doit ce terminer le segment dans ce cas
+ * on "fusionne" les deux le point existant devient le point d'arrivé du segment.
+ * - Un segment se trouve sur le chemin du segment que l'on souhaite placer. Dans ce cas le segment
+ * que l'on souhaite placer sera sectionné à l'intersection des deux segments et le points d'intersections sera
+ * le point d'arrivé du segment à placer.
+ * @param roadPointY *road : La route à laquelle on veut ajouter le segmetn.
+ * @param roadNodeY *rnb : Le nœd de départ du segment.
+ * @param roadNodeY *rne : Le nœd d'arrivé du segment.
+ * @param int lag : le décalage maximal autorisé pour le placement du nœd d'arrivé.
+ * @return roadNodeY* : Le nœd d'arrivé du vecteur potentiellement modifié.
+ */
+roadStep* insertRoadSegment(roadPointY *road, roadPointY *rpb, roadNodeY *rne, int lag) {
+ int segLength = distBetween(rpb->rn->v, rne->v);
+ float coef = ((float)segLength-lag)/(float)segLength;
+ roadNodeY *nearestNode = NULL;
+ Vertex tmpEnd;
+ roadStep * rstep;
+
+ // ------- 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 rstep;
+}
+
+
int distBetween(Vertex *v, Vertex *u) {
return sqrt((v->x-u->x)*(v->x-u->x)+(v->y-u->y)*(v->y-u->y));
}
@@ -118,58 +359,129 @@ roadNodeY** grid_getNearNodes(Vertex *v) {
return nodesGrid[toX(v)][toY(v)];
}
-void carreY() {
- int size = 500;
- grid_initNodesGrid(6);
- roadPointY *roada = (roadPointY*) malloc(sizeof(roadPointY));
- roadPointY *roadb = (roadPointY*) malloc(sizeof(roadPointY));
- roadNodeY *rn;
- Vertex *v;
- roadNodeY *common = NULL;
- int i;
-
- for(i=0;i<40;i++) {
- rn = (roadNodeY*)malloc(sizeof(roadNodeY));
- v = (Vertex*) malloc(sizeof(Vertex));
-
- v->x = (i+1)*16;
- v->y = ((i+1)%3)*(61%(i+1))+100;
- rn->v = v;
- if(i == 18) common = rn;
- grid_insertRoadNode(rn);
- addRoadNode(roada,rn);
- }
-
- for(i=0;i<30;i++) {
- rn = (roadNodeY*)malloc(sizeof(roadNodeY));
- v = (Vertex*) malloc(sizeof(Vertex));
-
- v->x = (i+1)*22;
- v->y = ((i+1)%5)*(61%(i+2))+160;
- rn->v = v;
- if(i%5) if(grid_getNearestRoadNode(v) != NULL)
- rn = grid_getNearestRoadNode(v);
- //rn = common;
- addRoadNode(roadb,rn);
- }
-
- roadPointY *rd = roada;
- while(rd->next != NULL) {
- svg_line(rd->rn->v,rd->next->rn->v);
-
- rd = rd->next;
- }
-
- rd = roadb;
- while(rd->next != NULL) {
- svg_line(rd->rn->v,rd->next->rn->v);
-
- rd = rd->next;
- }
-
- size=size;
+
+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);
+}
+
+
+void forceFields() {
+ /* Initialiser `fifo` à vide. */
+ /* Choisir un point de départ aléatoire, une direction aléatoire,
+ * et insérer `(x,y,vecteur)` dans `fifo`. */
+ FSegmentArray a;
+ a.seg[0] = (FSegment){
+ .from = { .x = 400, .y = 300 },
+ .to = { .x = 360, .y = 300 }
+ };
+ a.firstUnseen = 0;
+ a.firstFree = 1;
+
+ grid_initNodesGrid(800, 600, 40);
+
+ int i;
+ for (i = 0; i < FSegmentArray_SIZE; i++) {
+ f(fSegmentArray_pop(&a), &a);
+ }
+
+ grid_drawGrid();
+ for (i = 0; i < FSegmentArray_SIZE; i++) {
+ fsegment_display(a.seg[i]);
+ }
+}
+
+
int main() {
Vertex points[] = {
{ .x=10, .y=10 },
@@ -180,11 +492,26 @@ int main() {
};
int n = 5;
svg_start(800,600);
- carreY();
+ //carreY();
+ forceFields();
+ Vertex a = {1,1};
+ Vertex b = {4,1};
+ Vertex c = {1,2};
+ Vertex d = {4,0};
+
+ Vertex *inter = intersectionBetween(&a,&b,&c,&d);
+ if(inter == NULL)
+ fprintf(stderr,"Pas d'intersection\n");
+ else
+ fprintf(stderr,"intersection : %d %d\n",inter->x,inter->y);
+
//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];
diff --git a/roads.h b/roads.h
index 3ff55f9..08e7062 100644
--- a/roads.h
+++ b/roads.h
@@ -7,6 +7,11 @@ typedef struct Vertex {
int y;
} Vertex;
+typedef struct Segment {
+ Vertex *u;
+ Vertex *v;
+} Segment;
+
typedef Vertex Polygon;
/* Cette structure définie un nœd de route. Le nœd contient la liste de toute les intersections.
@@ -14,19 +19,9 @@ typedef Vertex Polygon;
typedef struct roadNodeY {
Vertex *v;
short nbIntersec;
- struct intersectionY *intersec;
+ struct intersectionY **intersec;
} roadNodeY;
-/* Définition d'une intersection. Permet de savoir quelle route est concernée par cette intersection.
- * Elle permet également de changer la navigation por parcourir une nouvelle route.
- * */
-typedef struct intersectionY {
- roadNodeY roadId; // Premier nœd de la route qui lui sert d'identifiant.
- roadNodeY *next; // Nœd de la route juste après l'intersection.
- roadNodeY *previous; // Nœd de la route juste avant l'intersection.
- int zIndex; // Index sur l'axe z de la route.
-} intersectionY;
-
typedef struct roadPointY {
struct roadPointY *first;
struct roadPointY *next;
@@ -34,16 +29,51 @@ typedef struct roadPointY {
roadNodeY *rn;
} roadPointY;
+/* Définition d'une intersection. Permet de savoir quelle route est concernée par cette intersection.
+ * Elle permet également de changer la navigation por parcourir une nouvelle route.
+ * */
+typedef struct intersectionY {
+ roadPointY *roadId; // Premier point de la route qui lui sert d'identifiant.
+ roadNodeY *next; // Nœd de la route juste après l'intersection.
+ roadNodeY *previous; // Nœd de la route juste avant l'intersection.
+ int zIndex; // Index sur l'axe z de la route.
+} intersectionY;
+
+typedef struct cartesianCoord {
+ int x; // Coordonnées sur x.
+ int y; // Coordonnées sur y.
+} cartesianCoord;
+
+typedef struct polarCoord {
+ int angle; // Angle en degrès.
+ int length; // Norme du vecteur.
+} polarCoord;
+
+typedef struct roadSet {
+ roadPointY *roadId; // Identifiant de la route.
+ roadPointY *rpc; // Nœd courrant.
+} roadStep;
+
+
roadNodeY ****nodesGrid;
-short maxSubDivision;
-short maxNodesInGrid = 10;
-int quarterSize = 600;
+roadPointY **roadsList;
+short nbXSubDivision;
+short nbYSubDivision;
+short maxSegmentSize;
+short maxNodesInGrid = 16;
+int quarterWidth;
+int quarterHeight;
int toX(Vertex*);
int toY(Vertex*);
-void grid_initNodesGrid(int size);
+void grid_initNodesGrid(int w, int h, int maxSegmentSize);
short grid_insertRoadNode(roadNodeY *rn);
-void addRoadNode(roadPointY *rp, roadNodeY *rn);
+roadStep* addRoadNode(roadPointY *rp, roadPointY *rpc, roadNodeY *rn);
int distBetween(Vertex *v, Vertex *u);
roadNodeY** grid_getNearNodes(Vertex *v);
+roadNodeY** grid_getNearNodes2(int x, int y);
roadNodeY* grid_getNearestRoadNode(Vertex *v);
+void grid_drawGrid();
+cartesianCoord* ptc(Vertex *origin, short angle, short length);
+polarCoord* ctp(Vertex *origin, Vertex *end);
+Segment** grid_getNearSegments(int x, int y);
diff --git a/roads.md b/roads.md
index 01f39ce..a6db3b3 100644
--- a/roads.md
+++ b/roads.md
@@ -158,22 +158,40 @@ différentes, puis transformer cette grille.
Algo champs de force
====================
-* On choisit un certain nombre de champs de force
- sur le quartier à subdiviser (centre, rayon,
- type = fonction(x,y,vecteur en cours)).
-* On a un champ de force par défaut qui s'applique
- sur toute la zone.
-* On part d'un point avec un vecteur aléatoire.
-* On demande à fonction(x,y,vecteur) la direction
- à prendre et la longueur à suivre. La fonction
- peut renvoyer plusieurs directions/longueurs à
- prendre pour faire un split.
-* Quand le segment donné par fonction s'intersecte
- avec un autre segment, on s'arrête là, et quand
- il y a un point suffisemment proche, on peut s'y
- raccrocher avec une certaine probabilité.
-* Quand on a plusieurs routes en cours de
- construction en parallèle (split), on les met
- dans une file d'attente round-robin, et on sort
- à chaque fois la tête de liste pour la faire
- avancer, puis on la remet à la fin.
+* 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`.
+* Initialiser `fifo` à vide.
+* Choisir un point de départ aléatoire, une direction aléatoire, et
+ insérer `(x,y,vecteur,0)` dans `fifo`.
+* Tant qu'on n'a pas suffisemment créé de routes :
+ * Prendre le point `(x,y,vecteur,n)` en tête de `fifo`.
+ * new = f(x,y,vecteur,n).
+ * Si new != NULL, tracer le segment `(x,y)--(new)`.
+ * insérer `(x,y,vecteur,n+1)` dans `fifo` si new dit que n+1 existe.
+ * insérer `(new,(x,y)--(new),0) dans `fifo`.
+
+Représentation simpliste des segments et routes
+===============================================
+
+* Dans chaque vertex, avoir un pointeur vers un des segments auxquels
+ il appartient.
+* Dans chaque segment, avoir un pointeur vers le segment de même
+ origine suivant dans le sens des aiguilles d'une montre.
+* Dans chaque segment, avoir un pointeur vers le segment de même
+ extrémité suivant dans le sens des aiguilles d'une montre.
+
+Algorithme de maintien des polygones
+====================================
+
+* Partir du périmètre du polygone de base.
+* Lorsqu'on ajoute un segment partant d'un point de ce périmètre,
+ étendre ce périmètre pour qu'il fasse l'aller-retour sur le segment.
+* Lorsqu'on ajoute un segment reliant deux points existants du
+ périmètre, séparer le périmètre en deux : le périmètre passant par
+ le côté gauche du segment, et celui passant par le côté droit du
+ segment.
+* TODO : gestion possible des « trous » ? (càd quand on ajoute un
+ segment qui n'est pas relié au périmètre). Serait pratique pour
+ pouvoir ajouter certains gros bâtiments avant la création des
+ routes.
diff --git a/terrain.md b/terrain.md
new file mode 100644
index 0000000..b486b0a
--- /dev/null
+++ b/terrain.md
@@ -0,0 +1,40 @@
+Liens
+-----
+
+* [Différents algos](http://www.sluniverse.com/php/vb/project-development/34994-automatically-generated-terrain-map.html) : Ridged Perlin Noise, Hills Algorithm, Craters, Erosion.
+* [Plein d'algos](http://planetgenesis.sourceforge.net/docs15/noise/noise.html#tileworley) dont plusieurs basés sur une sorte de voronoi donc à priori trop lents.
+
+Perlin noise
+------------
+
+Ridged Perlin Noise
+-------------------
+
+[Démo de Ridged Perlin Noise)(http://www.inear.se/2010/04/ridged-perlin-noise/)
+
+ // Fait des crêtes de montagnes ou vallées.
+ abs(perlinNoise());
+
+Hills Algorithm
+---------------
+
+Inverse de craters : on ajoute plein de cercles :
+
+ repeat 1000 times :
+ r=random();
+ cx=random();
+ cy=random();
+ terrain[x][y] += r**2 + ((x-cx)**2 – (y-cy)**2)
+
+Craters
+-------
+
+Soustraire des cercles (profondeur = f(distance au centre)) au terrain
+existant.
+Ou : générer un terrain nu, et soustraire plein de cercles aléatoirs.
+
+Erosion
+-------
+
+Modélisation correcte : trop lent. À la place, outil "courbes" de gimp.
+