Coverage Report

Created: 2025-08-26 06:41

/src/assimp/contrib/poly2tri/poly2tri/common/shapes.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
3
 * https://github.com/jhasse/poly2tri
4
 *
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without modification,
8
 * are permitted provided that the following conditions are met:
9
 *
10
 * * Redistributions of source code must retain the above copyright notice,
11
 *   this list of conditions and the following disclaimer.
12
 * * Redistributions in binary form must reproduce the above copyright notice,
13
 *   this list of conditions and the following disclaimer in the documentation
14
 *   and/or other materials provided with the distribution.
15
 * * Neither the name of Poly2Tri nor the names of its contributors may be
16
 *   used to endorse or promote products derived from this software without specific
17
 *   prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
 */
31
32
#pragma once
33
34
#include "dll_symbol.h"
35
36
#include <cmath>
37
#include <cstddef>
38
#include <stdexcept>
39
#include <vector>
40
41
#if defined(_WIN32) && defined(_MSC_VER) && !defined(__INTEL_COMPILER)
42
#  pragma warning( disable: 4251)
43
#endif
44
namespace p2t {
45
46
struct Edge;
47
48
struct P2T_DLL_SYMBOL Point {
49
50
  double x, y;
51
52
  /// Default constructor does nothing (for performance).
53
  Point()
54
0
  {
55
0
    x = 0.0;
56
0
    y = 0.0;
57
0
  }
58
59
  /// The edges this point constitutes an upper ending point
60
  std::vector<Edge*> edge_list;
61
62
  /// Construct using coordinates.
63
  Point(double x, double y);
64
65
  /// Set this point to all zeros.
66
  void set_zero()
67
0
  {
68
0
    x = 0.0;
69
0
    y = 0.0;
70
0
  }
71
72
  /// Set this point to some specified coordinates.
73
  void set(double x_, double y_)
74
0
  {
75
0
    x = x_;
76
0
    y = y_;
77
0
  }
78
79
  /// Negate this point.
80
  Point operator -() const
81
0
  {
82
0
    Point v;
83
0
    v.set(-x, -y);
84
0
    return v;
85
0
  }
86
87
  /// Add a point to this point.
88
  void operator +=(const Point& v)
89
0
  {
90
0
    x += v.x;
91
0
    y += v.y;
92
0
  }
93
94
  /// Subtract a point from this point.
95
  void operator -=(const Point& v)
96
0
  {
97
0
    x -= v.x;
98
0
    y -= v.y;
99
0
  }
100
101
  /// Multiply this point by a scalar.
102
  void operator *=(double a)
103
0
  {
104
0
    x *= a;
105
0
    y *= a;
106
0
  }
107
108
  /// Get the length of this point (the norm).
109
  double Length() const
110
0
  {
111
0
    return sqrt(x * x + y * y);
112
0
  }
113
114
  /// Convert this point into a unit point. Returns the Length.
115
  double Normalize()
116
0
  {
117
0
    const double len = Length();
118
0
    x /= len;
119
0
    y /= len;
120
0
    return len;
121
0
  }
122
123
};
124
125
P2T_DLL_SYMBOL std::ostream& operator<<(std::ostream&, const Point&);
126
127
// Represents a simple polygon's edge
128
struct P2T_DLL_SYMBOL Edge {
129
130
  Point* p, *q;
131
132
  /// Constructor
133
0
  Edge(Point& p1, Point& p2) : p(&p1), q(&p2)
134
0
  {
135
0
    if (p1.y > p2.y) {
136
0
      q = &p1;
137
0
      p = &p2;
138
0
    } else if (p1.y == p2.y) {
139
0
      if (p1.x > p2.x) {
140
0
        q = &p1;
141
0
        p = &p2;
142
0
      } else if (p1.x == p2.x) {
143
        // Repeat points
144
0
        throw std::runtime_error("Edge::Edge: p1 == p2");
145
0
      }
146
0
    }
147
148
0
    q->edge_list.push_back(this);
149
0
  }
150
};
151
152
// Triangle-based data structures are know to have better performance than quad-edge structures
153
// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
154
//      "Triangulations in CGAL"
155
class P2T_DLL_SYMBOL Triangle {
156
public:
157
158
/// Constructor
159
Triangle(Point& a, Point& b, Point& c);
160
161
/// Flags to determine if an edge is a Constrained edge
162
bool constrained_edge[3];
163
/// Flags to determine if an edge is a Delauney edge
164
bool delaunay_edge[3];
165
166
Point* GetPoint(int index);
167
Point* PointCW(const Point& point);
168
Point* PointCCW(const Point& point);
169
Point* OppositePoint(Triangle& t, const Point& p);
170
171
Triangle* GetNeighbor(int index);
172
void MarkNeighbor(Point* p1, Point* p2, Triangle* t);
173
void MarkNeighbor(Triangle& t);
174
175
void MarkConstrainedEdge(int index);
176
void MarkConstrainedEdge(Edge& edge);
177
void MarkConstrainedEdge(Point* p, Point* q);
178
179
int Index(const Point* p);
180
int EdgeIndex(const Point* p1, const Point* p2);
181
182
Triangle* NeighborAcross(const Point& point);
183
Triangle* NeighborCW(const Point& point);
184
Triangle* NeighborCCW(const Point& point);
185
bool GetConstrainedEdgeCCW(const Point& p);
186
bool GetConstrainedEdgeCW(const Point& p);
187
void SetConstrainedEdgeCCW(const Point& p, bool ce);
188
void SetConstrainedEdgeCW(const Point& p, bool ce);
189
bool GetDelunayEdgeCCW(const Point& p);
190
bool GetDelunayEdgeCW(const Point& p);
191
void SetDelunayEdgeCCW(const Point& p, bool e);
192
void SetDelunayEdgeCW(const Point& p, bool e);
193
194
bool Contains(const Point* p);
195
bool Contains(const Edge& e);
196
bool Contains(const Point* p, const Point* q);
197
void Legalize(Point& point);
198
void Legalize(Point& opoint, Point& npoint);
199
/**
200
 * Clears all references to all other triangles and points
201
 */
202
void Clear();
203
void ClearNeighbor(const Triangle *triangle);
204
void ClearNeighbors();
205
void ClearDelunayEdges();
206
207
inline bool IsInterior();
208
inline void IsInterior(bool b);
209
210
void DebugPrint();
211
212
bool CircumcicleContains(const Point&) const;
213
214
private:
215
216
bool IsCounterClockwise() const;
217
218
/// Triangle points
219
Point* points_[3];
220
/// Neighbor list
221
Triangle* neighbors_[3];
222
223
/// Has this triangle been marked as an interior triangle?
224
bool interior_;
225
};
226
227
inline bool cmp(const Point* a, const Point* b)
228
0
{
229
0
  if (a->y < b->y) {
230
0
    return true;
231
0
  } else if (a->y == b->y) {
232
    // Make sure q is point with greater x value
233
0
    if (a->x < b->x) {
234
0
      return true;
235
0
    }
236
0
  }
237
0
  return false;
238
0
}
239
240
/// Add two points_ component-wise.
241
inline Point operator +(const Point& a, const Point& b)
242
0
{
243
0
  return Point(a.x + b.x, a.y + b.y);
244
0
}
245
246
/// Subtract two points_ component-wise.
247
inline Point operator -(const Point& a, const Point& b)
248
0
{
249
0
  return Point(a.x - b.x, a.y - b.y);
250
0
}
251
252
/// Multiply point by scalar
253
inline Point operator *(double s, const Point& a)
254
0
{
255
0
  return Point(s * a.x, s * a.y);
256
0
}
257
258
inline bool operator ==(const Point& a, const Point& b)
259
0
{
260
0
  return a.x == b.x && a.y == b.y;
261
0
}
262
263
inline bool operator !=(const Point& a, const Point& b)
264
0
{
265
0
  return !(a.x == b.x) || !(a.y == b.y);
266
0
}
267
268
/// Peform the dot product on two vectors.
269
inline double Dot(const Point& a, const Point& b)
270
0
{
271
0
  return a.x * b.x + a.y * b.y;
272
0
}
273
274
/// Perform the cross product on two vectors. In 2D this produces a scalar.
275
inline double Cross(const Point& a, const Point& b)
276
0
{
277
0
  return a.x * b.y - a.y * b.x;
278
0
}
279
280
/// Perform the cross product on a point and a scalar. In 2D this produces
281
/// a point.
282
inline Point Cross(const Point& a, double s)
283
0
{
284
0
  return Point(s * a.y, -s * a.x);
285
0
}
286
287
/// Perform the cross product on a scalar and a point. In 2D this produces
288
/// a point.
289
inline Point Cross(double s, const Point& a)
290
0
{
291
0
  return Point(-s * a.y, s * a.x);
292
0
}
293
294
inline Point* Triangle::GetPoint(int index)
295
0
{
296
0
  return points_[index];
297
0
}
298
299
inline Triangle* Triangle::GetNeighbor(int index)
300
0
{
301
0
  return neighbors_[index];
302
0
}
303
304
inline bool Triangle::Contains(const Point* p)
305
0
{
306
0
  return p == points_[0] || p == points_[1] || p == points_[2];
307
0
}
308
309
inline bool Triangle::Contains(const Edge& e)
310
0
{
311
0
  return Contains(e.p) && Contains(e.q);
312
0
}
313
314
inline bool Triangle::Contains(const Point* p, const Point* q)
315
0
{
316
0
  return Contains(p) && Contains(q);
317
0
}
318
319
inline bool Triangle::IsInterior()
320
0
{
321
0
  return interior_;
322
0
}
323
324
inline void Triangle::IsInterior(bool b)
325
0
{
326
0
  interior_ = b;
327
0
}
328
329
/// Is this set a valid delaunay triangulation?
330
P2T_DLL_SYMBOL bool IsDelaunay(const std::vector<p2t::Triangle*>&);
331
332
}