Code_TYMPAN  4.4.0
Industrial site acoustic simulation
Triangulate.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
16 #include <math.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <assert.h>
21 
22 #include "Triangulate.h"
23 
24 float Triangulate::Area(const Vector2dVector& contour)
25 {
26 
27  size_t n = contour.size();
28 
29  float A = 0.0f;
30 
31  for (size_t p = n - 1, q = 0; q < n; p = q++)
32  {
33  A += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
34  }
35  return A * 0.5f;
36 }
37 
38 /*
39  InsideTriangle decides if a point P is Inside of the triangle
40  defined by A, B, C.
41 */
42 bool Triangulate::InsideTriangle(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Px,
43  float Py)
44 
45 {
46  float ax = NAN, ay = NAN, bx = NAN, by = NAN, cx = NAN, cy = NAN, apx = NAN, apy = NAN, bpx = NAN,
47  bpy = NAN, cpx = NAN, cpy = NAN;
48  float cCROSSap = NAN, bCROSScp = NAN, aCROSSbp = NAN;
49 
50  ax = Cx - Bx;
51  ay = Cy - By;
52  bx = Ax - Cx;
53  by = Ay - Cy;
54  cx = Bx - Ax;
55  cy = By - Ay;
56  apx = Px - Ax;
57  apy = Py - Ay;
58  bpx = Px - Bx;
59  bpy = Py - By;
60  cpx = Px - Cx;
61  cpy = Py - Cy;
62 
63  aCROSSbp = ax * bpy - ay * bpx;
64  cCROSSap = cx * apy - cy * apx;
65  bCROSScp = bx * cpy - by * cpx;
66 
67  return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
68 };
69 
70 bool Triangulate::Snip(const Vector2dVector& contour, int u, int v, int w, int n, int* V)
71 {
72  int p = 0;
73  float Ax = NAN, Ay = NAN, Bx = NAN, By = NAN, Cx = NAN, Cy = NAN, Px = NAN, Py = NAN;
74 
75  Ax = contour[V[u]].x;
76  Ay = contour[V[u]].y;
77 
78  Bx = contour[V[v]].x;
79  By = contour[V[v]].y;
80 
81  Cx = contour[V[w]].x;
82  Cy = contour[V[w]].y;
83 
84  if (EPSILON_6 > (((Bx - Ax) * (Cy - Ay)) - ((By - Ay) * (Cx - Ax))))
85  {
86  return false;
87  }
88 
89  for (p = 0; p < n; p++)
90  {
91  if ((p == u) || (p == v) || (p == w))
92  {
93  continue;
94  }
95  Px = contour[V[p]].x;
96  Py = contour[V[p]].y;
97  if (InsideTriangle(Ax, Ay, Bx, By, Cx, Cy, Px, Py))
98  {
99  return false;
100  }
101  }
102 
103  return true;
104 }
105 
107 {
108  /* allocate and initialize list of Vertices in polygon */
109 
110  size_t n = contour.size();
111  if (n < 3)
112  {
113  return false;
114  }
115 
116  int* V = new int[n];
117 
118  /* we want a counter-clockwise polygon in V */
119 
120  if (0.0f < Area(contour))
121  for (int v = 0; v < n; v++)
122  {
123  V[v] = v;
124  }
125  else
126  for (int v = 0; v < n; v++)
127  {
128  V[v] = (static_cast<int>(n) - 1) - v;
129  }
130 
131  int nv = static_cast<int>(n);
132 
133  /* remove nv-2 Vertices, creating 1 triangle every time */
134  int count = 2 * nv; /* error detection */
135 
136  for (int m = 0, v = nv - 1; nv > 2;)
137  {
138  /* if we loop, it is probably a non-simple polygon */
139  if (0 >= (count--))
140  {
141  //** Triangulate: ERROR - probable bad polygon!
142  return false;
143  }
144 
145  /* three consecutive vertices in current polygon, <u,v,w> */
146  int u = v;
147  if (nv <= u)
148  {
149  u = 0;
150  } /* previous */
151  v = u + 1;
152  if (nv <= v)
153  {
154  v = 0;
155  } /* new v */
156  int w = v + 1;
157  if (nv <= w)
158  {
159  w = 0;
160  } /* next */
161 
162  if (Snip(contour, u, v, w, nv, V))
163  {
164  int a = 0, b = 0, c = 0, s = 0, t = 0;
165 
166  /* true names of the vertices */
167  a = V[u];
168  b = V[v];
169  c = V[w];
170 
171  /* output Triangle */
172  result.push_back(contour[a]);
173  result.push_back(contour[b]);
174  result.push_back(contour[c]);
175 
176  m++;
177 
178  /* remove v from remaining polygon */
179  for (s = v, t = v + 1; t < nv; s++, t++)
180  {
181  V[s] = V[t];
182  }
183  nv--;
184 
185  /* resest error detection counter */
186  count = 2 * nv;
187  }
188  }
189 
190  delete[] V;
191 
192  return true;
193 }
#define EPSILON_6
Definition: 3d.h:39
NxReal s
Definition: NxVec3.cpp:317
NxReal c
Definition: NxVec3.cpp:317
std::vector< vec2 > Vector2dVector
Definition: Triangulate.h:40
static bool InsideTriangle(float Ax, float Ay, float Bx, float By, float Cx, float Cy, float Px, float Py)
Decide if the point (Px,Py) is inside a triangle defined by three points (Ax,Ay) (Bx,...
Definition: Triangulate.cpp:42
static float Area(const Vector2dVector &contour)
Compute and return area of a contour/polygon.
Definition: Triangulate.cpp:24
static bool Snip(const Vector2dVector &contour, int u, int v, int w, int n, int *V)
Definition: Triangulate.cpp:70
static bool Process(const Vector2dVector &contour, Vector2dVector &result)
Triangulate a contour/polygon, places results in STL vector as series of triangles.