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. +