diff --git a/src/libnest2d/include/libnest2d/geometry_traits.hpp b/src/libnest2d/include/libnest2d/geometry_traits.hpp index 345252f12..8b87229c0 100644 --- a/src/libnest2d/include/libnest2d/geometry_traits.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits.hpp @@ -30,11 +30,11 @@ template struct ShapeTag { using Type = typename Shape::Tag; }; template using Tag = typename ShapeTag>::Type; /// Meta function to derive the contour type for a polygon which could be itself -template struct ContourType { using Type = RawShape; }; +template struct ContourType { using Type = S; }; -/// TContour instead of `typename ContourType::type` -template -using TContour = typename ContourType>::Type; +/// TContour instead of `typename ContourType::type` +template +using TContour = typename ContourType>::Type; /// Getting the type of point structure used by a shape. template struct PointType { @@ -83,12 +83,12 @@ template struct ComputeType { template using TCompute = typename ComputeType>::Type; /// A meta function to derive a container type for holes in a polygon -template -struct HolesContainer { using Type = std::vector>; }; +template +struct HolesContainer { using Type = std::vector>; }; -/// Shorthand for `typename HolesContainer::Type` -template -using THolesContainer = typename HolesContainer>::Type; +/// Shorthand for `typename HolesContainer::Type` +template +using THolesContainer = typename HolesContainer>::Type; /* * TContour, TPoint, TCoord and TCompute should be usable for any type for which @@ -132,7 +132,7 @@ enum class Orientation { COUNTER_CLOCKWISE }; -template +template struct OrientationType { // Default Polygon orientation that the library expects @@ -146,45 +146,46 @@ template inline /*constexpr*/ bool is_clockwise() { /** * \brief A point pair base class for other point pairs (segment, box, ...). - * \tparam RawPoint The actual point type to use. + * \tparam P The actual point type to use. */ -template +template struct PointPair { - RawPoint p1; - RawPoint p2; + P p1; + P p2; }; /** * \brief An abstraction of a box; */ -template -class _Box: PointPair { - using PointPair::p1; - using PointPair::p2; +template +class _Box: PointPair

