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