$search
00001 #include <stdio.h> 00002 #include <stdlib.h> 00003 #include <string.h> 00004 #include <assert.h> 00005 00006 #include "bmtk/triangulate.h" 00007 00008 static const float EPSILON=0.0000000001f; 00009 00010 namespace bmtk { 00011 00012 float Triangulate::Area(const Vector2dVector &contour) 00013 { 00014 00015 int n = contour.size(); 00016 00017 float A=0.0f; 00018 00019 for(int p=n-1,q=0; q<n; p=q++) 00020 { 00021 A+= contour[p].GetX()*contour[q].GetY() - 00022 contour[q].GetX()*contour[p].GetY(); 00023 } 00024 return A*0.5f; 00025 } 00026 00027 /* 00028 InsideTriangle decides if a point P is Inside of the triangle 00029 defined by A, B, C. 00030 */ 00031 bool Triangulate::InsideTriangle(float Ax, float Ay, 00032 float Bx, float By, 00033 float Cx, float Cy, 00034 float Px, float Py) 00035 00036 { 00037 float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; 00038 float cCROSSap, bCROSScp, aCROSSbp; 00039 00040 ax = Cx - Bx; ay = Cy - By; 00041 bx = Ax - Cx; by = Ay - Cy; 00042 cx = Bx - Ax; cy = By - Ay; 00043 apx= Px - Ax; apy= Py - Ay; 00044 bpx= Px - Bx; bpy= Py - By; 00045 cpx= Px - Cx; cpy= Py - Cy; 00046 00047 aCROSSbp = ax*bpy - ay*bpx; 00048 cCROSSap = cx*apy - cy*apx; 00049 bCROSScp = bx*cpy - by*cpx; 00050 00051 return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); 00052 }; 00053 00054 bool Triangulate::Snip(const Vector2dVector &contour, 00055 int u,int v,int w,int n,int *V) 00056 { 00057 int p; 00058 float Ax, Ay, Bx, By, Cx, Cy, Px, Py; 00059 00060 Ax = contour[V[u]].GetX(); 00061 Ay = contour[V[u]].GetY(); 00062 00063 Bx = contour[V[v]].GetX(); 00064 By = contour[V[v]].GetY(); 00065 00066 Cx = contour[V[w]].GetX(); 00067 Cy = contour[V[w]].GetY(); 00068 00069 if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false; 00070 00071 for (p=0;p<n;p++) 00072 { 00073 if( (p == u) || (p == v) || (p == w) ) continue; 00074 Px = contour[V[p]].GetX(); 00075 Py = contour[V[p]].GetY(); 00076 if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false; 00077 } 00078 00079 return true; 00080 } 00081 00082 bool Triangulate::Process(const Vector2dVector &contour,VertexList &result) 00083 { 00084 /* allocate and initialize list of Vertices in polygon */ 00085 00086 int n = contour.size(); 00087 if ( n < 3 ) return false; 00088 00089 int *V = new int[n]; 00090 00091 /* we want a counter-clockwise polygon in V */ 00092 00093 if ( 0.0f < Area(contour) ) 00094 for (int v=0; v<n; v++) V[v] = v; 00095 else 00096 for(int v=0; v<n; v++) V[v] = (n-1)-v; 00097 00098 int nv = n; 00099 00100 /* remove nv-2 Vertices, creating 1 triangle every time */ 00101 int count = 2*nv; /* error detection */ 00102 00103 for(int m=0, v=nv-1; nv>2; ) 00104 { 00105 /* if we loop, it is probably a non-simple polygon */ 00106 if (0 >= (count--)) 00107 { 00108 //** Triangulate: ERROR - probable bad polygon! 00109 return false; 00110 } 00111 00112 /* three consecutive vertices in current polygon, <u,v,w> */ 00113 int u = v ; if (nv <= u) u = 0; /* previous */ 00114 v = u+1; if (nv <= v) v = 0; /* new v */ 00115 int w = v+1; if (nv <= w) w = 0; /* next */ 00116 00117 if ( Snip(contour,u,v,w,nv,V) ) 00118 { 00119 int a,b,c,s,t; 00120 00121 /* true names of the vertices */ 00122 a = V[u]; b = V[v]; c = V[w]; 00123 00124 /* output Triangle */ 00125 result.push_back( a ); 00126 result.push_back( b ); 00127 result.push_back( c ); 00128 00129 m++; 00130 00131 /* remove v from remaining polygon */ 00132 for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--; 00133 00134 /* resest error detection counter */ 00135 count = 2*nv; 00136 } 00137 } 00138 00139 00140 00141 delete V; 00142 00143 return true; 00144 } 00145 00146 } // namespace bmtk