{ + using PointPair

::p1; + using PointPair

::p2; public: using Tag = BoxTag; - using PointType = RawPoint; + using PointType = P; - inline _Box() = default; - inline _Box(const RawPoint& p, const RawPoint& pp): - PointPair({p, pp}) {} + inline _Box(const P& p = {TCoord

(0), TCoord

(0)}); + inline _Box(const P& p, const P& pp): + PointPair

({p, pp}) {} + + inline _Box(TCoord

width, TCoord

height, + const P& p = {TCoord

(0), TCoord

(0)});/*: + _Box(p, P{width, height}) {}*/ - inline _Box(TCoord width, TCoord height): - _Box(RawPoint{0, 0}, RawPoint{width, height}) {} + inline const P& minCorner() const BP2D_NOEXCEPT { return p1; } + inline const P& maxCorner() const BP2D_NOEXCEPT { return p2; } - inline const RawPoint& minCorner() const BP2D_NOEXCEPT { return p1; } - inline const RawPoint& maxCorner() const BP2D_NOEXCEPT { return p2; } + inline P& minCorner() BP2D_NOEXCEPT { return p1; } + inline P& maxCorner() BP2D_NOEXCEPT { return p2; } - inline RawPoint& minCorner() BP2D_NOEXCEPT { return p1; } - inline RawPoint& maxCorner() BP2D_NOEXCEPT { return p2; } + inline TCoord

width() const BP2D_NOEXCEPT; + inline TCoord

height() const BP2D_NOEXCEPT; - inline TCoord width() const BP2D_NOEXCEPT; - inline TCoord height() const BP2D_NOEXCEPT; + inline P center() const BP2D_NOEXCEPT; - inline RawPoint center() const BP2D_NOEXCEPT; - - template> + template> inline Unit area() const BP2D_NOEXCEPT { return Unit(width())*height(); } @@ -194,20 +195,20 @@ template struct PointType<_Box> { using Type = typename _Box::PointType; }; -template +template class _Circle { - RawPoint center_; + P center_; double radius_ = 0; public: using Tag = CircleTag; - using PointType = RawPoint; + using PointType = P; _Circle() = default; - _Circle(const RawPoint& center, double r): center_(center), radius_(r) {} + _Circle(const P& center, double r): center_(center), radius_(r) {} - inline const RawPoint& center() const BP2D_NOEXCEPT { return center_; } - inline void center(const RawPoint& c) { center_ = c; } + inline const P& center() const BP2D_NOEXCEPT { return center_; } + inline void center(const P& c) { center_ = c; } inline double radius() const BP2D_NOEXCEPT { return radius_; } inline void radius(double r) { radius_ = r; } @@ -224,38 +225,38 @@ template struct PointType<_Circle> { /** * \brief An abstraction of a directed line segment with two points. */ -template -class _Segment: PointPair { - using PointPair::p1; - using PointPair::p2; +template +class _Segment: PointPair

{ + using PointPair

::p1; + using PointPair

::p2; mutable Radians angletox_ = std::nan(""); public: - using PointType = RawPoint; + using PointType = P; inline _Segment() = default; - inline _Segment(const RawPoint& p, const RawPoint& pp): - PointPair({p, pp}) {} + inline _Segment(const P& p, const P& pp): + PointPair

({p, pp}) {} /** * @brief Get the first point. * @return Returns the starting point. */ - inline const RawPoint& first() const BP2D_NOEXCEPT { return p1; } + inline const P& first() const BP2D_NOEXCEPT { return p1; } /** * @brief The end point. * @return Returns the end point of the segment. */ - inline const RawPoint& second() const BP2D_NOEXCEPT { return p2; } + inline const P& second() const BP2D_NOEXCEPT { return p2; } - inline void first(const RawPoint& p) BP2D_NOEXCEPT + inline void first(const P& p) BP2D_NOEXCEPT { angletox_ = std::nan(""); p1 = p; } - inline void second(const RawPoint& p) BP2D_NOEXCEPT { + inline void second(const P& p) BP2D_NOEXCEPT { angletox_ = std::nan(""); p2 = p; } @@ -263,7 +264,7 @@ public: inline Radians angleToXaxis() const; /// The length of the segment in the measure of the coordinate system. - template> inline Unit sqlength() const; + template> inline Unit sqlength() const; }; @@ -275,42 +276,42 @@ template struct PointType<_Segment> { // used in friend declarations. namespace pointlike { -template -inline TCoord x(const RawPoint& p) +template +inline TCoord

x(const P& p) { return p.x(); } -template -inline TCoord y(const RawPoint& p) +template +inline TCoord

y(const P& p) { return p.y(); } -template -inline TCoord& x(RawPoint& p) +template +inline TCoord

& x(P& p) { return p.x(); } -template -inline TCoord& y(RawPoint& p) +template +inline TCoord

& y(P& p) { return p.y(); } -template> -inline Unit squaredDistance(const RawPoint& p1, const RawPoint& p2) +template> +inline Unit squaredDistance(const P& p1, const P& p2) { auto x1 = Unit(x(p1)), y1 = Unit(y(p1)), x2 = Unit(x(p2)), y2 = Unit(y(p2)); Unit a = (x2 - x1), b = (y2 - y1); return a * a + b * b; } -template -inline double distance(const RawPoint& p1, const RawPoint& p2) +template +inline double distance(const P& p1, const P& p2) { - return std::sqrt(squaredDistance(p1, p2)); + return std::sqrt(squaredDistance(p1, p2)); } // create perpendicular vector @@ -339,9 +340,9 @@ inline Unit magnsq(const Pt& p) return Unit(x(p)) * x(p) + Unit(y(p)) * y(p); } -template> +template> inline std::pair horizontalDistance( - const RawPoint& p, const _Segment& s) + const P& p, const _Segment

& s) { namespace pl = pointlike; auto x = Unit(pl::x(p)), y = Unit(pl::y(p)); @@ -364,9 +365,9 @@ inline std::pair horizontalDistance( return {ret, true}; } -template> +template> inline std::pair verticalDistance( - const RawPoint& p, const _Segment& s) + const P& p, const _Segment

& s) { namespace pl = pointlike; auto x = Unit(pl::x(p)), y = Unit(pl::y(p)); @@ -390,42 +391,42 @@ inline std::pair verticalDistance( } } -template -TCoord _Box::width() const BP2D_NOEXCEPT +template +TCoord

_Box

::width() const BP2D_NOEXCEPT { return pointlike::x(maxCorner()) - pointlike::x(minCorner()); } -template -TCoord _Box::height() const BP2D_NOEXCEPT +template +TCoord

_Box

::height() const BP2D_NOEXCEPT { return pointlike::y(maxCorner()) - pointlike::y(minCorner()); } -template -TCoord getX(const RawPoint& p) { return pointlike::x(p); } +template +TCoord

getX(const P& p) { return pointlike::x

(p); } -template -TCoord getY(const RawPoint& p) { return pointlike::y(p); } +template +TCoord

getY(const P& p) { return pointlike::y

(p); } -template -void setX(RawPoint& p, const TCoord& val) +template +void setX(P& p, const TCoord

& val) { - pointlike::x(p) = val; + pointlike::x

(p) = val; } -template -void setY(RawPoint& p, const TCoord& val) +template +void setY(P& p, const TCoord

& val) { - pointlike::y(p) = val; + pointlike::y

(p) = val; } -template -inline Radians _Segment::angleToXaxis() const +template +inline Radians _Segment

::angleToXaxis() const { if(std::isnan(static_cast(angletox_))) { - TCoord dx = getX(second()) - getX(first()); - TCoord dy = getY(second()) - getY(first()); + TCoord

dx = getX(second()) - getX(first()); + TCoord

dy = getY(second()) - getY(first()); double a = std::atan2(dy, dx); auto s = std::signbit(a); @@ -436,21 +437,48 @@ inline Radians _Segment::angleToXaxis() const return angletox_; } -template +template template -inline Unit _Segment::sqlength() const +inline Unit _Segment

::sqlength() const { - return pointlike::squaredDistance(first(), second()); + return pointlike::squaredDistance(first(), second()); } -template -inline RawPoint _Box::center() const BP2D_NOEXCEPT { +template +enable_if_t::value, T> modulo(const T &v, const T &m) +{ + return 0; +} +template +enable_if_t::value, T> modulo(const T &v, const T &m) +{ + return v % m; +} + +template +inline _Box

::_Box(TCoord

width, TCoord

height, const P & center) : + PointPair

({center - P{width / 2, height / 2}, + center + P{width / 2, height / 2} + + P{modulo(width, TCoord

(2)), + modulo(height, TCoord

(2))}}) {} + +template +inline _Box

::_Box(const P& center) { + using C = TCoord

; + TCoord

M = std::max(getX(center), getY(center)) - + std::numeric_limits::lowest(); + maxCorner() = center + P{M, M}; + minCorner() = center - P{M, M}; +} + +template +inline P _Box

::center() const BP2D_NOEXCEPT { auto& minc = minCorner(); auto& maxc = maxCorner(); - using Coord = TCoord; + using Coord = TCoord

; - RawPoint ret = { // No rounding here, we dont know if these are int coords + P ret = { // No rounding here, we dont know if these are int coords Coord( (getX(minc) + getX(maxc)) / Coord(2) ), Coord( (getY(minc) + getY(maxc)) / Coord(2) ) }; @@ -467,76 +495,76 @@ enum class Formats { // used in friend declarations and can be aliased at class scope. namespace shapelike { -template -inline RawShape create(const TContour& contour, - const THolesContainer& holes) +template +inline S create(const TContour& contour, + const THolesContainer& holes) { - return RawShape(contour, holes); + return S(contour, holes); } -template -inline RawShape create(TContour&& contour, - THolesContainer&& holes) +template +inline S create(TContour&& contour, + THolesContainer&& holes) { - return RawShape(contour, holes); + return S(contour, holes); } -template -inline RawShape create(const TContour& contour) +template +inline S create(const TContour& contour) { - return create(contour, {}); + return create(contour, {}); } -template -inline RawShape create(TContour&& contour) +template +inline S create(TContour&& contour) { - return create(contour, {}); + return create(contour, {}); } -template -inline THolesContainer& holes(RawShape& /*sh*/) +template +inline THolesContainer& holes(S& /*sh*/) { - static THolesContainer empty; + static THolesContainer empty; return empty; } -template -inline const THolesContainer& holes(const RawShape& /*sh*/) +template +inline const THolesContainer& holes(const S& /*sh*/) { - static THolesContainer empty; + static THolesContainer empty; return empty; } -template -inline TContour& hole(RawShape& sh, unsigned long idx) +template +inline TContour& hole(S& sh, unsigned long idx) { return holes(sh)[idx]; } -template -inline const TContour& hole(const RawShape& sh, unsigned long idx) +template +inline const TContour& hole(const S& sh, unsigned long idx) { return holes(sh)[idx]; } -template -inline size_t holeCount(const RawShape& sh) +template +inline size_t holeCount(const S& sh) { return holes(sh).size(); } -template -inline TContour& contour(RawShape& sh) +template +inline TContour& contour(S& sh) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::contour() unimplemented!"); return sh; } -template -inline const TContour& contour(const RawShape& sh) +template +inline const TContour& contour(const S& sh) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::contour() unimplemented!"); return sh; } @@ -548,71 +576,71 @@ inline void reserve(RawPath& p, size_t vertex_capacity, const PathTag&) p.reserve(vertex_capacity); } -template -inline void addVertex(RawShape& sh, const PathTag&, Args...args) +template +inline void addVertex(S& sh, const PathTag&, Args...args) { sh.emplace_back(std::forward(args)...); } -template -inline void foreachVertex(RawShape& sh, Fn fn, const PathTag&) { +template +inline void foreachVertex(S& sh, Fn fn, const PathTag&) { std::for_each(sh.begin(), sh.end(), fn); } -template -inline typename RawShape::iterator begin(RawShape& sh, const PathTag&) +template +inline typename S::iterator begin(S& sh, const PathTag&) { return sh.begin(); } -template -inline typename RawShape::iterator end(RawShape& sh, const PathTag&) +template +inline typename S::iterator end(S& sh, const PathTag&) { return sh.end(); } -template -inline typename RawShape::const_iterator -cbegin(const RawShape& sh, const PathTag&) +template +inline typename S::const_iterator +cbegin(const S& sh, const PathTag&) { return sh.cbegin(); } -template -inline typename RawShape::const_iterator -cend(const RawShape& sh, const PathTag&) +template +inline typename S::const_iterator +cend(const S& sh, const PathTag&) { return sh.cend(); } -template -inline std::string toString(const RawShape& /*sh*/) +template +inline std::string toString(const S& /*sh*/) { return ""; } -template -inline std::string serialize(const RawShape& /*sh*/, double /*scale*/=1) +template +inline std::string serialize(const S& /*sh*/, double /*scale*/=1) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::serialize() unimplemented!"); return ""; } -template -inline void unserialize(RawShape& /*sh*/, const std::string& /*str*/) +template +inline void unserialize(S& /*sh*/, const std::string& /*str*/) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::unserialize() unimplemented!"); } template inline Unit area(const Cntr& poly, const PathTag& ); -template -inline bool intersects(const RawShape& /*sh*/, const RawShape& /*sh*/) +template +inline bool intersects(const S& /*sh*/, const S& /*sh*/) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::intersects() unimplemented!"); return false; } @@ -633,29 +661,29 @@ inline bool isInside(const TGuest&, const THost&, return false; } -template -inline bool touches( const RawShape& /*shape*/, - const RawShape& /*shape*/) +template +inline bool touches( const S& /*shape*/, + const S& /*shape*/) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::touches(shape, shape) unimplemented!"); return false; } -template -inline bool touches( const TPoint& /*point*/, - const RawShape& /*shape*/) +template +inline bool touches( const TPoint& /*point*/, + const S& /*shape*/) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::touches(point, shape) unimplemented!"); return false; } -template -inline _Box> boundingBox(const RawShape& /*sh*/, +template +inline _Box> boundingBox(const S& /*sh*/, const PathTag&) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::boundingBox(shape) unimplemented!"); } @@ -667,34 +695,34 @@ boundingBox(const RawShapes& /*sh*/, const MultiPolygonTag&) "shapelike::boundingBox(shapes) unimplemented!"); } -template -inline RawShape convexHull(const RawShape& sh, const PathTag&); +template +inline S convexHull(const S& sh, const PathTag&); template inline S convexHull(const RawShapes& sh, const MultiPolygonTag&); -template -inline void rotate(RawShape& /*sh*/, const Radians& /*rads*/) +template +inline void rotate(S& /*sh*/, const Radians& /*rads*/) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::rotate() unimplemented!"); } -template -inline void translate(RawShape& /*sh*/, const RawPoint& /*offs*/) +template +inline void translate(S& /*sh*/, const P& /*offs*/) { - static_assert(always_false::value, + static_assert(always_false::value, "shapelike::translate() unimplemented!"); } -template -inline void offset(RawShape& /*sh*/, TCoord> /*distance*/) +template +inline void offset(S& /*sh*/, TCoord> /*distance*/) { dout() << "The current geometry backend does not support offsetting!\n"; } -template -inline std::pair isValid(const RawShape& /*sh*/) +template +inline std::pair isValid(const S& /*sh*/) { return {false, "shapelike::isValid() unimplemented!"}; } @@ -735,56 +763,56 @@ template inline bool isConvex(const RawPath& sh, const PathTag&) // No need to implement these // ***************************************************************************** -template -inline typename TContour::iterator -begin(RawShape& sh, const PolygonTag&) +template +inline typename TContour::iterator +begin(S& sh, const PolygonTag&) { return begin(contour(sh), PathTag()); } -template // Tag dispatcher -inline auto begin(RawShape& sh) -> decltype(begin(sh, Tag())) +template // Tag dispatcher +inline auto begin(S& sh) -> decltype(begin(sh, Tag())) { - return begin(sh, Tag()); + return begin(sh, Tag()); } -template -inline typename TContour::const_iterator -cbegin(const RawShape& sh, const PolygonTag&) +template +inline typename TContour::const_iterator +cbegin(const S& sh, const PolygonTag&) { return cbegin(contour(sh), PathTag()); } -template // Tag dispatcher -inline auto cbegin(const RawShape& sh) -> decltype(cbegin(sh, Tag())) +template // Tag dispatcher +inline auto cbegin(const S& sh) -> decltype(cbegin(sh, Tag())) { - return cbegin(sh, Tag()); + return cbegin(sh, Tag()); } -template -inline typename TContour::iterator -end(RawShape& sh, const PolygonTag&) +template +inline typename TContour::iterator +end(S& sh, const PolygonTag&) { return end(contour(sh), PathTag()); } -template // Tag dispatcher -inline auto end(RawShape& sh) -> decltype(begin(sh, Tag())) +template // Tag dispatcher +inline auto end(S& sh) -> decltype(begin(sh, Tag())) { - return end(sh, Tag()); + return end(sh, Tag()); } -template -inline typename TContour::const_iterator -cend(const RawShape& sh, const PolygonTag&) +template +inline typename TContour::const_iterator +cend(const S& sh, const PolygonTag&) { return cend(contour(sh), PathTag()); } -template // Tag dispatcher -inline auto cend(const RawShape& sh) -> decltype(cend(sh, Tag())) +template // Tag dispatcher +inline auto cend(const S& sh) -> decltype(cend(sh, Tag())) { - return cend(sh, Tag()); + return cend(sh, Tag()); } template std::reverse_iterator _backward(It iter) { @@ -817,8 +845,8 @@ template TPoint

back (const P& p) { } // Optional, does nothing by default -template -inline void reserve(RawShape& sh, size_t vertex_capacity, const PolygonTag&) +template +inline void reserve(S& sh, size_t vertex_capacity, const PolygonTag&) { reserve(contour(sh), vertex_capacity, PathTag()); } @@ -828,20 +856,20 @@ inline void reserve(T& sh, size_t vertex_capacity) { reserve(sh, vertex_capacity, Tag()); } -template -inline void addVertex(RawShape& sh, const PolygonTag&, Args...args) +template +inline void addVertex(S& sh, const PolygonTag&, Args...args) { addVertex(contour(sh), PathTag(), std::forward(args)...); } -template // Tag dispatcher -inline void addVertex(RawShape& sh, Args...args) +template // Tag dispatcher +inline void addVertex(S& sh, Args...args) { - addVertex(sh, Tag(), std::forward(args)...); + addVertex(sh, Tag(), std::forward(args)...); } -template -inline _Box> boundingBox(const RawShape& poly, const PolygonTag&) +template +inline _Box> boundingBox(const S& poly, const PolygonTag&) { return boundingBox(contour(poly), PathTag()); } @@ -938,40 +966,40 @@ template inline double area(const S& poly, const PolygonTag& ) }); } -template // Dispatching function -inline double area(const RawShape& sh) +template // Dispatching function +inline double area(const S& sh) { - return area(sh, Tag()); + return area(sh, Tag()); } template inline double area(const RawShapes& shapes, const MultiPolygonTag&) { - using RawShape = typename RawShapes::value_type; + using S = typename RawShapes::value_type; return std::accumulate(shapes.begin(), shapes.end(), 0.0, - [](double a, const RawShape& b) { + [](double a, const S& b) { return a += area(b); }); } -template -inline RawShape convexHull(const RawShape& sh, const PolygonTag&) +template +inline S convexHull(const S& sh, const PolygonTag&) { - return create(convexHull(contour(sh), PathTag())); + return create(convexHull(contour(sh), PathTag())); } -template -inline auto convexHull(const RawShape& sh) - -> decltype(convexHull(sh, Tag())) // TODO: C++14 could deduce +template +inline auto convexHull(const S& sh) + -> decltype(convexHull(sh, Tag())) // TODO: C++14 could deduce { - return convexHull(sh, Tag()); + return convexHull(sh, Tag()); } -template -inline RawShape convexHull(const RawShape& sh, const PathTag&) +template +inline S convexHull(const S& sh, const PathTag&) { - using Unit = TCompute; - using Point = TPoint; + using Unit = TCompute; + using Point = TPoint; namespace sl = shapelike; size_t edges = sl::cend(sh) - sl::cbegin(sh); @@ -1016,8 +1044,8 @@ inline RawShape convexHull(const RawShape& sh, const PathTag&) ++ik; } - RawShape ret; reserve(ret, U.size() + L.size()); - if(is_clockwise()) { + S ret; reserve(ret, U.size() + L.size()); + if(is_clockwise()) { for(auto it = U.begin(); it != std::prev(U.end()); ++it) addVertex(ret, *it); for(auto it = L.rbegin(); it != std::prev(L.rend()); ++it) @@ -1068,11 +1096,11 @@ inline bool isInside(const TP& point, const TB& box, return px > minx && px < maxx && py > miny && py < maxy; } -template -inline bool isInside(const RawShape& sh, const TC& circ, +template +inline bool isInside(const S& sh, const TC& circ, const PolygonTag&, const CircleTag&) { - return std::all_of(cbegin(sh), cend(sh), [&circ](const TPoint& p) + return std::all_of(cbegin(sh), cend(sh), [&circ](const TPoint& p) { return isInside(p, circ, PointTag(), CircleTag()); }); @@ -1103,8 +1131,8 @@ inline bool isInside(const TBGuest& ibb, const TBHost& box, return iminX > minX && imaxX < maxX && iminY > minY && imaxY < maxY; } -template -inline bool isInside(const RawShape& poly, const TB& box, +template +inline bool isInside(const S& poly, const TB& box, const PolygonTag&, const BoxTag&) { return isInside(boundingBox(poly), box, BoxTag(), BoxTag()); @@ -1115,36 +1143,36 @@ inline bool isInside(const TGuest& guest, const THost& host) { return isInside(guest, host, Tag(), Tag()); } -template // Potential O(1) implementation may exist -inline TPoint& vertex(RawShape& sh, unsigned long idx, +template // Potential O(1) implementation may exist +inline TPoint& vertex(S& sh, unsigned long idx, const PolygonTag&) { return *(shapelike::begin(contour(sh)) + idx); } -template // Potential O(1) implementation may exist -inline TPoint& vertex(RawShape& sh, unsigned long idx, +template // Potential O(1) implementation may exist +inline TPoint& vertex(S& sh, unsigned long idx, const PathTag&) { return *(shapelike::begin(sh) + idx); } -template // Potential O(1) implementation may exist -inline TPoint& vertex(RawShape& sh, unsigned long idx) +template // Potential O(1) implementation may exist +inline TPoint& vertex(S& sh, unsigned long idx) { - return vertex(sh, idx, Tag()); + return vertex(sh, idx, Tag()); } -template // Potential O(1) implementation may exist -inline const TPoint& vertex(const RawShape& sh, +template // Potential O(1) implementation may exist +inline const TPoint& vertex(const S& sh, unsigned long idx, const PolygonTag&) { return *(shapelike::cbegin(contour(sh)) + idx); } -template // Potential O(1) implementation may exist -inline const TPoint& vertex(const RawShape& sh, +template // Potential O(1) implementation may exist +inline const TPoint& vertex(const S& sh, unsigned long idx, const PathTag&) { @@ -1152,28 +1180,28 @@ inline const TPoint& vertex(const RawShape& sh, } -template // Potential O(1) implementation may exist -inline const TPoint& vertex(const RawShape& sh, +template // Potential O(1) implementation may exist +inline const TPoint& vertex(const S& sh, unsigned long idx) { - return vertex(sh, idx, Tag()); + return vertex(sh, idx, Tag()); } -template -inline size_t contourVertexCount(const RawShape& sh) +template +inline size_t contourVertexCount(const S& sh) { return shapelike::cend(sh) - shapelike::cbegin(sh); } -template -inline void foreachVertex(RawShape& sh, Fn fn, const PolygonTag&) { +template +inline void foreachVertex(S& sh, Fn fn, const PolygonTag&) { foreachVertex(contour(sh), fn, PathTag()); for(auto& h : holes(sh)) foreachVertex(h, fn, PathTag()); } -template -inline void foreachVertex(RawShape& sh, Fn fn) { - foreachVertex(sh, fn, Tag()); +template +inline void foreachVertex(S& sh, Fn fn) { + foreachVertex(sh, fn, Tag()); } template inline bool isConvex(const Poly& sh, const PolygonTag&) @@ -1184,9 +1212,9 @@ template inline bool isConvex(const Poly& sh, const PolygonTag&) return convex; } -template inline bool isConvex(const RawShape& sh) // dispatch +template inline bool isConvex(const S& sh) // dispatch { - return isConvex(sh, Tag()); + return isConvex(sh, Tag()); } }