00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "triangulator.h"
00038 #include "common/math/build_basis.h"
00039 #include "common/math/point2.h"
00040 #include "common/math/point3.h"
00041 #include "common/math/real.h"
00042 #include "common/math/vector2.h"
00043 #include "common/math/vector3.h"
00044
00045 #include <cassert>
00046 #include <list>
00047
00048 using namespace sheep;
00049 using namespace std;
00050
00051 namespace {
00052
00053
00054 Vector3 ComputeTrianglePlane3(const Point3 &v0,
00055 const Point3 &v1,
00056 const Point3 &v2)
00057 {
00058 const Vector3 e0 = v1 - v0;
00059 const Vector3 e1 = v2 - v0;
00060
00061 assert(e0.SquareNorm() > 0.0);
00062 assert(e1.SquareNorm() > 0.0);
00063
00064 return e0 ^ e1;
00065 }
00066
00067
00068 Real ComputePolygonArea2(vector<Point2> input) {
00069 const int n = input.size();
00070
00071
00072 input.push_back(input[0]);
00073 input.push_back(input[1]);
00074
00075 Real area = 0.0;
00076
00077 for(int i = 1, j = 2, k = 0; i <= n; ++i, ++j, ++k) {
00078 area += input[i].m_x * (input[j].m_y - input[k].m_y);
00079 }
00080
00081 return 0.5 * area;
00082 }
00083
00084
00085
00086 Real ComputePolygonNormal3(vector<Point3> input, Vector3 *normal) {
00087 assert(normal);
00088
00089 const int n = input.size();
00090
00091
00092 input.push_back(input[0]);
00093 input.push_back(input[1]);
00094
00095 normal->m_x = normal->m_y = normal->m_z = 0.0;
00096
00097
00098 for(int i = 1, j = 2, k = 0; i <= n; ++i, ++j, ++k) {
00099 normal->m_x += input[i].m_y * (input[j].m_z - input[k].m_z);
00100 normal->m_y += input[i].m_z * (input[j].m_x - input[k].m_x);
00101 normal->m_z += input[i].m_x * (input[j].m_y - input[k].m_y);
00102 }
00103
00104
00105 const Real area = normal->Norm();
00106
00107
00108 assert(area > 0.0);
00109 *normal /= area;
00110
00111 return area;
00112 }
00113
00114
00115 void ProjectPlanarPolygon3(const vector<Point3> &input,
00116 vector<Point2> *output)
00117 {
00118 assert(input.size() >= 3);
00119 assert(output);
00120
00121
00122 Vector3 n;
00123 ComputePolygonNormal3(input, &n);
00124
00125
00126 Vector3 u, v;
00127 build_basis(n, &u, &v);
00128
00129
00130 for(vector<Point3>::const_iterator i = input.begin(), e = input.end(); i != e; ++i) {
00131 const Point3 &p = *i;
00132 output->push_back(Point2(p * u, p * v));
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 }
00180
00181 enum Orientation { CCW, CW };
00182
00183
00184 Orientation ComputeTriangleOrientation2(const Point2 &v0,
00185 const Point2 &v1,
00186 const Point2 &v2)
00187 {
00188 const Vector2 v0v1 = v1 - v0;
00189 const Vector2 v0v2 = v2 - v0;
00190 const Real cp = v0v1.m_x * v0v2.m_y - v0v2.m_x * v0v1.m_y;
00191
00192
00193
00194
00195 return cp > 0.0 ? CCW : CW;
00196 }
00197
00198
00199 Orientation ComputePolygonOrientation2(const vector<Point2> &vertices) {
00200 assert(vertices.size() >= 3);
00201
00202 const int n = vertices.size();
00203
00204
00205 int rmin = 0;
00206 Real xmin = vertices[0].m_x;
00207 Real ymin = vertices[0].m_y;
00208
00209 for(int i = 1; i < n; ++i) {
00210 const Point2 &v = vertices[i];
00211
00212 if(v.m_y > ymin)
00213 continue;
00214
00215 if(v.m_y == ymin) {
00216 if(v.m_x < xmin)
00217 continue;
00218 }
00219
00220 rmin = i;
00221 xmin = v.m_x;
00222 ymin = v.m_y;
00223 }
00224
00225 if(rmin == 0)
00226 return ComputeTriangleOrientation2(
00227 vertices[n - 1],
00228 vertices[0],
00229 vertices[1]);
00230 else if(rmin == n - 1)
00231 return ComputeTriangleOrientation2(
00232 vertices[n - 2],
00233 vertices[n - 1],
00234 vertices[0]);
00235 else
00236 return ComputeTriangleOrientation2(
00237 vertices[rmin - 1],
00238 vertices[rmin],
00239 vertices[rmin + 1]);
00240 }
00241
00242
00243
00244 bool IsPointInsideTriangle2(const Point2 &v0,
00245 const Point2 &v1,
00246 const Point2 &v2,
00247 const Point2 &p)
00248 {
00249 assert(ComputeTriangleOrientation2(v0, v1, v2) == CCW);
00250
00251 const Vector2 v0p = p - v0;
00252 const Vector2 v0v1 = v1 - v0;
00253
00254 if(v0p.m_x * v0v1.m_y - v0v1.m_x * v0p.m_y > 0.0)
00255 return false;
00256
00257 const Vector2 v1p = p - v1;
00258 const Vector2 v1v2 = v2 - v1;
00259
00260 if(v1p.m_x * v1v2.m_y - v1v2.m_x * v1p.m_y > 0.0)
00261 return false;
00262
00263 const Vector2 v2p = p - v2;
00264 const Vector2 v2v0 = v0 - v2;
00265
00266 if(v2p.m_x * v2v0.m_y - v2v0.m_x * v2p.m_y > 0.0)
00267 return false;
00268
00269 return true;
00270 }
00271
00272 bool IsAnEar(const vector<Point2> &vertices,
00273 const list<int> &active,
00274 list<int>::const_iterator prev,
00275 list<int>::const_iterator cur,
00276 list<int>::const_iterator next)
00277 {
00278 const Point2 &v0 = vertices[*prev];
00279 const Point2 &v1 = vertices[*cur];
00280 const Point2 &v2 = vertices[*next];
00281
00282 if(ComputeTriangleOrientation2(v0, v1, v2) != CCW)
00283 return false;
00284
00285 for(list<int>::const_iterator i = active.begin(), e = active.end(); i != e; ++i) {
00286 if(i == prev || i == cur || i == next)
00287 continue;
00288
00289 if(IsPointInsideTriangle2(v0, v1, v2, vertices[*i]))
00290 return false;
00291 }
00292
00293 return true;
00294 }
00295
00296 template<typename Iterator> inline
00297 Iterator succ(Iterator i) {
00298 return ++i;
00299 }
00300 }
00301
00302 bool sheep::TriangulatePolygon3(const vector<Point3> &vertices,
00303 vector<int> *triangles)
00304 {
00305 assert(vertices.size() >= 3);
00306 assert(triangles);
00307
00308 vector<Point2> vertices2;
00309 ProjectPlanarPolygon3(vertices, &vertices2);
00310
00311 const int n = vertices2.size();
00312
00313 list<int> active;
00314
00315 switch(ComputePolygonOrientation2(vertices2)) {
00316 case CCW:
00317
00318 for(int i = 0; i < n; ++i)
00319 active.push_back(i);
00320 break;
00321 case CW:
00322
00323 for(int i = n - 1; i >= 0; --i)
00324 active.push_back(i);
00325 break;
00326 }
00327
00328 triangles->reserve(3 * (n - 2));
00329
00330 list<int>::iterator prev = active.begin(), cur = succ(prev), next = succ(cur);
00331 int iter = 0;
00332
00333 while(active.size() > 2) {
00334 if(IsAnEar(vertices2, active, prev, cur, next)) {
00335
00336 triangles->push_back(*prev);
00337 triangles->push_back(*cur);
00338 triangles->push_back(*next);
00339
00340
00341
00342 cur = active.erase(cur);
00343 if(cur == active.end())
00344 cur = active.begin();
00345
00346
00347 next = succ(cur);
00348 if(next == active.end())
00349 next = active.begin();
00350
00351
00352 iter = 0;
00353 } else {
00354
00355 prev = cur;
00356 cur = next;
00357 next = succ(next);
00358 if(next == active.end())
00359 next = active.begin();
00360
00361
00362 if(++iter > 2 * n)
00363 return false;
00364 }
00365 }
00366
00367 return true;
00368 }