OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
Mesher.cpp
Go to the documentation of this file.
1 #include "Utilities/Mesher.h"
2 
3 Mesher::Mesher(std::vector<Vector_t> &vertices):
4  vertices_m(vertices)
5 {
6  apply();
7 }
8 
9 std::vector<mslang::Triangle> Mesher::getTriangles() const {
10  return triangles_m;
11 }
12 
14  const unsigned int size = vertices_m.size();
15  double sum = 0.0;
16  for (unsigned int i = 0; i < size; ++ i) {
17  unsigned int iPlusOne = (i + 1) % size;
18  Vector_t edge(vertices_m[iPlusOne][0] - vertices_m[i][0],
19  vertices_m[iPlusOne][1] + vertices_m[i][1],
20  0.0);
21  sum += edge[0] * edge[1];
22  }
23  if (sum <= 0.0) return;
24 
25  std::vector<Vector_t> reoriented(vertices_m.rbegin(), vertices_m.rend());
26 
27  vertices_m.swap(reoriented);
28 }
29 
30 bool Mesher::isConvex(unsigned int i) const {
31  unsigned int numVertices = vertices_m.size();
32  i = i % numVertices;
33  unsigned int iPlusOne = (i + 1) % numVertices;
34  unsigned int iMinusOne = (i + numVertices - 1) % numVertices;
35 
36  Vector_t edge0 = vertices_m[iMinusOne] - vertices_m[i];
37  Vector_t edge1 = vertices_m[iPlusOne] - vertices_m[i];
38 
39  double vectorProduct = edge0[0] * edge1[1] - edge0[1] * edge1[0];
40 
41  return (vectorProduct < 0.0);
42 }
43 
45  const Vector_t &b) const {
46  return a[0] * b[1] - a[1] * b[0];
47 }
48 
49 bool Mesher::isPointOnLine(unsigned int i,
50  unsigned int j,
51  const Vector_t &pt) const {
52  Vector_t aTmp = vertices_m[j] - vertices_m[i];
53  Vector_t bTmp = pt - vertices_m[i];
54 
55  double r = crossProduct(aTmp, bTmp);
56 
57  return std::abs(r) < 1e-10;
58 }
59 
60 bool Mesher::isPointRightOfLine(unsigned int i,
61  unsigned int j,
62  const Vector_t &pt) const {
63  Vector_t aTmp = vertices_m[j] - vertices_m[i];
64  Vector_t bTmp = pt - vertices_m[i];
65 
66  return crossProduct(aTmp, bTmp) < 0.0;
67 }
68 
70  unsigned int j,
71  unsigned int k,
72  unsigned int l) const {
73  return (isPointOnLine(i, j, vertices_m[k]) ||
74  isPointOnLine(i, j, vertices_m[l]) ||
75  (isPointRightOfLine(i, j, vertices_m[k]) ^
76  isPointRightOfLine(i, j, vertices_m[l])));
77 }
78 
79 bool Mesher::isPotentialEdgeIntersected(unsigned int i) const {
80  unsigned int numVertices = vertices_m.size();
81  if (numVertices < 5) return false;
82 
83  i = i % numVertices;
84  unsigned int iPlusOne = (i + 1) % numVertices;
85  unsigned int iMinusOne = (i + numVertices - 1) % numVertices;
86 
87  mslang::BoundingBox bbPotentialNewEdge;
88  bbPotentialNewEdge.center_m = 0.5 * (vertices_m[iMinusOne] + vertices_m[iPlusOne]);
89  bbPotentialNewEdge.width_m = std::abs(vertices_m[iMinusOne][0] - vertices_m[iPlusOne][0]);
90  bbPotentialNewEdge.height_m = std::abs(vertices_m[iMinusOne][1] - vertices_m[iPlusOne][1]);
91 
92  for (unsigned int j = iPlusOne + 1; j < iPlusOne + numVertices - 3; ++ j) {
93  unsigned int k = (j % numVertices);
94  unsigned int kPlusOne = ((k + 1) % numVertices);
95 
96  mslang::BoundingBox bbThisEdge;
97  bbThisEdge.center_m = 0.5 * (vertices_m[k] + vertices_m[kPlusOne]);
98  bbThisEdge.width_m = std::abs(vertices_m[k][0] - vertices_m[kPlusOne][0]);
99  bbThisEdge.height_m = std::abs(vertices_m[k][1] - vertices_m[kPlusOne][1]);
100 
101  if (bbPotentialNewEdge.doesIntersect(bbThisEdge) &&
102  lineSegmentTouchesOrCrossesLine(iPlusOne, iMinusOne,
103  k, kPlusOne) &&
105  iPlusOne, iMinusOne))
106  return true;
107  }
108 
109  return false;
110 }
111 
113  const Vector_t &b) {
114  double lengthA = mslang::euclidean_norm2D(a);
115  double lengthB = mslang::euclidean_norm2D(b);
116 
117  double angle = std::acos((a[0] * b[0] + a[1] * b[1]) / lengthA / lengthB);
118  if (a[0] * b[1] - a[1] * b[0] < 0.0)
119  angle += M_PI;
120 
121  return angle;
122 }
123 
124 double Mesher::dotProduct(unsigned int i,
125  unsigned int j,
126  const Vector_t &pt) const {
127  Vector_t edge0 = vertices_m[j] - vertices_m[i];
128  Vector_t edge1 = vertices_m[j] - pt;
129 
130  return edge0[0] * edge1[0] + edge0[1] * edge1[1];
131 }
132 
133 double dotProduct(const Vector_t &a,
134  const Vector_t &b) {
135  return a[0] * b[0] + a[1] * b[1];
136 }
137 
138 bool Mesher::isPointInsideCone(unsigned int i,
139  unsigned int j,
140  unsigned int jPlusOne,
141  unsigned int jMinusOne) const {
142  const Vector_t &pt = vertices_m[i];
143 
144  return !((isPointRightOfLine(jMinusOne, j, pt) &&
145  dotProduct(jMinusOne, j, pt) > 0.0) ||
146  (isPointRightOfLine(j, jPlusOne, pt) &&
147  dotProduct(jPlusOne, j, pt) < 0.0));
148 }
149 
150 bool Mesher::isEar(unsigned int i) const {
151  unsigned int size = vertices_m.size();
152 
153  unsigned int iMinusTwo = (i + size - 2) % size;
154  unsigned int iMinusOne = (i + size - 1) % size;
155  unsigned int iPlusOne = (i + 1) % size;
156  unsigned int iPlusTwo = (i + 2) % size;
157 
158  bool convex = isConvex(i);
159  bool isInsideCone1 = isPointInsideCone(iMinusOne, iPlusOne, iPlusTwo, i);
160  bool isInsideCone2 = isPointInsideCone(iPlusOne, iMinusOne, i, iMinusTwo);
161  bool notCrossed = !isPotentialEdgeIntersected(i);
162 
163  return (convex &&
164  isInsideCone1 &&
165  isInsideCone2 &&
166  notCrossed);
167 }
168 
169 std::vector<unsigned int> Mesher::findAllEars() const {
170  unsigned int size = vertices_m.size();
171  std::vector<unsigned int> ears;
172 
173  for (unsigned int i = 0; i < size; ++ i) {
174  if (isEar(i)) {
175  ears.push_back(i);
176  }
177  }
178 
179  return ears;
180 }
181 
182 double Mesher::computeMinimumAngle(unsigned int i) const {
183  unsigned int numVertices = vertices_m.size();
184  unsigned int previous = (i + numVertices - 1) % numVertices;
185  unsigned int next = (i + 1) % numVertices;
186 
187  Vector_t edge0 = vertices_m[i] - vertices_m[previous];
188  Vector_t edge1 = vertices_m[next] - vertices_m[i];
189  Vector_t edge2 = vertices_m[previous] - vertices_m[next];
190  double length0 = mslang::euclidean_norm2D(edge0);
191  double length1 = mslang::euclidean_norm2D(edge1);
192  double length2 = mslang::euclidean_norm2D(edge2);
193 
194  double angle01 = std::acos(-(edge0[0] * edge1[0] + edge0[1] * edge1[1]) / length0 / length1);
195  double angle12 = std::acos(-(edge1[0] * edge2[0] + edge1[1] * edge2[1]) / length1 / length2);
196  double angle20 = M_PI - angle01 - angle12;
197 
198  return std::min(std::min(angle01, angle12), angle20);
199 }
200 
201 unsigned int Mesher::selectBestEar(std::vector<unsigned int> &ears) const {
202  unsigned int numEars = ears.size();
203 
204  double maxMinAngle = computeMinimumAngle(ears[0]);
205  unsigned int earWithMaxMinAngle = 0;
206 
207  for (unsigned int i = 1; i < numEars; ++ i) {
208  double angle = computeMinimumAngle(ears[i]);
209 
210  if (angle > maxMinAngle) {
211  maxMinAngle = angle;
212  earWithMaxMinAngle = i;
213  }
214  }
215 
216  return ears[earWithMaxMinAngle];
217 }
218 
221 
222  unsigned int numVertices = vertices_m.size();
223  while (numVertices > 3) {
224  std::vector<unsigned int> allEars = findAllEars();
225  unsigned int bestEar = selectBestEar(allEars);
226  unsigned int next = (bestEar + 1) % numVertices;
227  unsigned int previous = (bestEar + numVertices - 1) % numVertices;
228 
229  mslang::Triangle tri;
230  tri.nodes_m[0] = vertices_m[previous];
231  tri.nodes_m[1] = vertices_m[bestEar];
232  tri.nodes_m[2] = vertices_m[next];
233  // tri.print(4);
234  triangles_m.push_back(tri);
235 
236  vertices_m.erase(vertices_m.begin() + bestEar);
237 
238  -- numVertices;
239  }
240 
241  mslang::Triangle tri;
242  tri.nodes_m = vertices_m;
243  triangles_m.push_back(tri);
244 }
std::vector< unsigned int > findAllEars() const
Definition: Mesher.cpp:169
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
std::vector< Vector_t > vertices_m
Definition: Mesher.h:43
PETE_TUTree< FnArcCos, typename T::PETE_Expr_t > acos(const PETE_Expr< T > &l)
Definition: PETE.h:808
constexpr double e
The value of .
Definition: Physics.h:40
void apply()
Definition: Mesher.cpp:219
std::vector< mslang::Triangle > triangles_m
Definition: Mesher.h:42
bool isConvex(unsigned int i) const
Definition: Mesher.cpp:30
double dotProduct(unsigned int i, unsigned int j, const Vector_t &pt) const
Definition: Mesher.cpp:124
Mesher(std::vector< Vector_t > &vertices)
Definition: Mesher.cpp:3
bool isPotentialEdgeIntersected(unsigned int i) const
Definition: Mesher.cpp:79
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition: PETE.h:1213
double crossProduct(const Vector_t &a, const Vector_t &b) const
Definition: Mesher.cpp:44
unsigned int selectBestEar(std::vector< unsigned int > &ears) const
Definition: Mesher.cpp:201
std::vector< mslang::Triangle > getTriangles() const
Definition: Mesher.cpp:9
double getAngleBetweenEdges(const Vector_t &a, const Vector_t &b)
Definition: Mesher.cpp:112
void orientVerticesCCW()
Definition: Mesher.cpp:13
std::vector< Vector_t > nodes_m
Definition: Triangle.h:8
double euclidean_norm2D(Vector_t v)
Definition: MSLang.h:19
bool isPointInsideCone(unsigned int i, unsigned int j, unsigned int jPlusOne, unsigned int jMinusOne) const
Definition: Mesher.cpp:138
bool isEar(unsigned int i) const
Definition: Mesher.cpp:150
bool doesIntersect(const BoundingBox &bb) const
Definition: BoundingBox.cpp:4
bool lineSegmentTouchesOrCrossesLine(unsigned int i, unsigned int j, unsigned int k, unsigned int l) const
Definition: Mesher.cpp:69
bool isPointRightOfLine(unsigned int i, unsigned int j, const Vector_t &pt) const
Definition: Mesher.cpp:60
bool isPointOnLine(unsigned int i, unsigned int j, const Vector_t &pt) const
Definition: Mesher.cpp:49
double computeMinimumAngle(unsigned int i) const
Definition: Mesher.cpp:182
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:95
double dotProduct(const Vector_t &a, const Vector_t &b)
Definition: Mesher.cpp:133