CDT  2.0.1
C++ library for constrained Delaunay triangulation
Loading...
Searching...
No Matches
CDTUtils.hpp
Go to the documentation of this file.
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
9#ifndef CDT_zWlHcbQZQyBBqPgxvFDT
10#define CDT_zWlHcbQZQyBBqPgxvFDT
11
12#include "CDTUtils.h"
13
14#include "predicates.h" // robust predicates: orient, in-circle
15
16#include <stdexcept>
17
18CDT_ENSURE_PRECISE_MATH_FOR_CONSTRUCTIONS
19
20namespace CDT
21{
22
23CDT_INLINE_IF_HEADER_ONLY Index ccw(Index i)
24{
25 return Index((i + 1) % 3);
26}
27
28CDT_INLINE_IF_HEADER_ONLY Index cw(Index i)
29{
30 return Index((i + 2) % 3);
31}
32
33CDT_INLINE_IF_HEADER_ONLY bool isOnEdge(const PtTriLocation::Enum location)
34{
35 return location == PtTriLocation::OnEdge1 ||
36 location == PtTriLocation::OnEdge2 ||
37 location == PtTriLocation::OnEdge3;
38}
39
40CDT_INLINE_IF_HEADER_ONLY Index edgeNeighbor(const PtTriLocation::Enum location)
41{
42 assert(isOnEdge(location));
43 return static_cast<Index>(location - PtTriLocation::OnEdge1);
44}
45
46template <typename T>
47T orient2D(const V2d<T>& p, const V2d<T>& v1, const V2d<T>& v2)
48{
49 return predicates::orient2d(v1.x, v1.y, v2.x, v2.y, p.x, p.y);
50}
51
52template <typename T>
54 const V2d<T>& p,
55 const V2d<T>& v1,
56 const V2d<T>& v2,
57 const T orientationTolerance)
58{
59 return classifyOrientation(orient2D(p, v1, v2), orientationTolerance);
60}
61
62template <typename T>
64classifyOrientation(const T orientation, const T orientationTolerance)
65{
66 if(orientation < -orientationTolerance)
67 return PtLineLocation::Right;
68 if(orientation > orientationTolerance)
69 return PtLineLocation::Left;
70 return PtLineLocation::OnLine;
71}
72
73template <typename T>
75 const V2d<T>& p,
76 const V2d<T>& v1,
77 const V2d<T>& v2,
78 const V2d<T>& v3)
79{
80 PtTriLocation::Enum result = PtTriLocation::Inside;
81 PtLineLocation::Enum edgeCheck = locatePointLine(p, v1, v2);
82 if(edgeCheck == PtLineLocation::Right)
83 return PtTriLocation::Outside;
84 if(edgeCheck == PtLineLocation::OnLine)
85 result = PtTriLocation::OnEdge1;
86 edgeCheck = locatePointLine(p, v2, v3);
87 if(edgeCheck == PtLineLocation::Right)
88 return PtTriLocation::Outside;
89 if(edgeCheck == PtLineLocation::OnLine)
90 {
91 result = (result == PtTriLocation::Inside) ? PtTriLocation::OnEdge2
92 : PtTriLocation::OnVertex;
93 }
94 edgeCheck = locatePointLine(p, v3, v1);
95 if(edgeCheck == PtLineLocation::Right)
96 return PtTriLocation::Outside;
97 if(edgeCheck == PtLineLocation::OnLine)
98 {
99 result = (result == PtTriLocation::Inside) ? PtTriLocation::OnEdge3
100 : PtTriLocation::OnVertex;
101 }
102 return result;
103}
104
105CDT_INLINE_IF_HEADER_ONLY Index opoNbr(const Index vertIndex)
106{
107 if(vertIndex == Index(0))
108 return Index(1);
109 if(vertIndex == Index(1))
110 return Index(2);
111 if(vertIndex == Index(2))
112 return Index(0);
113 assert(false && "Invalid vertex index");
114 handleException(std::runtime_error("Invalid vertex index"));
115 return invalidIndex;
116}
117
118CDT_INLINE_IF_HEADER_ONLY Index opoVrt(const Index neighborIndex)
119{
120 if(neighborIndex == Index(0))
121 return Index(2);
122 if(neighborIndex == Index(1))
123 return Index(0);
124 if(neighborIndex == Index(2))
125 return Index(1);
126 assert(false && "Invalid neighbor index");
127 handleException(std::runtime_error("Invalid neighbor index"));
128 return invalidIndex;
129}
130
131CDT_INLINE_IF_HEADER_ONLY Index
133{
134 assert(vv[0] == iVert || vv[1] == iVert || vv[2] == iVert);
135 if(vv[0] == iVert)
136 return Index(1);
137 if(vv[1] == iVert)
138 return Index(2);
139 return Index(0);
140}
141
142CDT_INLINE_IF_HEADER_ONLY Index edgeNeighborInd(
143 const VerticesArr3& vv,
144 const VertInd iVedge1,
145 const VertInd iVedge2)
146{
147 assert(vv[0] == iVedge1 || vv[1] == iVedge1 || vv[2] == iVedge1);
148 assert(vv[0] == iVedge2 || vv[1] == iVedge2 || vv[2] == iVedge2);
149 assert(
150 (vv[0] != iVedge1 && vv[0] != iVedge2) ||
151 (vv[1] != iVedge1 && vv[1] != iVedge2) ||
152 (vv[2] != iVedge1 && vv[2] != iVedge2));
153 /*
154 * vv[2]
155 * /\
156 * n[2]/ \n[1]
157 * /____\
158 * vv[0] n[0] vv[1]
159 */
160 if(vv[0] == iVedge1)
161 {
162 if(vv[1] == iVedge2)
163 return Index(0);
164 return Index(2);
165 }
166 if(vv[0] == iVedge2)
167 {
168 if(vv[1] == iVedge1)
169 return Index(0);
170 return Index(2);
171 }
172 return Index(1);
173}
174
175CDT_INLINE_IF_HEADER_ONLY Index
176opposedVertexInd(const NeighborsArr3& nn, const TriInd iTopo)
177{
178 assert(nn[0] == iTopo || nn[1] == iTopo || nn[2] == iTopo);
179 if(nn[0] == iTopo)
180 return Index(2);
181 if(nn[1] == iTopo)
182 return Index(0);
183 return Index(1);
184}
185
186CDT_INLINE_IF_HEADER_ONLY Index
187vertexInd(const VerticesArr3& vv, const VertInd iV)
188{
189 assert(vv[0] == iV || vv[1] == iV || vv[2] == iV);
190 if(vv[0] == iV)
191 return Index(0);
192 if(vv[1] == iV)
193 return Index(1);
194 return Index(2);
195}
196
197CDT_INLINE_IF_HEADER_ONLY TriInd
198opposedTriangle(const Triangle& tri, const VertInd iVert)
199{
200 return tri.neighbors[opposedTriangleInd(tri.vertices, iVert)];
201}
202
203CDT_INLINE_IF_HEADER_ONLY VertInd
204opposedVertex(const Triangle& tri, const TriInd iTopo)
205{
206 return tri.vertices[opposedVertexInd(tri.neighbors, iTopo)];
207}
208
210CDT_INLINE_IF_HEADER_ONLY TriInd
211edgeNeighbor(const Triangle& tri, VertInd iVedge1, VertInd iVedge2)
212{
213 return tri.neighbors[edgeNeighborInd(tri.vertices, iVedge1, iVedge2)];
214}
215
216template <typename T>
218 const V2d<T>& p,
219 const V2d<T>& v1,
220 const V2d<T>& v2,
221 const V2d<T>& v3)
222{
223 return predicates::incircle(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y, p.x, p.y) >
224 T(0);
225}
226
227CDT_INLINE_IF_HEADER_ONLY
228bool verticesShareEdge(const TriIndVec& aTris, const TriIndVec& bTris)
229{
230 for(TriIndVec::const_iterator it = aTris.begin(); it != aTris.end(); ++it)
231 if(std::find(bTris.begin(), bTris.end(), *it) != bTris.end())
232 return true;
233 return false;
234}
235
236template <typename T>
237T distanceSquared(const T ax, const T ay, const T bx, const T by)
238{
239 const T dx = bx - ax;
240 const T dy = by - ay;
241 return dx * dx + dy * dy;
242}
243
244template <typename T>
245T distance(const T ax, const T ay, const T bx, const T by)
246{
247 return std::sqrt(distanceSquared(ax, ay, bx, by));
248}
249
250template <typename T>
251T distance(const V2d<T>& a, const V2d<T>& b)
252{
253 return distance(a.x, a.y, b.x, b.y);
254}
255
256template <typename T>
257T distanceSquared(const V2d<T>& a, const V2d<T>& b)
258{
259 return distanceSquared(a.x, a.y, b.x, b.y);
260}
261
263{
264 return t.vertices[0] < nSuperTriVerts || t.vertices[1] < nSuperTriVerts ||
265 t.vertices[2] < nSuperTriVerts;
266}
267
268namespace detail
269{
270
271template <typename T>
273 const V2d<T>& v,
274 const V2d<T>& edgeStart,
275 const V2d<T>& edgeEnd)
276{
277 // strictly inside the edge's diametral circle: the angle at v is obtuse
278 return predicates::indiamcircle(
279 edgeStart.x, edgeStart.y, edgeEnd.x, edgeEnd.y, v.x, v.y) >
280 T(0);
281}
282
283template <typename T>
284T doubledArea(const V2d<T>& a, const V2d<T>& b, const V2d<T>& c)
285{
286 return std::abs(orient2D(a, b, c));
287}
288
289template <typename T>
290T sineOfSmallestAngle(const V2d<T>& a, const V2d<T>& b, const V2d<T>& c)
291{
292 // find sides of the smallest angle using law of sines:
293 T sideA = distance(a, b), sideB = distance(b, c);
294 if(sideA > sideB)
295 std::swap(sideA, sideB);
296 sideA = std::max(sideA, distance(a, c));
297 return (doubledArea(a, b, c) / sideA) / sideB;
298}
299
300} // namespace detail
301
302template <typename T>
303T area(const V2d<T>& a, const V2d<T>& b, const V2d<T>& c)
304{
305 return detail::doubledArea(a, b, c) / T(2);
306}
307
308template <typename T>
310{
311 const T denom = T(2) * orient2D(a, b, c);
312 assert(denom != T(0));
313 const T aLenSq = distanceSquared(a, c), bLenSq = distanceSquared(b, c);
314 a.x -= c.x, a.y -= c.y;
315 b.x -= c.x, b.y -= c.y;
316 c.x += (b.y * aLenSq - a.y * bLenSq) / denom;
317 c.y += (a.x * bLenSq - b.x * aLenSq) / denom;
318 return c;
319}
320
321template <typename T>
322T smallestAngle(const V2d<T>& a, const V2d<T>& b, const V2d<T>& c)
323{
324 const T angleSine = detail::sineOfSmallestAngle(a, b, c);
325 assert(angleSine >= -1 && angleSine <= 1);
326 return std::asin(angleSine);
327}
328
329template <typename T>
330T degToRad(const T degrees)
331{
332 return degrees / T(180) * T(CDT_M_PI);
333}
334
335} // namespace CDT
336
337CDT_RESTORE_MATH_SETTINGS_FOR_CONSTRUCTIONS
338
339#endif // header-guard
Utilities and helpers.
T sineOfSmallestAngle(const V2d< T > &a, const V2d< T > &b, const V2d< T > &c)
Sine of smallest angle of triangle ABC.
Definition CDTUtils.hpp:290
bool isEncroachingOnEdge(const V2d< T > &v, const V2d< T > &edgeStart, const V2d< T > &edgeEnd)
Check if vertex V is encroaching on diametral circle of an edge.
Definition CDTUtils.hpp:272
T doubledArea(const V2d< T > &a, const V2d< T > &b, const V2d< T > &c)
Doubled surface area of a triangle ABC.
Definition CDTUtils.hpp:284
Namespace containing triangulation functionality.
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY VertInd opposedVertex(const Triangle &tri, TriInd iTopo)
Given two triangles, return vertex of first triangle opposed to the second.
Definition CDTUtils.hpp:204
CDT_EXPORT T degToRad(T degrees)
Convert an angle from degrees to radians.
Definition CDTUtils.hpp:330
CDT_EXPORT T area(const V2d< T > &a, const V2d< T > &b, const V2d< T > &c)
Surface area of a triangle ABC.
Definition CDTUtils.hpp:303
std::vector< TriInd > TriIndVec
Vector of triangle indices.
Definition CDTUtils.h:272
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index edgeNeighborInd(const VerticesArr3 &vv, VertInd iVedge1, VertInd iVedge2)
Index of triangle's neighbor opposed to an edge.
Definition CDTUtils.hpp:142
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index opposedTriangleInd(const VerticesArr3 &vv, VertInd iVert)
Index of triangle's neighbor opposed to a vertex.
Definition CDTUtils.hpp:132
CDT_EXPORT PtLineLocation::Enum classifyOrientation(T orientation, T orientationTolerance=T(0))
Classify value of orient2d predicate.
Definition CDTUtils.hpp:64
array< TriInd, 3 > NeighborsArr3
array of three neighbors
Definition CDTUtils.h:274
CDT_EXPORT T distance(const V2d< T > &a, const V2d< T > &b)
Distance between two 2D points.
Definition CDTUtils.hpp:251
IndexSizeType VertInd
Vertex index.
Definition CDTUtils.h:254
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY bool verticesShareEdge(const TriIndVec &aTris, const TriIndVec &bTris)
Test if two vertices share at least one common triangle.
Definition CDTUtils.hpp:228
CDT_EXPORT Index cw(Index i)
Advance vertex or neighbor index clockwise.
Definition CDTUtils.hpp:28
array< VertInd, 3 > VerticesArr3
array of three vertex indices
Definition CDTUtils.h:273
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY bool touchesSuperTriangle(const Triangle &t)
Check if any of triangle's vertices belongs to a super-triangle.
Definition CDTUtils.hpp:262
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index opoVrt(Index neighborIndex)
Opposed vertex index from neighbor index.
Definition CDTUtils.hpp:118
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index opoNbr(Index vertIndex)
Opposed neighbor index from vertex index.
Definition CDTUtils.hpp:105
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index vertexInd(const VerticesArr3 &vv, VertInd iV)
If triangle has a given vertex return vertex-index.
Definition CDTUtils.hpp:187
CDT_EXPORT T orient2D(const V2d< T > &p, const V2d< T > &v1, const V2d< T > &v2)
Orient p against line v1-v2 2D: robust geometric predicate.
Definition CDTUtils.hpp:47
CDT_EXPORT PtLineLocation::Enum locatePointLine(const V2d< T > &p, const V2d< T > &v1, const V2d< T > &v2, T orientationTolerance=T(0))
Check if point lies to the left of, to the right of, or on a line.
Definition CDTUtils.hpp:53
CDT_EXPORT T distanceSquared(const V2d< T > &a, const V2d< T > &b)
Squared distance between two 2D points.
Definition CDTUtils.hpp:257
CDT_EXPORT Index ccw(Index i)
Advance vertex or neighbor index counter-clockwise.
Definition CDTUtils.hpp:23
CDT_EXPORT V2d< T > circumcenter(V2d< T > a, V2d< T > b, V2d< T > c)
Position of ABC triangle circumcenter.
Definition CDTUtils.hpp:309
CDT_EXPORT Index edgeNeighbor(PtTriLocation::Enum location)
Neighbor index from a on-edge location.
Definition CDTUtils.hpp:40
unsigned char Index
Index in triangle.
Definition CDTUtils.h:252
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY TriInd opposedTriangle(const Triangle &tri, VertInd iVert)
Given triangle and a vertex find opposed triangle.
Definition CDTUtils.hpp:198
CDT_EXPORT T smallestAngle(const V2d< T > &a, const V2d< T > &b, const V2d< T > &c)
Smallest angle of triangle ABC in radians.
Definition CDTUtils.hpp:322
CDT_EXPORT bool isInCircumcircle(const V2d< T > &p, const V2d< T > &v1, const V2d< T > &v2, const V2d< T > &v3)
Test if point lies in a circumscribed circle of a triangle.
Definition CDTUtils.hpp:217
CDT_EXPORT bool isOnEdge(PtTriLocation::Enum location)
Check if location is classified as on any of three edges.
Definition CDTUtils.hpp:33
IndexSizeType TriInd
Triangle index.
Definition CDTUtils.h:256
CDT_EXPORT PtTriLocation::Enum locatePointTriangle(const V2d< T > &p, const V2d< T > &v1, const V2d< T > &v2, const V2d< T > &v3)
Check if point a lies inside of, outside of, or on an edge of a triangle.
Definition CDTUtils.hpp:74
CDT_EXPORT CDT_INLINE_IF_HEADER_ONLY Index opposedVertexInd(const NeighborsArr3 &nn, TriInd iTopo)
Index of triangle's vertex opposed to a triangle.
Definition CDTUtils.hpp:176
Triangulation triangle (counter-clockwise winding)
Definition CDTUtils.h:416
VerticesArr3 vertices
triangle's three vertices
Definition CDTUtils.h:417
NeighborsArr3 neighbors
triangle's three neighbors
Definition CDTUtils.h:418
2D vector
Definition CDTUtils.h:192
T y
Y-coordinate.
Definition CDTUtils.h:194
T x
X-coordinate.
Definition CDTUtils.h:193