Choreonoid  1.8
Triangulator.h
Go to the documentation of this file.
1 
6 #ifndef CNOID_UTIL_TRIANGULATOR_H
7 #define CNOID_UTIL_TRIANGULATOR_H
8 
9 #include <vector>
10 
11 namespace cnoid {
12 
13 template<class TVector3Array> class Triangulator
14 {
15  typedef typename TVector3Array::value_type TVector3;
16 
17  enum Convexity { FLAT, CONVEX, CONCAVE };
18 
19  const TVector3Array* vertices;
20  const std::vector<int>* orgPolygon;
21  std::vector<int> triangles_;
22  std::vector<int> workPolygon;
23  TVector3 ccs; // cyclic cross sum
24  std::vector<char> earMask;
25 
26  const TVector3& vertex(int localIndex)
27  {
28  return (*vertices)[(*orgPolygon)[localIndex]];
29  }
30 
31  const TVector3& workVertex(int workPolygonIndex)
32  {
33  return (*vertices)[(*orgPolygon)[workPolygon[workPolygonIndex]]];
34  }
35 
36  Convexity calcConvexity(int ear)
37  {
38  int n = workPolygon.size();
39 
40  const TVector3& p0 = workVertex((ear + n - 1) % n);
41  TVector3 a = workVertex(ear) - p0;
42  TVector3 b = workVertex((ear + 1) % n) - p0;
43  TVector3 ccs = a.cross(b);
44 
45  Convexity convexity;
46 
47  if((ccs.norm() / (a.norm() + b.norm())) < 1.0e-4f){
48  convexity = FLAT;
49  } else {
50  convexity = (this->ccs.dot(ccs) > 0.0f) ? CONVEX : CONCAVE;
51  }
52 
53  return convexity;
54  }
55 
56  bool checkIfEarContainsOtherVertices(int ear)
57  {
58  bool contains = false;
59 
60  const int n = workPolygon.size();
61 
62  if(n > 3){
63  const int prev = (ear + n -1) % n;
64  const int next = (ear+1) % n;
65  const TVector3& a = workVertex(prev);
66  const TVector3& b = workVertex(ear);
67  const TVector3& c = workVertex(next);
68 
69  earMask[prev] = earMask[ear] = earMask[next] = 1;
70 
71  for(size_t i=0; i < workPolygon.size(); ++i){
72  if(!earMask[i]){
73  const TVector3& p = workVertex(i);
74  if(((a - p).cross(b - p)).dot(ccs) <= 0.0f){
75  continue;
76  }
77  if(((b - p).cross(c - p)).dot(ccs) <= 0.0f){
78  continue;
79  }
80  if(((c - p).cross(a - p)).dot(ccs) <= 0.0f){
81  continue;
82  }
83  contains = true;
84  break;
85  }
86  }
87 
88  earMask[prev] = earMask[ear] = earMask[next] = 0;
89  }
90 
91  return contains;
92  }
93 
94 public:
95  void setVertices(const TVector3Array& vertices)
96  {
97  this->vertices = &vertices;
98  }
99 
103  int apply(const std::vector<int>& polygon)
104  {
105  triangles_.clear();
106 
107  size_t numOrgVertices = polygon.size();
108 
109  if(numOrgVertices > earMask.size()){
110  earMask.resize(numOrgVertices, 0);
111  }
112 
113  if(numOrgVertices < 3){
114  return 0;
115  } else if(numOrgVertices == 3){
116  triangles_.push_back(0);
117  triangles_.push_back(1);
118  triangles_.push_back(2);
119  return 1;
120  }
121 
122  orgPolygon = &polygon;
123 
124  workPolygon.resize(numOrgVertices);
125  for(size_t i=0; i < numOrgVertices; ++i){
126  workPolygon[i] = i;
127  }
128 
129  ccs.setZero();
130  const TVector3& o = vertex(0);
131  for(size_t i=1; i < numOrgVertices - 1; ++i){
132  ccs += (vertex(i) - o).cross(vertex((i+1) % numOrgVertices) - o);
133  }
134 
135  int numTriangles = 0;
136 
137  while(true) {
138  int n = workPolygon.size();
139  if(n < 3){
140  break;
141  }
142  int target = -1;
143  for(int i=0; i < n; ++i){
144  Convexity convexity = calcConvexity(i);
145  if(convexity == FLAT){
146  target = i;
147  break;
148  } else if(convexity == CONVEX){
149  if(!checkIfEarContainsOtherVertices(i)){
150  triangles_.push_back(workPolygon[(i + n - 1) % n]);
151  triangles_.push_back(workPolygon[i]);
152  triangles_.push_back(workPolygon[(i + 1) % n]);
153  target = i;
154  numTriangles++;
155  break;
156  }
157  }
158  }
159  if(target < 0){
160  break;
161  }
162  for(int i = target + 1; i < n; ++i){
163  workPolygon[target++] = workPolygon[i];
164  }
165  workPolygon.pop_back();
166  }
167 
168  return numTriangles;
169  }
170 
176  const std::vector<int>& triangles()
177  {
178  return triangles_;
179  }
180 };
181 }
182 
183 #endif
cnoid::Triangulator::triangles
const std::vector< int > & triangles()
Definition: Triangulator.h:176
cnoid::Triangulator::apply
int apply(const std::vector< int > &polygon)
Definition: Triangulator.h:103
cnoid::Triangulator::setVertices
void setVertices(const TVector3Array &vertices)
Definition: Triangulator.h:95
cnoid
Definition: AbstractSceneLoader.h:11
cnoid::Triangulator
Definition: Triangulator.h:13