#include <iostream> #include <fstream> #include <math.h> // pour cos() et sin() #define PI 3.14159265 #include <stdlib.h> using namespace std; /*******************************************************************/ // Structure point /*******************************************************************/ typedef struct { int abscisse; int ordonnee; } point; /*******************************************************************/ // Structure triangle /*******************************************************************/ //structure triangle, pour une variable triangle T, ses sommets sont accessibles par //T.a, T.b et T.c typedef struct { int a; int b; int c; } triangle; /*******************************************************************/ //Petites fonctions arithmetiques ou geometriques /*******************************************************************/ int det(point p0, point p1, point p2, point p3){ //Renvoie le determinant de p0p1,p2p3 return (p1.abscisse-p0.abscisse)*(p3.ordonnee-p2.ordonnee)-(p1.ordonnee-p0.ordonnee)*(p3.abscisse-p2.abscisse); } //------------------------------ int ProduitScalaire(point p0, point p1, point p2,point p3){ //Renvoie le produit scalaire de p0p1,p2p3 return (p1.abscisse-p0.abscisse)*(p3.abscisse-p2.abscisse)+(p1.ordonnee-p0.ordonnee)*(p3.ordonnee-p2.ordonnee); } //------------------------------ int Carre(int x){ return x*x;} //----------------------------- int NormeAuCarre(point p1,point p2){ //Calcul la norme au carre de p1p2 return Carre(p1.ordonnee-p2.ordonnee)+Carre(p1.abscisse-p2.abscisse); } //----------------------------- float RayonCercleCirconscrit(point A, point B, point C){ //Renvoie le rayon du cercle circonscrit a ABC float O[2]; //le centre int xa=A.abscisse; int ya=A.ordonnee; int xb=B.abscisse; int yb=B.ordonnee; int xc=C.abscisse; int yc=C.ordonnee; // // A COMPLETER // } //------------------------------ bool EstADroite(point A, point B, point C){ //Renvoie vrai si C est strictement a droite de (AB) oriente de A vers B. if(det(A,B,A,C)>=0){return false;} else{return true;} } /*******************************************************************/ //Fonctions d'affichage /*******************************************************************/ void AffichagePoints(int n, point sommet[]){ //Affichage de n points dont les coordonnees sont dans sommet[n][2] //Un fichier Points.ps est cree, visualisable avec un afficheur postscript (ex: ggv, kghostview) ofstream output; output.open("Points.ps");// output << "%!PS-Adobe-3.0" << endl; output << endl; for(int i=0;i<n;i++){ output << sommet[i].abscisse << " " << sommet[i].ordonnee << " 2 0 360 arc" <<endl; output << "0 setgray" <<endl; output << "fill" <<endl; output << "stroke" << endl; output << endl; } output << "showpage"; output << endl; output.close(); } //------------------------------------- void AffichageTriangulation(int n, point sommet[], int t, triangle T[]){ //Affichage des n points du plan dont les coordonnees sont dans sommet[][2] et d'une triangulation //en t triangles stockes dans T, tableau de taille t. ofstream output; output.open("AlphaShape.ps"); output << "%!PS-Adobe-3.0" << endl; output << endl; for(int i=0;i<n;i++){ output << sommet[i].abscisse << " " << sommet[i].ordonnee << " 2 0 360 arc" <<endl; output << "0 setgray" <<endl; output << "fill" <<endl; output << "stroke" << endl; output << endl; } output << endl; for(int i=0;i<t;i++){ output << sommet[T[i].a].abscisse << " " << sommet[T[i].a].ordonnee << " moveto" << endl; output << sommet[T[i].b].abscisse << " " << sommet[T[i].b].ordonnee << " lineto" << endl; output << sommet[T[i].b].abscisse << " " << sommet[T[i].b].ordonnee << " moveto" << endl; output << sommet[T[i].c].abscisse << " " << sommet[T[i].c].ordonnee << " lineto" << endl; output << sommet[T[i].c].abscisse << " " << sommet[T[i].c].ordonnee << " moveto" << endl; output << sommet[T[i].a].abscisse << " " << sommet[T[i].a].ordonnee << " lineto" << endl; output << "stroke" << endl; output << endl; } output << "showpage"; output << endl; output.close(); } /*******************************************************************/ //Reperer un point par rapport au cercle circonscrit a un triangle /*******************************************************************/ bool MemeCote(point A, point B, point C, point D){ //Renvoie vrai si C et D sont du meme cote de (AB). if((det(A,B,A,C)*det(A,B,A,D))>0){return true;} else{ return false;} } //---------------------------------------- bool StrictementDansLeCercleCirconscritMemeCote(point A, point B, point C, point D){ //Renvoie vrai si D est strictement dans le cercle circonscrit de ABC. //On suppose C et D du meme cote de (AB). //Faire un test entier // // A RECUPERER OU INCLURE // } //--------------------------------------- bool StrictementDansLeCercleCirconscrit(point A, point B, point C, point D){ //Renvoie vrai si D est strictement dans le cercle circonscrit de ABC, quelquesoit sa position. // // A RECUPERER OU INCLURE // } /************************************************************************/ //Calcul d'une premiere triangulation (algo incremental par ex) /************************************************************************/ void TriLexicographique(int n, point sommet[], int t, int Tri[]){ if(t>1){ int pivot=Tri[0]; //indice du sommet pivot int d=0; // nombre de sommets a droite de min_pivot for(int i=1;i<t;i++){//On compte (on ne tient pas compte de pivot) if((sommet[Tri[0]].abscisse<sommet[Tri[i]].abscisse)|| ((sommet[Tri[0]].abscisse==sommet[Tri[i]].abscisse)&& (sommet[Tri[0]].ordonnee<sommet[Tri[i]].ordonnee))){d++;} } int Tg[t-d-1]; int Td[d]; int indice_gauche=0; //indice d'insertion dans Tg int indice_droit=0; //indice d'insertion dans Td for(int i=1;i<t;i++){ //Remplissage de Tg et Td (on ne tient pas compte de pivot) if((sommet[Tri[0]].abscisse<sommet[Tri[i]].abscisse)|| ((sommet[Tri[0]].abscisse==sommet[Tri[i]].abscisse)&& (sommet[Tri[0]].ordonnee<sommet[Tri[i]].ordonnee))){//A droite Td[indice_droit]=Tri[i]; indice_droit++;} else{//A gauche Tg[indice_gauche]=Tri[i]; indice_gauche++;}} //On trie Td et Tg if(d>0){TriLexicographique(n,sommet,d,Td);} if(t-d-1>0){TriLexicographique(n,sommet,t-d-1,Tg);} //Fusion dans Tri for(int i=0;i<t;i++){ if(i<t-d-1){Tri[i]=Tg[i];} if(i==t-d-1){Tri[i]=pivot;} if(i>t-d-1){Tri[i]=Td[i-t+d];} } } } //---------------------------------------- int TriangulIncrementale(int n, point sommet[], int tri[], triangle T[]){ // // A RECUPERER OU INCLURE // } /*******************************************************************/ //Triangulation de Delaunay /*******************************************************************/ bool TrianglesAdjacents(triangle s, triangle t){ //renvoie vrai si s et t ont une arete en commun int sommet_commun=0; if((s.a==t.a)||(s.a==t.b)||(s.a==t.c)){sommet_commun++;} if((s.b==t.a)||(s.b==t.b)||(s.b==t.c)){sommet_commun++;} if((s.c==t.a)||(s.c==t.b)||(s.c==t.c)){sommet_commun++;} if(sommet_commun>=2){return true;} return false; } //------------------------------------------- void TrianglesVoisins(int t, triangle T[], int voisin[][3]){ //Calcul pour chaque triangle les indices des triangles qui lui sont adjacents for(int i=0;i<t;i++){ for(int j=0;j<i;j++){ if(TrianglesAdjacents(T[i],T[j])){ int case_libre; if(voisin[i][0]==-1){case_libre=0;} else{if(voisin[i][1]==-1){case_libre=1;} else{case_libre=2;}} voisin[i][case_libre]=j; if(voisin[j][0]==-1){case_libre=0;} else{if(voisin[j][1]==-1){case_libre=1;} else{case_libre=2;}} voisin[j][case_libre]=i; } } } } //------------------------------------------- int TroisiemePoint(triangle s, triangle t){ //Renvoie l'indice du point de s qui n'est pas dans t if((s.a!=t.a)&&(s.a!=t.b)&&(s.a!=t.c)){return s.a;} if((s.b!=t.a)&&(s.b!=t.b)&&(s.b!=t.c)){return s.b;} if((s.c!=t.a)&&(s.c!=t.b)&&(s.c!=t.c)){return s.c;} return -1; } //--------------------------------------------- void Flip(int i, int j, int t, triangle T[], int voisin[][3]){ //Effectue un 'flip' entre les triangles T[i] et T[j] //t est la taille du tableau T et voisin, tableau calcule //par la fonction TrianglesVoisins, sera mis-a-jour int vieux_voisins_Ti[3]={voisin[i][0],voisin[i][1],voisin[i][2]}; int vieux_voisins_Tj[3]={voisin[j][0],voisin[j][1],voisin[j][2]}; int x=TroisiemePoint(T[i],T[j]);// On nomme les 4 sommets int y=TroisiemePoint(T[j],T[i]); int z; int w; if(T[i].a==x){z=T[i].b; w=T[i].c;} if(T[i].b==x){z=T[i].a; w=T[i].c;} if(T[i].c==x){z=T[i].a; w=T[i].b;} T[i].a=z;T[i].b=x;T[i].c=y; // mise a jour de Ti et Tj T[j].a=w;T[j].b=x;T[j].c=y; //mise a jour des voisins: A faire plus proprement... for(int i=0;i<t;i++){ voisin[i][0]=-1; voisin[i][1]=-1; voisin[i][2]=-1; } TrianglesVoisins(t,T,voisin); } //-------------------------------------------- int Delaunay(int n, point sommet[],int t, triangle T[]){ // // A RECUPERER OU INCLURE // return 0; } /*******************************************************************/ //main /*******************************************************************/ int main(){ int n=200; point sommet[200]={ {416,529},{505,438},{268,188},{188,276},{312,595},{542,411},{331,195},{483,331},{427,216},{260,241}, {137,456},{291,236},{412,291},{430,617},{192,342},{308,241},{460,265},{355,232},{537,326},{556,288}, {251,264},{537,260},{195,443},{382,596},{404,224},{542,321},{166,516},{472,256},{417,177},{411,505}, {404,166},{494,595},{502,353},{251,481},{558,467},{561,361},{480,561},{147,387},{404,248},{227,201}, {241,532},{251,472},{360,249},{552,390},{171,267},{491,502},{329,520},{168,328},{451,232},{584,446}, {345,540},{121,380},{256,307},{217,249},{435,560},{508,460},{128,464},{451,500},{363,227},{585,428}, {192,404},{152,518},{489,536},{473,500},{275,294},{459,488},{540,414},{140,364},{140,380},{350,609}, {528,433},{267,539},{422,521},{160,248},{464,518},{339,529},{472,513},{219,403},{427,288},{262,576}, {344,604},{204,320},{441,204},{281,630},{516,276},{486,379},{220,508},{510,513},{465,540},{196,454}, {260,254},{540,536},{230,280},{470,329},{313,576},{406,209},{488,425},{411,268},{488,420},{444,264}, {168,491},{427,225},{312,606},{564,411},{160,438},{212,454},{531,249},{145,360},{459,310},{225,294}, {243,539},{249,246},{556,342},{564,332},{433,494},{313,584},{483,547},{374,235},{505,257},{265,243}, {432,624},{412,228},{278,294},{456,304},{212,286},{513,300},{545,380},{222,553},{208,398},{560,464}, {401,192},{262,580},{350,568},{233,281},{331,198},{233,481},{220,564},{395,224},{328,182},{137,355}, {512,342},{510,326},{236,248},{454,248},{459,545},{152,409},{425,174},{428,617},{524,468},{454,472}, {116,379},{515,326},{352,537},{216,464},{436,179},{192,524},{424,612},{355,203},{476,366},{460,316}, {158,545},{166,406},{486,587},{198,214},{188,355},{446,190},{248,515},{528,521},{332,561},{550,473}, {227,609},{366,523},{204,262},{153,443},{371,544},{524,296},{459,614},{137,374},{465,356},{492,222}, {288,614},{347,265},{486,518},{361,217},{518,446},{180,305},{315,172},{329,201},{241,614},{198,368}, {556,316},{252,622},{212,264},{353,280},{204,267},{185,300},{515,342},{344,571},{155,513},{494,289}, }; int tri[n]; triangle T[2*n]; for(int i=0;i<n;i++){tri[i]=i;} AffichagePoints(n,sommet); TriLexicographique(n,sommet,n,tri); int t=TriangulIncrementale(n,sommet,tri,T); Delaunay(n,sommet,t,T); float rayon[t];//tableau contenant les rayons for(int i=0;i<t;i++){ rayon[i]=RayonCercleCirconscrit(sommet[T[i].a],sommet[T[i].b],sommet[T[i].c]); } AffichageTriangulation(n,sommet,t,T);//affichage de Delaunay //seuillage: triangle Taccepte[2*n];//les triangles qu'on affichera float alpha; while(1){ cout << "Valeur de alpha: "; cin >> alpha; int t_acceptes=0; int indice=0; for(int i=0;i<t;i++){ if(rayon[i]<alpha){//on accepte le triangle i t_acceptes++; Taccepte[indice].a=T[i].a; Taccepte[indice].b=T[i].b; Taccepte[indice].c=T[i].c; indice++; } } AffichageTriangulation(n,sommet,t_acceptes,Taccepte); } }