GtePolygon2.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <Mathematics/GteVector2.h>
12 #include <algorithm>
13 #include <set>
14 #include <vector>
15 
16 // The Polygon2 object represents a simple polygon: No duplicate vertices,
17 // closed (each vertex is shared by exactly two edges), and no
18 // self-intersections at interior edge points. The 'vertexPool' array can
19 // contain more points than needed to define the polygon, which allows the
20 // vertex pool to have multiple polygons associated with it. Thus, the
21 // programmer must ensure that the vertex pool persists as long as any
22 // Polygon2 objects exist that depend on the pool. The number of polygon
23 // vertices is 'numIndices' and must be 3 or larger. The 'indices' array
24 // refers to the points in 'vertexPool' that are part of the polygon and must
25 // have 'numIndices' unique elements. The edges of the polygon are pairs of
26 // indices into 'vertexPool',
27 // edge[0] = (indices[0], indices[1])
28 // :
29 // edge[numIndices-2] = (indices[numIndices-2], indices[numIndices-1])
30 // edge[numIndices-1] = (indices[numIndices-1], indices[0])
31 // The programmer should ensure the polygon is simple. The geometric
32 // queries are valid regardless of whether the polygon is oriented clockwise
33 // or counterclockwise.
34 //
35 // NOTE: Comparison operators are not provided. The semantics of equal
36 // polygons is complicated and (at the moment) not useful. The vertex pools
37 // can be different and indices do not match, but the vertices they reference
38 // can match. Even with a shared vertex pool, the indices can be "rotated",
39 // leading to the same polygon abstractly but the data structures do not
40 // match.
41 
42 namespace gte
43 {
44 
45 template <typename Real>
46 class Polygon2
47 {
48 public:
49  // Construction. The constructor succeeds when 'numIndices' >= 3 and
50  // 'vertexPool' and 'indices' are not null; we cannot test whether you
51  // have a valid number of elements in the input arrays. A copy is made
52  // of 'indices', but the 'vertexPool' is not copied. If the constructor
53  // fails, the internal vertex pointer is set to null, the index array
54  // has no elements, and the orientation is set to clockwise.
55  Polygon2(Vector2<Real> const* vertexPool, int numIndices,
56  int const* indices, bool counterClockwise);
57 
58  // To validate construction, create an object as shown:
59  // Polygon2<Real> polygon(parameters);
60  // if (!polygon) { <constructor failed, handle accordingly>; }
61  inline operator bool() const;
62 
63  // Member access.
64  inline Vector2<Real> const* GetVertexPool() const;
65  inline std::set<int> const& GetVertices() const;
66  inline std::vector<int> const& GetIndices() const;
67  inline bool CounterClockwise() const;
68 
69  // Geometric queries.
71  Real ComputePerimeterLength() const;
72  Real ComputeArea() const;
73 
74  // Simple polygons have no self-intersections at interior points
75  // of edges. The test is an exhaustive all-pairs intersection
76  // test for edges, which is inefficient for polygons with a large
77  // number of vertices. TODO: Provide an efficient algorithm that
78  // uses the algorithm of class RectangleManager.h.
79  bool IsSimple() const;
80 
81  // Convex polygons are simple polygons where the angles between
82  // consecutive edges are less than or equal to pi radians.
83  bool IsConvex() const;
84 
85 private:
86  // These calls have preconditions that mVertexPool is not null and
87  // mIndices.size() > 3. The heart of the algorithms are implemented
88  // here.
89  bool IsSimpleInternal() const;
90  bool IsConvexInternal() const;
91 
93  std::set<int> mVertices;
94  std::vector<int> mIndices;
96 };
97 
98 
99 template <typename Real>
100 Polygon2<Real>::Polygon2(Vector2<Real> const* vertexPool, int numIndices,
101  int const* indices, bool counterClockwise)
102  :
103  mVertexPool(vertexPool),
104  mCounterClockwise(counterClockwise)
105 {
106  if (numIndices >= 3 && vertexPool && indices)
107  {
108  for (int i = 0; i < numIndices; ++i)
109  {
110  mVertices.insert(indices[i]);
111  }
112 
113  if (numIndices == static_cast<int>(mVertices.size()))
114  {
115  mIndices.resize(numIndices);
116  std::copy(indices, indices + numIndices, mIndices.begin());
117  return;
118  }
119 
120  // At least one duplicated vertex was encountered, so the polygon
121  // is not simple. Fail the constructor call.
122  mVertices.clear();
123  }
124 
125  // Invalid input to the Polygon2 constructor.
126  mVertexPool = nullptr;
127  mCounterClockwise = false;
128 }
129 
130 template <typename Real> inline
132 {
133  return mVertexPool != nullptr;
134 }
135 
136 template <typename Real> inline
138 {
139  return mVertexPool;
140 }
141 
142 template <typename Real> inline
143 std::set<int> const& Polygon2<Real>::GetVertices() const
144 {
145  return mVertices;
146 }
147 
148 template <typename Real> inline
149 std::vector<int> const& Polygon2<Real>::GetIndices() const
150 {
151  return mIndices;
152 }
153 
154 template <typename Real> inline
156 {
157  return mCounterClockwise;
158 }
159 
160 template <typename Real>
162 {
164  if (mVertexPool)
165  {
166  for (int index : mVertices)
167  {
168  average += mVertexPool[index];
169  }
170  average /= static_cast<Real>(mVertices.size());
171  }
172  return average;
173 }
174 
175 template <typename Real>
177 {
178  Real length = (Real)0;
179  if (mVertexPool)
180  {
182  for (int index : mIndices)
183  {
185  length += Length(v1 - v0);
186  v0 = v1;
187  }
188  }
189  return length;
190 }
191 
192 template <typename Real>
194 {
195  Real area = (Real)0;
196  if (mVertexPool)
197  {
198  int const numIndices = static_cast<int>(mIndices.size());
199  Vector2<Real> v0 = mVertexPool[mIndices[numIndices - 2]];
200  Vector2<Real> v1 = mVertexPool[mIndices[numIndices - 1]];
201  for (int index : mIndices)
202  {
204  area += v1[0] * (v2[1] - v0[1]);
205  v0 = v1;
206  v1 = v2;
207  }
208  area *= (Real)0.5;
209  }
210  return fabs(area);
211 }
212 
213 template <typename Real>
215 {
216  if (!mVertexPool)
217  {
218  return false;
219  }
220 
221  // For mVertexPool to be nonnull, the number of indices is guaranteed
222  // to be at least 3.
223  int const numIndices = static_cast<int>(mIndices.size());
224  if (numIndices == 3)
225  {
226  // The polygon is a triangle.
227  return true;
228  }
229 
230  return IsSimpleInternal();
231 }
232 
233 template <typename Real>
235 {
236  if (!mVertexPool)
237  {
238  return false;
239  }
240 
241  // For mVertexPool to be nonnull, the number of indices is guaranteed
242  // to be at least 3.
243  int const numIndices = static_cast<int>(mIndices.size());
244  if (numIndices == 3)
245  {
246  // The polygon is a triangle.
247  return true;
248  }
249 
250  return IsSimpleInternal() && IsConvexInternal();
251 }
252 
253 template <typename Real>
255 {
256  Segment2<Real> seg0, seg1;
259 
260  int const numIndices = static_cast<int>(mIndices.size());
261  for (int i0 = 0; i0 < numIndices; ++i0)
262  {
263  int i0p1 = (i0 + 1) % numIndices;
264  seg0.p[0] = mVertexPool[mIndices[i0]];
265  seg0.p[1] = mVertexPool[mIndices[i0p1]];
266 
267  int i1min = (i0 + 2) % numIndices;
268  int i1max = (i0 - 2 + numIndices) % numIndices;
269  for (int i1 = i1min; i1 <= i1max; ++i1)
270  {
271  int i1p1 = (i1 + 1) % numIndices;
272  seg1.p[0] = mVertexPool[mIndices[i1]];
273  seg1.p[1] = mVertexPool[mIndices[i1p1]];
274 
275  result = query(seg0, seg1);
276  if (result.intersect)
277  {
278  return false;
279  }
280  }
281  }
282  return true;
283 }
284 
285 template <typename Real>
287 {
288  Real sign = (mCounterClockwise ? (Real)1 : (Real)-1);
289  int const numIndices = static_cast<int>(mIndices.size());
290  for (int i = 0; i < numIndices; ++i)
291  {
292  int iPrev = (i + numIndices - 1) % numIndices;
293  int iNext = (i + 1) % numIndices;
294  Vector2<Real> vPrev = mVertexPool[mIndices[iPrev]];
295  Vector2<Real> vCurr = mVertexPool[mIndices[i]];
296  Vector2<Real> vNext = mVertexPool[mIndices[iNext]];
297  Vector2<Real> edge0 = vCurr - vPrev;
298  Vector2<Real> edge1 = vNext - vCurr;
299  Real test = sign * DotPerp(edge0, edge1);
300  if (test < (Real)0)
301  {
302  return false;
303  }
304  }
305  return true;
306 }
307 
308 }
std::vector< int > mIndices
Definition: GtePolygon2.h:94
Vector2< Real > ComputeVertexAverage() const
Definition: GtePolygon2.h:161
bool CounterClockwise() const
Definition: GtePolygon2.h:155
bool IsSimpleInternal() const
Definition: GtePolygon2.h:254
GLfloat GLfloat v1
Definition: glcorearb.h:812
Real ComputeArea() const
Definition: GtePolygon2.h:193
std::array< Vector< N, Real >, 2 > p
Definition: GteSegment.h:46
Vector2< Real > const * mVertexPool
Definition: GtePolygon2.h:92
Vector2< Real > const * GetVertexPool() const
Definition: GtePolygon2.h:137
GLsizei GLenum const void * indices
Definition: glcorearb.h:401
static Vector Zero()
Real DotPerp(Vector2< Real > const &v0, Vector2< Real > const &v1)
Definition: GteVector2.h:117
std::set< int > mVertices
Definition: GtePolygon2.h:93
Polygon2(Vector2< Real > const *vertexPool, int numIndices, int const *indices, bool counterClockwise)
Definition: GtePolygon2.h:100
GLfloat v0
Definition: glcorearb.h:811
bool IsConvex() const
Definition: GtePolygon2.h:234
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:790
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
bool IsConvexInternal() const
Definition: GtePolygon2.h:286
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:813
GLuint index
Definition: glcorearb.h:781
bool IsSimple() const
Definition: GtePolygon2.h:214
bool mCounterClockwise
Definition: GtePolygon2.h:95
GLuint64EXT * result
Definition: glext.h:10003
GLenum query
Definition: glext.h:2716
std::set< int > const & GetVertices() const
Definition: GtePolygon2.h:143
std::vector< int > const & GetIndices() const
Definition: GtePolygon2.h:149
Real ComputePerimeterLength() const
Definition: GtePolygon2.h:176


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01