Library of Assembled Shared Sources
simple_polygon_2d.inl
Go to the documentation of this file.
1/** @file
2 * @author Bram de Greve (bram@cocamware.com)
3 * @author Tom De Muer (tom@cocamware.com)
4 *
5 * *** BEGIN LICENSE INFORMATION ***
6 *
7 * The contents of this file are subject to the Common Public Attribution License
8 * Version 1.0 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://lass.sourceforge.net/cpal-license. The License is based on the
11 * Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover
12 * use of software over a computer network and provide for limited attribution for
13 * the Original Developer. In addition, Exhibit A has been modified to be consistent
14 * with Exhibit B.
15 *
16 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
17 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
18 * language governing rights and limitations under the License.
19 *
20 * The Original Code is LASS - Library of Assembled Shared Sources.
21 *
22 * The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
23 * The Original Developer is the Initial Developer.
24 *
25 * All portions of the code written by the Initial Developer are:
26 * Copyright (C) 2004-2022 the Initial Developer.
27 * All Rights Reserved.
28 *
29 * Contributor(s):
30 *
31 * Alternatively, the contents of this file may be used under the terms of the
32 * GNU General Public License Version 2 or later (the GPL), in which case the
33 * provisions of GPL are applicable instead of those above. If you wish to allow use
34 * of your version of this file only under the terms of the GPL and not to allow
35 * others to use your version of this file under the CPAL, indicate your decision by
36 * deleting the provisions above and replace them with the notice and other
37 * provisions required by the GPL License. If you do not delete the provisions above,
38 * a recipient may use your version of this file under either the CPAL or the GPL.
39 *
40 * *** END LICENSE INFORMATION ***
41 */
42
43#ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_SIMPLE_POLYGON_2D_INL
44#define LASS_GUARDIAN_OF_INCLUSION_PRIM_SIMPLE_POLYGON_2D_INL
45
46#include "prim_common.h"
47#include "simple_polygon_2d.h"
48
49#include <cstddef>
50
51namespace lass
52{
53namespace prim
54{
55
56// --- public --------------------------------------------------------------------------------------
57
58template <typename T, class DP>
59SimplePolygon2D<T, DP>::SimplePolygon2D():
60 vertices_()
61{
62}
63
64
65
66template <typename T, class DP>
67template <typename InputIterator>
68SimplePolygon2D<T, DP>::SimplePolygon2D(InputIterator iFirstVertex, InputIterator iLastVertex):
69 vertices_(iFirstVertex, iLastVertex)
70{
71}
72
73
74
75template <typename T, class DP>
76SimplePolygon2D<T, DP>::SimplePolygon2D(std::initializer_list<TPoint> init) :
77 vertices_(init)
78{
79}
80
81
82
83/** return vertex of polygon by its index, not wrapped, no bounds check.
84 */
85template <typename T, class DP>
86const typename SimplePolygon2D<T, DP>::TPoint&
87SimplePolygon2D<T, DP>::operator[](size_t iIndexOfVertex) const
88{
89 LASS_ASSERT(iIndexOfVertex < vertices_.size());
90 return vertices_[iIndexOfVertex];
91}
92
93
94
95/** return vertex of polygon by its index, not wrapped, no bounds check.
96 */
97template <typename T, class DP>
98typename SimplePolygon2D<T, DP>::TPoint&
100{
101 LASS_ASSERT(iIndexOfVertex < vertices_.size());
102 return vertices_[iIndexOfVertex];
107/** return vertex of polygon by its index, but wrap around the bounds.
108 * this->at(-1) will return the same vertex as this->at(this->size() - 1);
109 * @throw an exception is thrown if polygon is empty
110 */
111template <typename T, class DP>
112const typename SimplePolygon2D<T, DP>::TPoint&
113SimplePolygon2D<T, DP>::at(int iIndexOfVertex) const
115 LASS_ENFORCE(!isEmpty());
116 const size_t i = num::mod(iIndexOfVertex, static_cast<unsigned>(vertices_.size()));
117 LASS_ASSERT(isInRange(i));
118 return vertices_[i];
122
123/** return vertex of polygon by its index, but wrap around the bounds.
124 * this->at(-1) will return the same vertex as this->at(this->size() - 1);
125 * @throw an exception is thrown if polygon is empty
126 */
127template <typename T, class DP>
128typename SimplePolygon2D<T, DP>::TPoint&
129SimplePolygon2D<T, DP>::at(int iIndexOfVertex)
131 LASS_ENFORCE(!isEmpty());
132 const size_t i = num::mod(iIndexOfVertex, static_cast<unsigned>(vertices_.size()));
133 LASS_ASSERT(isInRange(i));
135 return vertices_[i];
136}
137
138
139
140/** return the edge of the polygon between vertices at(iIndex) and at(iIndex + 1).
141 * @throw an exception is thrown if polygon has less than two vertices
142 */
143template <typename T, class DP>
144const typename SimplePolygon2D<T, DP>::TLineSegment
145SimplePolygon2D<T, DP>::edge(int iIndexOfTailVertex) const
146{
147 DP::enforceEdge(*this, iIndexOfTailVertex);
148 return TLineSegment(at(iIndexOfTailVertex), at(iIndexOfTailVertex + 1));
149}
150
151
152
153/** return the vector between vertices at(iIndex) and at(iIndex + 1)\
154 */
155template <typename T, class DP>
156const typename SimplePolygon2D<T, DP>::TVector
157SimplePolygon2D<T, DP>::vector(int iIndexOfTailVertex) const
158{
159 DP::enforceEdge(*this, iIndexOfTailVertex);
160 return at(iIndexOfTailVertex + 1) - at(iIndexOfTailVertex);
161}
162
163
164
165/** add a point at the "end" of the vertex list.
166 * this is almost the same as <tt>insert(0, iVertex)</tt> with the difference that
167 * <tt>add(iVertex)</tt> is also valid for empty polygons.
168 */
169template <typename T, class DP>
170void SimplePolygon2D<T, DP>::add(const TPoint& iVertex)
171{
172 vertices_.push_back(iVertex);
173}
174
175
176/** insert a vertex at iIndex (so it will sit before the current at(iIndex)).
177 */
178template <typename T, class DP>
179void SimplePolygon2D<T, DP>::insert(int iIndexOfVertex, const TPoint& iVertex)
180{
181 LASS_ENFORCE(!isEmpty());
182
183 const size_t i = num::mod(iIndexOfVertex, static_cast<unsigned>(vertices_.size()));
184 LASS_ASSERT(isInRange(i));
185 vertices_.insert(vertices_.begin() + static_cast<std::ptrdiff_t>(i), iVertex);
186}
187
188
189
190/** remove the vertex at(iIndex)
191 */
192template <typename T, class DP>
193void SimplePolygon2D<T, DP>::erase(int iIndexOfVertex)
194{
195 LASS_ENFORCE(!isEmpty());
196 const size_t i = num::mod(iIndexOfVertex, static_cast<unsigned>(vertices_.size()));
197 LASS_ASSERT(isInRange(i));
198 vertices_.erase(vertices_.begin() + static_cast<std::ptrdiff_t>(i));
199}
200
201
202
203/** return true if polygon has no vertices
204 */
205template <typename T, class DP>
207{
208 return vertices_.empty();
209}
210
211
212
213/** return number of vertices
214 */
215template <typename T, class DP>
217{
218 return vertices_.size();
219}
220
221
222
223/** return signed polygon area.
224 *
225 * <i>The area of a convex polygon is defined to be positive if the points are arranged in a
226 * counterclockwise order, and negative if they are in clockwise order.</i>,
227 * Eric W. Weisstein. "Polygon Area." From MathWorld--A Wolfram Web Resource.
228 * http://mathworld.wolfram.com/PolygonArea.html
229 *
230 * @par Algorithm:
231 * comp.graphics.algorithms Frequently Asked Questions:
232 * Subject 2.01: "How do I find the area of a polygon?"
233 * http://www.faqs.org/faqs/graphics/algorithms-faq/
234 *
235 * https://www.johndcook.com/blog/2018/09/26/polygon-area/
236 *
237 * @warning polygon must be simple accoring degenerate policy.
238 */
239template <typename T, class DP>
240const typename SimplePolygon2D<T, DP>::TValue
242{
243 DP::enforceSimple(*this);
244
245 if (size() < 3)
246 {
247 return TNumTraits::zero;
248 }
249
250 TValue result = TNumTraits::zero;
251 const size_t n = size();
252 TVector v1 = vertices_[1] - vertices_[0];
253 for (size_t i2 = 2; i2 < n; ++i2)
254 {
255 const TVector v2 = vertices_[i2] - vertices_[0];
256 result += perpDot(v1, v2);
257 v1 = v2;
258 }
259 return result / T(2);
260}
261
262
263
264/** return area of the polygons surface.
265 *
266 * <i>The area of a surface is the amount of material needed to "cover" it completely</i>,
267 * Eric W. Weisstein. "Area." From MathWorld--A Wolfram Web Resource.
268 * http://mathworld.wolfram.com/Area.html
269 *
270 * @warning polygon must be simple accoring @a DegeneratePolicy.
271 */
272template <typename T, class DP>
273const typename SimplePolygon2D<T, DP>::TValue
275{
276 return num::abs(signedArea()); // DP::enforceSimple(*this);
277}
278
279
280
281/** return orientation of polygon.
282 *
283 * @warning polygon must be simple accoring @a DegeneratePolicy.
284 */
285template <typename T, class DP>
287{
288 const TValue signArea = TDegeneratePolicy::enforceNonZeroSignedArea(*this); // DP::enforceSimple(*this);
289 return signArea == TNumTraits::zero ? oInvalid :
290 (signArea < TNumTraits::zero ? oClockWise : oCounterClockWise);
291}
292
293
294
295/** return sum of the lengths of all edges
296 */
297template <typename T, class DP>
298const typename SimplePolygon2D<T, DP>::TValue
300{
301 TValue result = TNumTraits::zero;
302 const size_t n = size();
303 for (size_t prevI = n - 1, i = 0; i < n; prevI = i++)
304 {
305 result += distance(vertices_[prevI], vertices_[i]);
306 }
307 return result;
308}
309
310
311
312/** return the barycenter of all vertices.
313 * The vertex centroid is the homogenous sum of all vertices.
314 *
315 * @warning for non-convex polygons, it's NOT guaranteed that this center is inside the polygon.
316 */
317template <typename T, class DP>
318const typename SimplePolygon2D<T, DP>::TPointH
320{
321 TPointH result;
322 const size_t n = size();
323 for (size_t i = 0; i < n; ++i)
324 {
325 result += vertices_[i];
326 }
327 return result;
328}
329
330
331
332/** return the centroid of the filled polygon.
333 *
334 * Eric W. Weisstein. "Geometric Centroid." From MathWorld--A Wolfram Web Resource.
335 * http://mathworld.wolfram.com/GeometricCentroid.html
336 *
337 * @par Algorithm:
338 * comp.graphics.algorithms Frequently Asked Questions:
339 * Subject 2.02: "How can the centroid of a polygon be computed?"
340 * http://www.faqs.org/faqs/graphics/algorithms-faq/
341 *
342 * @warning for non-convex polygons, it's NOT guaranteed that this center is inside the polygon.
343 */
344template <typename T, class DP>
345const typename SimplePolygon2D<T, DP>::TPointH
347{
348 const size_t n = size();
349 if (n < 3)
350 {
351 return vertexCentroid();
352 }
353
354 TPointH result;
355 for (size_t prevI = n - 1, i = 0; i < n; prevI = i++)
356 {
357 const TValue triangleWeight = perpDot(vertices_[prevI].position(), vertices_[i].position());
358 const TPointH triangleCenter = vertices_[prevI] + vertices_[i] + TPoint();
359 result += triangleWeight * triangleCenter;
360 }
361 return result;
362}
363
364
365
366/** return true if polygon is simple, false if not.
367 *
368 * <i>A polygon P is said to be simple (or Jordan) if the only points of the plane belonging to
369 * two polygon edges of P are the polygon vertices of P. Such a polygon has a well defined
370 * interior and exterior. Simple polygons are topologically equivalent to a disk.</i>,
371 * Eric W. Weisstein. "Simple Polygon." From MathWorld--A Wolfram Web Resource.
372 * http://mathworld.wolfram.com/SimplePolygon.html
373 *
374 * A polygon with less than four vertices is always simple.
375 *
376 * @warning this is a brute force test. we simple test for all edges if they are not intersecting
377 * Hence, this is O(n^2).
378 */
379template <typename T, class DP>
381{
382 const int n = static_cast<int>(size());
383 LASS_ASSERT(n >= 0);
384 if (n < 4)
385 {
386 return true;
387 }
388
389 for (int i = 0; i < n; ++i)
390 {
391 const TLineSegment e = edge(i);
392 TValue t1;
393 TValue t2;
394 if (intersect(e, edge(i + 1), t1, t2) != rOne)
395 {
396 return false;
397 }
398 const int m = i == 0 ? n - 1 : n;
399 for (int j = i + 2; j < m; ++j)
400 {
401 if (intersect(e, edge(j), t1, t2) != rNone)
402 {
403 return false;
404 }
405 }
406 }
407
408 return true;
409}
410
411
412
413/** return true if polygon is convex, false if not.
414 *
415 * <i>A planar polygon is convex if it contains all the line segments connecting any pair of its
416 * points. Thus, for example, a regular pentagon is convex, while an indented pentagon is not.
417 * A planar polygon that is not convex is said to be a concave polygon</i>,
418 * Eric W. Weisstein. "Convex Polygon." From MathWorld--A Wolfram Web Resource.
419 * http://mathworld.wolfram.com/ConvexPolygon.html
420 *
421 * A simple polygon is convex if all the cross products of adjacent edges will be the same sign
422 * (we ignore zero cross products of colinear edges, only + or - are taken in account), a concave polygon
423 * will have a mixture of cross product signs.
424 *
425 * A polygon with less than three vertices is always convex. A polygon with all coincident.
426 * vertices is considered convex if DegeneratePolicy allows this.
427 *
428 * @warning polygon must be simple and should not have coincident vertices, according
429 * @a DegeneratePolicy.
430 */
431template <typename T, class DP>
433{
434 DP::enforceSimple(*this);
435
436 const int n = static_cast<int>(size());
437 LASS_ASSERT(n >= 0);
438 if (n < 3)
439 {
440 return true;
441 }
442
443 TValue sign = TNumTraits::zero;
444 for (int i = 0; i < n; ++i)
445 {
446 const TValue s = num::sign(perpDot(vector(i - 1), vector(i))); // Ax(-B) = BxA
447 if (sign != s && s != TNumTraits::zero)
448 {
449 if (sign == TNumTraits::zero)
450 {
451 sign = s;
452 }
453 else
454 {
455 return false;
456 }
457 }
458 }
459
460 return true;
461}
462
463
464
465/** return true if inner angle of vertex is reflex (is > 180 degrees).
466 *
467 * <i>Reflect Angle: An angle more than 180�</i>,
468 * Eric W. Weisstein. "Reflex Angle." From MathWorld--A Wolfram Web Resource.
469 * http://mathworld.wolfram.com/ReflexAngle.html
470 *
471 * test if signedArea() and perdDot(...) have different sign.
472 * if one of them is zero, it will return false by default.
473 *
474 * @warning polygon must be simple accoring @a DegeneratePolicy.
475 */
476template <typename T, class DP>
477bool SimplePolygon2D<T, DP>::isReflex(int iIndexOfVertex) const
478{
479 DP::enforceSimple(*this);
480
481 const TValue pd = perpDot(vector(iIndexOfVertex - 1), vector(iIndexOfVertex)); // Ax(-B) = BxA
482 LASS_ASSERT(!isEmpty()); // vector(i) should enforce this
483 return signedArea() * pd < TNumTraits::zero;
484}
485
486
487
488/** return true when a point is inside or on a polygon.
489 *
490 * When a point lies on a polygon edge the answer can either be true or false but in a way that
491 * for a meshing the answer will only be true for one polygon. More precise: for polygons sharing
492 * an edge only one of them will return true for a point on the edge.
493 * For an explanation of how this exactly works:
494 * http://www.ecse.rpi.edu/Homepages/wrf/geom/pnpoly.html (Wm Randolph Franklin)
495 *
496 * @par Algorithm:
497 * comp.graphics.algorithms Frequently Asked Questions:
498 * Subject 2.03: "How do I find if a point lies within a polygon?"
499 * http://www.faqs.org/faqs/graphics/algorithms-faq/
500 */
501template <typename T, class DP>
502bool SimplePolygon2D<T, DP>::contains(const TPoint& iP) const
503{
504 size_t i, j;
505 const TVector& p = iP.position();
506 bool c = false;
507 const size_t npol = size();
508 for (i = 0, j = npol-1; i < npol; j = i++)
509 {
510 const TVector& a = vertices_[i].position();
511 const TVector& b = vertices_[j].position();
512 if (((a.y <= p.y && p.y < b.y) || (b.y <= p.y && p.y < a.y)) &&
513 p.x < (b.x - a.x) * (p.y - a.y) / (b.y - a.y) + a.x)
514 {
515 c = !c;
516 }
517 }
518 return c;
519}
520
521
522
523template <typename T, class DP>
524Side SimplePolygon2D<T, DP>::classify(const TPoint& iP) const
525{
526 return contains(iP) ? sInside : sOutside;
527}
528
529
530
531/** flip orientation of polygon.
532 */
533template <typename T, class DP>
535{
536 std::reverse(vertices_.begin(), vertices_.end());
537}
538
539
540
541/** fixes degenerate polygons as far as possible.
542 *
543 * things that can be repared are:
544 * - coincident vertices: if two or more adjacent vertices are coincident, they can be reduced to
545 * one vertex.
546 * - colinear edges: if two or more adjacent edges are colinear, they can be merged to one edge.
547 * - zero area: if a polygon has no area, this is pretty much the same as an @a empty polygon.
548 * All vertices will be removed.
549 *
550 * Things that can't repared (and will cause an exception to be thrown) are:
551 * - non-simple polygons: there's no way we can repare polygons that are not simple, so we don't
552 * even try to! An exception is thrown regardless the @a DegeneratePolicy.
553 */
554template <typename T, class DP>
556{
557 // remove coincident vertices
558 //
559 int i = 0;
560 while (i < size())
561 {
562 if (at(i) == at(i + 1))
563 {
564 erase(i);
565 }
566 else
567 {
568 ++i;
569 }
570 }
571
572 // merge colinear edges
573 //
574 while (size() > 2 && i < size())
575 {
576 if (perpDot(vector(i - 1), vector(i)) == TNumTraits::zero)
577 {
578 erase(i);
579 }
580 else
581 {
582 ++i;
583 }
584 }
585
586 // by now there are no coincident points that can trigger policy predicates in @c isSimple()
587 // so exceptions are not thrown before we get the change to fix it.
588 //
589 LASS_ENFORCE(isSimple());
590
591 // check zero area of polygons in two ways: literally, and by the knowledge that less than
592 // three vertices is zero area for sure.
593 //
594 if (size() < 3 || signedArea() == TNumTraits::zero)
595 {
596 vertices_.clear();
597 }
598}
599
600
601
602/** a simple polygon is valid if it is not degenerate.
603 */
604template <typename T, class DP>
606{
607 return size() >= 3 && isSimple() && signedArea() != TNumTraits::zero;
608}
609
610
611
612// --- protected -----------------------------------------------------------------------------------
613
614
615
616// --- private -------------------------------------------------------------------------------------
617
618/** return if index of vertex is in range of the std::vector
619 */
620template <typename T, class DP>
621bool SimplePolygon2D<T, DP>::isInRange(size_t iIndexOfVertex) const
622{
623 return iIndexOfVertex < size();
624}
625
626
627
628// --- free ----------------------------------------------------------------------------------------
629
630/** @relates lass::prim::SimplePolygon2D
631 * O(N) with N is size of poly
632 */
633template <typename T, typename DP, typename PP>
634bool intersects(const SimplePolygon2D<T, DP>& poly, const LineSegment2D<T, PP>& segment)
635{
636 // silly algorithms go first ...
637 for (int k = 0, n = static_cast<int>(poly.size()); k < n; ++k)
638 {
639 if (intersects(segment, poly.edge(k)))
640 {
641 return true;
642 }
643 }
644 return false;
645}
646
647
648/** @relates lass::prim::SimplePolygon2D
649 * O(N) with N is size of poly
650 */
651template <typename T, typename DP, typename PP>
652bool intersects(const LineSegment2D<T, PP>& segment, const SimplePolygon2D<T, DP>& poly)
653{
654 return intersects(poly, segment);
655}
656
657
658/** @relates lass::prim::SimplePolygon2D
659 * O(M+N) with M and N the sizes of the polygons
660 */
661template <typename T, typename DP1, typename DP2>
662bool intersects(const SimplePolygon2D<T, DP1>& a, const SimplePolygon2D<T, DP2>& b)
663{
664 for (int k = 0, n = static_cast<int>(a.size()); k < n; ++k)
665 {
666 if (intersects(b, a.edge(k)))
667 {
668 return true;
669 }
670 }
671
672 // special cases ... a could be completely inside b, or the other way around.
673 for (size_t k = 0, n = a.size(); k < n; ++k)
674 {
675 if (b.contains(a[k]))
676 {
677 return true;
678 }
679 }
680 for (size_t k = 0, n = b.size(); k < n; ++k)
681 {
682 if (a.contains(b[k]))
683 {
684 return true;
685 }
686 }
687
688 return false;
689}
690
691
692
693/** @relates lass::prim::SimplePolygon2D
694 */
695template <typename T, class DP>
696io::XmlOStream& operator<<(io::XmlOStream& ioOStream, const SimplePolygon2D<T, DP>& iPolygon)
697{
698 const size_t n = iPolygon.size();
699 LASS_ENFORCE_STREAM(ioOStream) << "<SimplePolygon2D>\n";
700 for (size_t i = 0; i < n; ++i)
701 {
702 ioOStream << "<vertex id='" << static_cast<unsigned long>(i) << "'>" << iPolygon[i] << "</vertex>\n";
703 }
704 ioOStream << "</SimplePolygon2D>\n";
705 return ioOStream;
706}
707
708
709/** @relates lass::prim::SimplePolygon2D
710 */
711template <typename T, class DP>
712std::ostream& operator<<(std::ostream& ioOStream, const SimplePolygon2D<T, DP>& iPolygon)
713{
714 const size_t n = iPolygon.size();
715 LASS_ENFORCE_STREAM(ioOStream) << "{";
716 if (n > 0)
717 {
718 ioOStream << iPolygon[0];
719 }
720 for (size_t i = 1; i < n; ++i)
721 {
722 ioOStream << ", " << iPolygon[i];
723 }
724 ioOStream << "}";
725 return ioOStream;
726}
727
728/** @relates lass::prim::SimplePolygon2D
729 */
730template <typename T, class DP>
732 const SimplePolygon2D<T, DP>& iPolygon)
733{
734 LASS_ENFORCE_STREAM(oOStream) << "lasthandle = patch(";
735 oOStream << "[" << iPolygon[0].x;
736 for (size_t i=1;i<iPolygon.size();++i)
737 oOStream << "," << iPolygon[i].x;
738 oOStream << "],";
739 oOStream << "[" << iPolygon[0].y;
740 for (size_t i=1;i<iPolygon.size();++i)
741 oOStream << "," << iPolygon[i].y;
742 oOStream << "],";
743 oOStream << "'Color'," << oOStream.color() << ");\n";
744 return oOStream;
745}
746
747}
748
749}
750
751#endif
752
753// EOF
Output stream for writing a selection of geometric primitives to matlab M files.
Output stream for writing a selection of geometric primitives to XML files.
convex or concave polygon in 2D (not selfintersecting, no holes)
const TPointH vertexCentroid() const
return the barycenter of all vertices.
bool isSimple() const
return true if polygon is simple, false if not.
void flip()
flip orientation of polygon.
size_t size() const
return number of vertices
bool intersects(const LineSegment2D< T, PP > &segment, const SimplePolygon2D< T, DP > &poly)
O(N) with N is size of poly.
void erase(int iIndexOfVertex)
remove the vertex at(iIndex)
bool isValid() const
a simple polygon is valid if it is not degenerate.
bool intersects(const SimplePolygon2D< T, DP > &poly, const LineSegment2D< T, PP > &segment)
O(N) with N is size of poly.
const TValue perimeter() const
return sum of the lengths of all edges
const TPoint & at(int iIndexOfVertex) const
return vertex of polygon by its index, but wrap around the bounds.
const TValue area() const
return area of the polygons surface.
const TPointH surfaceCentroid() const
return the centroid of the filled polygon.
bool isReflex(int iIndexOfVertex) const
return true if inner angle of vertex is reflex (is > 180 degrees).
Result intersect(const SimplePolygon2D< T, DP > &polygon, const Ray2D< T, NP, PP > &ray, T &t, const T &tMin=T())
Find the intersection of a ray and a triangle by their parameter t on the ray.
Orientation orientation() const
return orientation of polygon.
bool isConvex() const
return true if polygon is convex, false if not.
void insert(int iIndexOfVertex, const TPoint &iVertex)
insert a vertex at iIndex (so it will sit before the current at(iIndex)).
void add(const TPoint &iVertex)
add a point at the "end" of the vertex list.
const TLineSegment edge(int iIndexOfTailVertex) const
return the edge of the polygon between vertices at(iIndex) and at(iIndex + 1).
const TVector vector(int iIndexOfTailVertex) const
return the vector between vertices at(iIndex) and at(iIndex + 1)\
const TValue signedArea() const
return signed polygon area.
const TPoint & operator[](size_t iIndexOfVertex) const
return vertex of polygon by its index, not wrapped, no bounds check.
void fixDegenerate()
fixes degenerate polygons as far as possible.
bool contains(const TPoint &iP) const
return true when a point is inside or on a polygon.
bool intersects(const SimplePolygon2D< T, DP1 > &a, const SimplePolygon2D< T, DP2 > &b)
O(M+N) with M and N the sizes of the polygons.
T sign(const T &x)
if x < 0 return -1, else if x > 0 return 1, else return 0.
Definition basic_ops.h:153
T abs(const T &x)
if x < 0 return -x, else return x.
Definition basic_ops.h:145
T sign(const T &x)
if x < 0 return -1, else if x > 0 return 1, else return 0.
set of geometrical primitives
Definition aabb_2d.h:81
Side
Different sides of a surface.
Definition side.h:79
@ sOutside
outside the surface
Definition side.h:86
@ sInside
inside the surface
Definition side.h:85
Orientation
enumeration of clockwise versus counterclockwise
Definition orientation.h:58
@ oClockWise
clockwise orientation
Definition orientation.h:60
@ oInvalid
invalid state
Definition orientation.h:59
@ oCounterClockWise
counterclockwise orientation
Definition orientation.h:61
@ rNone
operation has no answer, output arguments are meaningless
Definition result.h:76
@ rOne
there's exactly one answer, 1 output argument contains the answer
Definition result.h:77
Library for Assembled Shared Sources.
Definition config.h:53