43#ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_SIMPLE_POLYGON_2D_INL
44#define LASS_GUARDIAN_OF_INCLUSION_PRIM_SIMPLE_POLYGON_2D_INL
58template <
typename T,
class DP>
59SimplePolygon2D<T, DP>::SimplePolygon2D():
66template <
typename T,
class DP>
67template <
typename InputIterator>
68SimplePolygon2D<T, DP>::SimplePolygon2D(InputIterator iFirstVertex, InputIterator iLastVertex):
69 vertices_(iFirstVertex, iLastVertex)
75template <
typename T,
class DP>
76SimplePolygon2D<T, DP>::SimplePolygon2D(std::initializer_list<TPoint> init) :
85template <
typename T,
class DP>
86const typename SimplePolygon2D<T, DP>::TPoint&
89 LASS_ASSERT(iIndexOfVertex < vertices_.size());
90 return vertices_[iIndexOfVertex];
97template <
typename T,
class DP>
98typename SimplePolygon2D<T, DP>::TPoint&
101 LASS_ASSERT(iIndexOfVertex < vertices_.size());
102 return vertices_[iIndexOfVertex];
111template <
typename T,
class DP>
112const typename SimplePolygon2D<T, DP>::TPoint&
116 const size_t i = num::mod(iIndexOfVertex,
static_cast<unsigned>(vertices_.size()));
117 LASS_ASSERT(isInRange(i));
127template <
typename T,
class DP>
128typename SimplePolygon2D<T, DP>::TPoint&
132 const size_t i = num::mod(iIndexOfVertex,
static_cast<unsigned>(vertices_.size()));
133 LASS_ASSERT(isInRange(i));
143template <
typename T,
class DP>
144const typename SimplePolygon2D<T, DP>::TLineSegment
147 DP::enforceEdge(*
this, iIndexOfTailVertex);
148 return TLineSegment(
at(iIndexOfTailVertex),
at(iIndexOfTailVertex + 1));
155template <
typename T,
class DP>
156const typename SimplePolygon2D<T, DP>::TVector
159 DP::enforceEdge(*
this, iIndexOfTailVertex);
160 return at(iIndexOfTailVertex + 1) -
at(iIndexOfTailVertex);
169template <
typename T,
class DP>
172 vertices_.push_back(iVertex);
178template <
typename T,
class DP>
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);
192template <
typename T,
class DP>
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));
205template <
typename T,
class DP>
208 return vertices_.empty();
215template <
typename T,
class DP>
218 return vertices_.size();
239template <
typename T,
class DP>
240const typename SimplePolygon2D<T, DP>::TValue
243 DP::enforceSimple(*
this);
247 return TNumTraits::zero;
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)
255 const TVector v2 = vertices_[i2] - vertices_[0];
256 result += perpDot(v1, v2);
259 return result / T(2);
272template <
typename T,
class DP>
273const typename SimplePolygon2D<T, DP>::TValue
285template <
typename T,
class DP>
288 const TValue signArea = TDegeneratePolicy::enforceNonZeroSignedArea(*
this);
289 return signArea == TNumTraits::zero ?
oInvalid :
297template <
typename T,
class DP>
298const typename SimplePolygon2D<T, DP>::TValue
301 TValue result = TNumTraits::zero;
302 const size_t n =
size();
303 for (
size_t prevI = n - 1, i = 0; i < n; prevI = i++)
305 result += distance(vertices_[prevI], vertices_[i]);
317template <
typename T,
class DP>
318const typename SimplePolygon2D<T, DP>::TPointH
322 const size_t n =
size();
323 for (
size_t i = 0; i < n; ++i)
325 result += vertices_[i];
344template <
typename T,
class DP>
345const typename SimplePolygon2D<T, DP>::TPointH
348 const size_t n =
size();
355 for (
size_t prevI = n - 1, i = 0; i < n; prevI = i++)
357 const TValue triangleWeight = perpDot(vertices_[prevI].position(), vertices_[i].position());
358 const TPointH triangleCenter = vertices_[prevI] + vertices_[i] + TPoint();
359 result += triangleWeight * triangleCenter;
379template <
typename T,
class DP>
382 const int n =
static_cast<int>(
size());
389 for (
int i = 0; i < n; ++i)
391 const TLineSegment e =
edge(i);
398 const int m = i == 0 ? n - 1 : n;
399 for (
int j = i + 2; j < m; ++j)
431template <
typename T,
class DP>
434 DP::enforceSimple(*
this);
436 const int n =
static_cast<int>(
size());
443 TValue
sign = TNumTraits::zero;
444 for (
int i = 0; i < n; ++i)
447 if (
sign != s && s != TNumTraits::zero)
449 if (
sign == TNumTraits::zero)
476template <
typename T,
class DP>
479 DP::enforceSimple(*
this);
481 const TValue pd = perpDot(
vector(iIndexOfVertex - 1),
vector(iIndexOfVertex));
501template <
typename T,
class DP>
505 const TVector& p = iP.position();
507 const size_t npol =
size();
508 for (i = 0, j = npol-1; i < npol; j = i++)
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)
523template <
typename T,
class DP>
524Side SimplePolygon2D<T, DP>::classify(
const TPoint& iP)
const
533template <
typename T,
class DP>
536 std::reverse(vertices_.begin(), vertices_.end());
554template <
typename T,
class DP>
562 if (
at(i) ==
at(i + 1))
576 if (perpDot(
vector(i - 1),
vector(i)) == TNumTraits::zero)
604template <
typename T,
class DP>
620template <
typename T,
class DP>
621bool SimplePolygon2D<T, DP>::isInRange(
size_t iIndexOfVertex)
const
623 return iIndexOfVertex < size();
633template <
typename T,
typename DP,
typename PP>
637 for (
int k = 0, n =
static_cast<int>(poly.
size()); k < n; ++k)
651template <
typename T,
typename DP,
typename PP>
661template <
typename T,
typename DP1,
typename DP2>
662bool intersects(
const SimplePolygon2D<T, DP1>& a,
const SimplePolygon2D<T, DP2>& b)
664 for (
int k = 0, n =
static_cast<int>(a.
size()); k < n; ++k)
673 for (
size_t k = 0, n = a.
size(); k < n; ++k)
680 for (
size_t k = 0, n = b.
size(); k < n; ++k)
695template <
typename T,
class DP>
698 const size_t n = iPolygon.
size();
699 LASS_ENFORCE_STREAM(ioOStream) <<
"<SimplePolygon2D>\n";
700 for (
size_t i = 0; i < n; ++i)
702 ioOStream <<
"<vertex id='" <<
static_cast<unsigned long>(i) <<
"'>" << iPolygon[i] <<
"</vertex>\n";
704 ioOStream <<
"</SimplePolygon2D>\n";
711template <
typename T,
class DP>
712std::ostream& operator<<(std::ostream& ioOStream,
const SimplePolygon2D<T, DP>& iPolygon)
714 const size_t n = iPolygon.size();
715 LASS_ENFORCE_STREAM(ioOStream) <<
"{";
718 ioOStream << iPolygon[0];
720 for (
size_t i = 1; i < n; ++i)
722 ioOStream <<
", " << iPolygon[i];
730template <
typename T,
class DP>
732 const SimplePolygon2D<T, DP>& iPolygon)
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;
739 oOStream <<
"[" << iPolygon[0].y;
740 for (
size_t i=1;i<iPolygon.size();++i)
741 oOStream <<
"," << iPolygon[i].y;
743 oOStream <<
"'Color'," << oOStream.color() <<
");\n";
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.
T abs(const T &x)
if x < 0 return -x, else return x.
T sign(const T &x)
if x < 0 return -1, else if x > 0 return 1, else return 0.
set of geometrical primitives
Side
Different sides of a surface.
@ sOutside
outside the surface
@ sInside
inside the surface
Orientation
enumeration of clockwise versus counterclockwise
@ oClockWise
clockwise orientation
@ oCounterClockWise
counterclockwise orientation
@ rNone
operation has no answer, output arguments are meaningless
@ rOne
there's exactly one answer, 1 output argument contains the answer
Library for Assembled Shared Sources.