OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
Mesher.cpp
Go to the documentation of this file.
1#include "Utilities/Mesher.h"
2
3Mesher::Mesher(std::vector<Vector_t> &vertices):
4 vertices_m(vertices)
5{
6 apply();
7}
8
9std::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
30bool 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
49bool 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
60bool 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]) ||
77}
78
79bool 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::BoundingBox2D 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::BoundingBox2D 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
124double 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
133double dotProduct(const Vector_t &a,
134 const Vector_t &b) {
135 return a[0] * b[0] + a[1] * b[1];
136}
137
138bool 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
150bool 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
169std::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
182double 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
201unsigned 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
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
242 tri.nodes_m = vertices_m;
243 triangles_m.push_back(tri);
244}
double dotProduct(const Vector_t &a, const Vector_t &b)
Definition: Mesher.cpp:133
double getAngleBetweenEdges(const Vector_t &a, const Vector_t &b)
Definition: Mesher.cpp:112
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition: PETE.h:1111
PETE_TUTree< FnArcCos, typename T::PETE_Expr_t > acos(const PETE_Expr< T > &l)
Definition: PETE.h:725
std::complex< double > a
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
constexpr double e
The value of.
Definition: Physics.h:39
double euclidean_norm2D(Vector_t v)
Definition: MSLang.h:19
bool isPointOnLine(unsigned int i, unsigned int j, const Vector_t &pt) const
Definition: Mesher.cpp:49
double dotProduct(unsigned int i, unsigned int j, const Vector_t &pt) const
Definition: Mesher.cpp:124
bool isPointRightOfLine(unsigned int i, unsigned int j, const Vector_t &pt) const
Definition: Mesher.cpp:60
std::vector< mslang::Triangle > getTriangles() const
Definition: Mesher.cpp:9
bool isPointInsideCone(unsigned int i, unsigned int j, unsigned int jPlusOne, unsigned int jMinusOne) const
Definition: Mesher.cpp:138
void orientVerticesCCW()
Definition: Mesher.cpp:13
bool isConvex(unsigned int i) const
Definition: Mesher.cpp:30
unsigned int selectBestEar(std::vector< unsigned int > &ears) const
Definition: Mesher.cpp:201
bool lineSegmentTouchesOrCrossesLine(unsigned int i, unsigned int j, unsigned int k, unsigned int l) const
Definition: Mesher.cpp:69
std::vector< unsigned int > findAllEars() const
Definition: Mesher.cpp:169
std::vector< Vector_t > vertices_m
Definition: Mesher.h:43
double computeMinimumAngle(unsigned int i) const
Definition: Mesher.cpp:182
void apply()
Definition: Mesher.cpp:219
double crossProduct(const Vector_t &a, const Vector_t &b) const
Definition: Mesher.cpp:44
Mesher(std::vector< Vector_t > &vertices)
Definition: Mesher.cpp:3
bool isPotentialEdgeIntersected(unsigned int i) const
Definition: Mesher.cpp:79
std::vector< mslang::Triangle > triangles_m
Definition: Mesher.h:42
bool isEar(unsigned int i) const
Definition: Mesher.cpp:150
bool doesIntersect(const BoundingBox2D &bb) const
std::vector< Vector_t > nodes_m
Definition: Triangle.h:8