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