triangulate.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <math.h>
6 
63 #include <vector> // Include STL vector class.
64 
65 #include "triangulate.h"
66 
67 
68 namespace ConvexDecomposition
69 {
70 
71 
72 class Vec2d
73 {
74 public:
75  Vec2d(const double *v)
76  {
77  mX = v[0];
78  mY = v[1];
79  }
80  Vec2d(double x,double y)
81  {
82  Set(x,y);
83  };
84  double GetX(void) const { return mX; };
85  double GetY(void) const { return mY; };
86 
87  void Set(double x,double y)
88  {
89  mX = x;
90  mY = y;
91  };
92 
93 private:
94  double mX;
95  double mY;
96 };// Typedef an STL vector of vertices which are used to represent
97 // a polygon/contour and a series of triangles.
98 
99 typedef std::vector< Vec2d > Vec2dVector;
100 
101 static bool Process(const Vec2dVector &contour,Vec2dVector &result); // compute area of a contour/polygon
102 static double Area(const Vec2dVector &contour); // decide if point Px/Py is inside triangle defined by (Ax,Ay) (Bx,By) (Cx,Cy)
103 static bool InsideTriangle(double Ax, double Ay,double Bx, double By,double Cx, double Cy,double Px, double Py);
104 static bool Snip(const Vec2dVector &contour,int u,int v,int w,int n,int *V);
105 
106 static const double EPSILON=0.0000000001f;
107 
108 double Area(const Vec2dVector &contour)
109 {
110  int n = contour.size();
111  double A=0.0f;
112  for(int p=n-1,q=0; q<n; p=q++)
113  {
114  A+= contour[p].GetX()*contour[q].GetY() - contour[q].GetX()*contour[p].GetY();
115  }
116  return A*0.5f;
117 }
118 /*
119  InsideTriangle decides if a point P is Inside of the triangle
120  defined by A, B, C.
121 */
122 bool InsideTriangle(double Ax, double Ay,double Bx, double By,double Cx, double Cy,double Px, double Py)
123 {
124  double ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
125  double cCROSSap, bCROSScp, aCROSSbp; ax = Cx - Bx; ay = Cy - By;
126  bx = Ax - Cx; by = Ay - Cy;
127  cx = Bx - Ax; cy = By - Ay;
128  apx= Px - Ax; apy= Py - Ay;
129  bpx= Px - Bx; bpy= Py - By;
130  cpx= Px - Cx; cpy= Py - Cy; aCROSSbp = ax*bpy - ay*bpx;
131  cCROSSap = cx*apy - cy*apx;
132  bCROSScp = bx*cpy - by*cpx; return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
133 };
134 
135 bool Snip(const Vec2dVector &contour,int u,int v,int w,int n,int *V)
136 {
137  int p;
138  double Ax, Ay, Bx, By, Cx, Cy, Px, Py;
139  Ax = contour[V[u]].GetX();
140  Ay = contour[V[u]].GetY();
141  Bx = contour[V[v]].GetX();
142  By = contour[V[v]].GetY();
143  Cx = contour[V[w]].GetX();
144  Cy = contour[V[w]].GetY();
145  if ( EPSILON > (((Bx-Ax)*(Cy-Ay)) - ((By-Ay)*(Cx-Ax))) ) return false; for (p=0;p<n;p++)
146  {
147  if( (p == u) || (p == v) || (p == w) ) continue;
148  Px = contour[V[p]].GetX();
149  Py = contour[V[p]].GetY();
150  if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) return false;
151  } return true;
152 }
153 
154 bool Process(const Vec2dVector &contour,Vec2dVector &result)
155 {
156  /* allocate and initialize list of Vertices in polygon */
157  int n = contour.size();
158  if ( n < 3 ) return false; int *V = new int[n]; /* we want a counter-clockwise polygon in V */ if ( 0.0f < Area(contour) )
159  for (int v=0; v<n; v++) V[v] = v;
160  else
161  for(int v=0; v<n; v++) V[v] = (n-1)-v; int nv = n; /* remove nv-2 Vertices, creating 1 triangle every time */
162 
163  int count = 2*nv; /* error detection */
164 
165  for(int m=0, v=nv-1; nv>2; )
166  {
167  /* if we loop, it is probably a non-simple polygon */
168  if (0 >= (count--))
169  {
170  //** Triangulate: ERROR - probable bad polygon!
171  return false;
172  } /* three consecutive vertices in current polygon, <u,v,w> */
173 
174  int u = v ;
175  if (nv <= u) u = 0; /* previous */
176  v = u+1; if (nv <= v) v = 0; /* new v */
177  int w = v+1;
178  if (nv <= w) w = 0; /* next */
179 
180  if ( Snip(contour,u,v,w,nv,V) )
181  {
182  int a,b,c,s,t; /* true names of the vertices */
183 
184  a = V[u];
185  b = V[v];
186  c = V[w]; /* output Triangle */
187 
188  result.push_back( contour[a] );
189  result.push_back( contour[b] );
190  result.push_back( contour[c] );
191 
192  m++; /* remove v from remaining polygon */
193  for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--; /* resest error detection counter */
194  count = 2*nv;
195  }
196 
197  }
198  delete V;
199  return true;
200 }
201 
202 
203 unsigned int triangulate3d(unsigned int pcount, // number of points in the polygon
204  const double *vertices, // array of 3d vertices.
205  double *triangles, // memory to store output triangles
206  unsigned int maxTri, // maximum triangles we are allowed to output.
207  const double *plane)
208 
209 {
210  unsigned int ret = 0;
211 
212  FILE *fph = fopen("debug.obj", "wb");
213  if ( fph )
214  {
215  fprintf(fph,"v 10 10 0\r\n");
216  for (unsigned int i=0; i<pcount; i++)
217  {
218  fprintf(fph,"v %f %f %f\r\n", vertices[i*3+0], vertices[i*3+1], vertices[i*3+2]);
219  }
220  for (unsigned int i=0; i<pcount; i++)
221  {
222  unsigned int next = i+1;
223  if ( next == pcount ) next = 0;
224  fprintf(fph,"f %d %d %d\r\n", i+2, 1, next+2 );
225  }
226  fclose(fph);
227  }
228 
229  if ( pcount >= 3 )
230  {
231  double normal[3];
232 
233  normal[0] = plane[0];
234  normal[1] = plane[1];
235  normal[2] = plane[2];
236  double D = plane[3];
237 
238  unsigned int i0 = 0;
239  unsigned int i1 = 1;
240  unsigned int i2 = 2;
241  unsigned int axis = 0;
242 
243 
244  // find the dominant axis.
245  double dx = fabs(normal[0]);
246  double dy = fabs(normal[1]);
247  double dz = fabs(normal[2]);
248 
249  if ( dx > dy && dx > dz )
250  {
251  axis = 0;
252  i0 = 1;
253  i1 = 2;
254  i2 = 0;
255  }
256  else if ( dy > dx && dy > dz )
257  {
258  i0 = 0;
259  i1 = 2;
260  i2 = 1;
261  axis = 1;
262  }
263  else if ( dz > dx && dz > dy )
264  {
265  i0 = 0;
266  i1 = 1;
267  i2 = 2;
268  axis = 2;
269  }
270 
271  double *ptemp = new double[pcount*2];
272  double *ptri = new double[maxTri*2*3];
273  const double *source = vertices;
274  double *dest = ptemp;
275 
276  for (unsigned int i=0; i<pcount; i++)
277  {
278 
279  dest[0] = source[i0];
280  dest[1] = source[i1];
281 
282  dest+=2;
283  source+=3;
284  }
285 
286  ret = triangulate2d(pcount, ptemp, ptri, maxTri );
287 
288  // ok..now we have to copy it back and project the 3d component.
289  if ( ret )
290  {
291  const double *source = ptri;
292  double *dest = triangles;
293 
294  double inverseZ = -1.0f / normal[i2];
295 
296  for (unsigned int i=0; i<ret*3; i++)
297  {
298 
299  dest[i0] = source[0];
300  dest[i1] = source[1];
301 
302  dest[i2] = (normal[i0]*source[0] + normal[i1]*source[1] + D ) * inverseZ; // solve for projected component
303 
304  dest+=3;
305  source+=2;
306  }
307 
308 
309  if ( 1 )
310  {
311  FILE *fph = fopen("test.obj","wb");
312  const double *source = triangles;
313  for (unsigned int i=0; i<ret*3; i++)
314  {
315  fprintf(fph,"v %f %f %f\r\n", source[0], source[1], source[2] );
316  source+=3;
317  }
318  int index = 1;
319  for (unsigned int i=0; i<ret; i++)
320  {
321  fprintf(fph,"f %d %d %d\r\n", index, index+1, index+2 );
322  index+=3;
323  }
324  fclose(fph);
325  }
326  }
327 
328  delete ptri;
329  delete ptemp;
330 
331  }
332 
333  return ret;
334 }
335 
336 unsigned int triangulate3d(unsigned int pcount, // number of points in the polygon
337  const unsigned int *indices, // polygon points using indices
338  const double *vertices, // base address for array indexing
339  double *triangles, // buffer to store output 3d triangles.
340  unsigned int maxTri, // maximum triangles we can output.
341  const double *plane)
342 {
343  unsigned int ret = 0;
344 
345  if ( pcount )
346  {
347  // copy the indexed polygon out as a flat array of vertices.
348  double *ptemp = new double[pcount*3];
349  double *dest = ptemp;
350 
351  for (unsigned int i=0; i<pcount; i++)
352  {
353  unsigned int index = indices[i];
354  const double *source = &vertices[index*3];
355  *dest++ = *source++;
356  *dest++ = *source++;
357  *dest++ = *source++;
358  }
359 
360  ret = triangulate3d(pcount,ptemp,triangles,maxTri,plane);
361 
362  delete ptemp;
363  }
364 
365  return ret;
366 }
367 
368 unsigned int triangulate2d(unsigned int pcount, // number of points in the polygon
369  const double *vertices, // address of input points (2d)
370  double *triangles, // destination buffer for output triangles.
371  unsigned int maxTri) // maximum number of triangles we can store.
372 {
373  unsigned int ret = 0;
374 
375  const double *source = vertices;
376  Vec2dVector vlist;
377 
378  for (unsigned int i=0; i<pcount; i++)
379  {
380  Vec2d v(source);
381  vlist.push_back(v);
382  source+=2;
383  }
384 
385  Vec2dVector result;
386 
387  bool ok = Process(vlist,result);
388  if ( ok )
389  {
390  ret = result.size()/3;
391  if ( ret < maxTri )
392  {
393  double *dest = triangles;
394  for (unsigned int i=0; i<ret*3; i++)
395  {
396  dest[0] = result[i].GetX();
397  dest[1] = result[i].GetY();
398  dest+=2;
399  }
400  }
401  else
402  {
403  ret = 0;
404  }
405  }
406 
407  return ret;
408 }
409 
410 }; // end of namespace
triangulate.h
ConvexDecomposition::Vec2d::Vec2d
Vec2d(const double *v)
Definition: triangulate.cpp:75
ConvexDecomposition::Vec2dVector
std::vector< Vec2d > Vec2dVector
Definition: triangulate.cpp:99
ConvexDecomposition::Process
static bool Process(const Vec2dVector &contour, Vec2dVector &result)
Definition: triangulate.cpp:154
ConvexDecomposition
Definition: bestfit.cpp:75
ConvexDecomposition::Vec2d::mX
double mX
Definition: triangulate.cpp:91
ConvexDecomposition::Snip
static bool Snip(const Vec2dVector &contour, int u, int v, int w, int n, int *V)
Definition: triangulate.cpp:135
ConvexDecomposition::Vec2d::Set
void Set(double x, double y)
Definition: triangulate.cpp:87
ConvexDecomposition::triangulate3d
unsigned int triangulate3d(unsigned int pcount, const double *vertices, double *triangles, unsigned int maxTri, const double *plane)
Definition: triangulate.cpp:203
ConvexDecomposition::Vec2d::GetY
double GetY(void) const
Definition: triangulate.cpp:85
ConvexDecomposition::triangulate2d
unsigned int triangulate2d(unsigned int pcount, const double *vertices, double *triangles, unsigned int maxTri)
Definition: triangulate.cpp:368
ConvexDecomposition::EPSILON
static const double EPSILON
Definition: triangulate.cpp:106
ConvexDecomposition::Vec2d
Definition: triangulate.cpp:72
ConvexDecomposition::Vec2d::GetX
double GetX(void) const
Definition: triangulate.cpp:84
ConvexDecomposition::InsideTriangle
static bool InsideTriangle(double Ax, double Ay, double Bx, double By, double Cx, double Cy, double Px, double Py)
Definition: triangulate.cpp:122
ConvexDecomposition::plane
Definition: planetri.cpp:182
ConvexDecomposition::Area
static double Area(const Vec2dVector &contour)
Definition: triangulate.cpp:108
ConvexDecomposition::Vec2d::mY
double mY
Definition: triangulate.cpp:95
ConvexDecomposition::Vec2d::Vec2d
Vec2d(double x, double y)
Definition: triangulate.cpp:80


convex_decomposition
Author(s): John W. Ratcliff
autogenerated on Wed Mar 2 2022 00:04:59