Merge branch 'master' of http://github.com/jsmaniac/2011-m2s3-city-builder
Conflicts: roads.md
This commit is contained in:
commit
5383c14458
511
roads.c
511
roads.c
|
@ -9,19 +9,65 @@ void svg_end() {
|
|||
printf("</svg>");
|
||||
}
|
||||
|
||||
void svg_line(Vertex* a, Vertex* b) {
|
||||
printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"black\" />", a->x, a->y, b->x, b->y);
|
||||
void svg_line(Vertex* a, Vertex* b, short color) {
|
||||
if(color == 0)
|
||||
printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"grey\" />", a->x, a->y, b->x, b->y);
|
||||
else if(color == 1)
|
||||
printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"#A0A000\" />", a->x, a->y, b->x, b->y);
|
||||
else if(color == 2)
|
||||
printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"blue\" />", a->x, a->y, b->x, b->y);
|
||||
else
|
||||
printf("<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke=\"black\" />", a->x, a->y, b->x, b->y);
|
||||
}
|
||||
|
||||
void svg_circle(int x, int y, int r) {
|
||||
printf("<circle cx=\"%d\" cy=\"%d\" r=\"%d\" stroke=\"black\" stroke-width=\"2\" fill=\"red\"/>",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;i<size;i++) {
|
||||
nodesGrid[i] = (roadNodeY***) malloc(sizeof(roadNodeY**)*size);
|
||||
for(j=0;j<size;j++) {
|
||||
/* 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;i<xSize;i++) {
|
||||
nodesGrid[i] = (roadNodeY***) malloc(sizeof(roadNodeY**)*ySize);
|
||||
for(j=0;j<ySize;j++) {
|
||||
nodesGrid[i][j] = (roadNodeY**) malloc(sizeof(roadNodeY*)*maxNodesInGrid);
|
||||
for(k=0;k<maxNodesInGrid;k++)
|
||||
nodesGrid[i][j][k] = NULL;
|
||||
|
@ -54,6 +148,55 @@ void grid_initNodesGrid(int size) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Détermine si il existe une intersection entre deux segments de droite. Dans le cas
|
||||
* ou une intersection existe les coordonnées du point d'intersection sont retournées.
|
||||
* Dans le cas contraire la fonction retourne NULL.
|
||||
* @param Vertex *va : Point de départ du premier segment.
|
||||
* @param Vertex *vb : Point d'arrivé du premier segment.
|
||||
* @param Vertex *ua : Point de départ du second segment.
|
||||
* @param Vertex *vb : Point d'arrivé du second segment.
|
||||
* @return Vertex* : Coordonnées du point d'intersection si il existe, sinon NULL.
|
||||
*/
|
||||
Vertex* intersectionBetween(Vertex *va, Vertex *vb, Vertex *ua, Vertex *ub) {
|
||||
Vertex *inter = (Vertex*) malloc(sizeof(Vertex));
|
||||
float m, k; // Coordonnées de l'intersection des vecteurs sur les droites.
|
||||
int Ix, Iy, Jx, Jy; // Vecteur I et J corespondant au segment v et u;
|
||||
|
||||
Ix = vb->x - 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;i<nbXSubDivision-1;i++)
|
||||
for(j=0;j<nbYSubDivision-1;j++) {
|
||||
Vertex v = {i*maxSegmentSize,j*maxSegmentSize};
|
||||
Vertex u = {(i+1)*maxSegmentSize,j*maxSegmentSize};
|
||||
svg_line(&v,&u,0);
|
||||
u.x = i*maxSegmentSize;
|
||||
u.y = (j+1)*maxSegmentSize;
|
||||
svg_line(&v,&u,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
short grid_insertRoadNode(roadNodeY *rn) {
|
||||
if(rn == NULL || rn->v == 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<x+2; i++) {
|
||||
for(j=y-1; j<y+2; j++,count++) {
|
||||
if(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<x+2;i++) {
|
||||
for(j=y-1;j<y+2;j++) {
|
||||
if(x >= 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;l<tmpnr->nbIntersec;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("<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\" />", 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];
|
||||
|
|
62
roads.h
62
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);
|
||||
|
|
56
roads.md
56
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.
|
||||
|
|
40
terrain.md
Normal file
40
terrain.md
Normal file
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user