mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 18:19:12 +08:00
Try to deal with infinite bin.
This commit is contained in:
parent
87c5e9bbaa
commit
320f2ecefd
@ -30,11 +30,11 @@ template<class Shape> struct ShapeTag { using Type = typename Shape::Tag; };
|
|||||||
template<class S> using Tag = typename ShapeTag<remove_cvref_t<S>>::Type;
|
template<class S> using Tag = typename ShapeTag<remove_cvref_t<S>>::Type;
|
||||||
|
|
||||||
/// Meta function to derive the contour type for a polygon which could be itself
|
/// Meta function to derive the contour type for a polygon which could be itself
|
||||||
template<class RawShape> struct ContourType { using Type = RawShape; };
|
template<class S> struct ContourType { using Type = S; };
|
||||||
|
|
||||||
/// TContour<RawShape> instead of `typename ContourType<RawShape>::type`
|
/// TContour<S> instead of `typename ContourType<S>::type`
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
using TContour = typename ContourType<remove_cvref_t<RawShape>>::Type;
|
using TContour = typename ContourType<remove_cvref_t<S>>::Type;
|
||||||
|
|
||||||
/// Getting the type of point structure used by a shape.
|
/// Getting the type of point structure used by a shape.
|
||||||
template<class Sh> struct PointType {
|
template<class Sh> struct PointType {
|
||||||
@ -83,12 +83,12 @@ template<class I> struct ComputeType<I, true> {
|
|||||||
template<class T> using TCompute = typename ComputeType<remove_cvref_t<T>>::Type;
|
template<class T> using TCompute = typename ComputeType<remove_cvref_t<T>>::Type;
|
||||||
|
|
||||||
/// A meta function to derive a container type for holes in a polygon
|
/// A meta function to derive a container type for holes in a polygon
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
struct HolesContainer { using Type = std::vector<TContour<RawShape>>; };
|
struct HolesContainer { using Type = std::vector<TContour<S>>; };
|
||||||
|
|
||||||
/// Shorthand for `typename HolesContainer<RawShape>::Type`
|
/// Shorthand for `typename HolesContainer<S>::Type`
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
using THolesContainer = typename HolesContainer<remove_cvref_t<RawShape>>::Type;
|
using THolesContainer = typename HolesContainer<remove_cvref_t<S>>::Type;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TContour, TPoint, TCoord and TCompute should be usable for any type for which
|
* TContour, TPoint, TCoord and TCompute should be usable for any type for which
|
||||||
@ -132,7 +132,7 @@ enum class Orientation {
|
|||||||
COUNTER_CLOCKWISE
|
COUNTER_CLOCKWISE
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
struct OrientationType {
|
struct OrientationType {
|
||||||
|
|
||||||
// Default Polygon orientation that the library expects
|
// Default Polygon orientation that the library expects
|
||||||
@ -146,45 +146,46 @@ template<class T> inline /*constexpr*/ bool is_clockwise() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A point pair base class for other point pairs (segment, box, ...).
|
* \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<class RawPoint>
|
template<class P>
|
||||||
struct PointPair {
|
struct PointPair {
|
||||||
RawPoint p1;
|
P p1;
|
||||||
RawPoint p2;
|
P p2;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief An abstraction of a box;
|
* \brief An abstraction of a box;
|
||||||
*/
|
*/
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
class _Box: PointPair<RawPoint> {
|
class _Box: PointPair<P> {
|
||||||
using PointPair<RawPoint>::p1;
|
using PointPair<P>::p1;
|
||||||
using PointPair<RawPoint>::p2;
|
using PointPair<P>::p2;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using Tag = BoxTag;
|
using Tag = BoxTag;
|
||||||
using PointType = RawPoint;
|
using PointType = P;
|
||||||
|
|
||||||
inline _Box() = default;
|
inline _Box(const P& p = {TCoord<P>(0), TCoord<P>(0)});
|
||||||
inline _Box(const RawPoint& p, const RawPoint& pp):
|
inline _Box(const P& p, const P& pp):
|
||||||
PointPair<RawPoint>({p, pp}) {}
|
PointPair<P>({p, pp}) {}
|
||||||
|
|
||||||
|
inline _Box(TCoord<P> width, TCoord<P> height,
|
||||||
|
const P& p = {TCoord<P>(0), TCoord<P>(0)});/*:
|
||||||
|
_Box(p, P{width, height}) {}*/
|
||||||
|
|
||||||
inline _Box(TCoord<RawPoint> width, TCoord<RawPoint> height):
|
inline const P& minCorner() const BP2D_NOEXCEPT { return p1; }
|
||||||
_Box(RawPoint{0, 0}, RawPoint{width, height}) {}
|
inline const P& maxCorner() const BP2D_NOEXCEPT { return p2; }
|
||||||
|
|
||||||
inline const RawPoint& minCorner() const BP2D_NOEXCEPT { return p1; }
|
inline P& minCorner() BP2D_NOEXCEPT { return p1; }
|
||||||
inline const RawPoint& maxCorner() const BP2D_NOEXCEPT { return p2; }
|
inline P& maxCorner() BP2D_NOEXCEPT { return p2; }
|
||||||
|
|
||||||
inline RawPoint& minCorner() BP2D_NOEXCEPT { return p1; }
|
inline TCoord<P> width() const BP2D_NOEXCEPT;
|
||||||
inline RawPoint& maxCorner() BP2D_NOEXCEPT { return p2; }
|
inline TCoord<P> height() const BP2D_NOEXCEPT;
|
||||||
|
|
||||||
inline TCoord<RawPoint> width() const BP2D_NOEXCEPT;
|
inline P center() const BP2D_NOEXCEPT;
|
||||||
inline TCoord<RawPoint> height() const BP2D_NOEXCEPT;
|
|
||||||
|
|
||||||
inline RawPoint center() const BP2D_NOEXCEPT;
|
template<class Unit = TCompute<P>>
|
||||||
|
|
||||||
template<class Unit = TCompute<RawPoint>>
|
|
||||||
inline Unit area() const BP2D_NOEXCEPT {
|
inline Unit area() const BP2D_NOEXCEPT {
|
||||||
return Unit(width())*height();
|
return Unit(width())*height();
|
||||||
}
|
}
|
||||||
@ -194,20 +195,20 @@ template<class S> struct PointType<_Box<S>> {
|
|||||||
using Type = typename _Box<S>::PointType;
|
using Type = typename _Box<S>::PointType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
class _Circle {
|
class _Circle {
|
||||||
RawPoint center_;
|
P center_;
|
||||||
double radius_ = 0;
|
double radius_ = 0;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using Tag = CircleTag;
|
using Tag = CircleTag;
|
||||||
using PointType = RawPoint;
|
using PointType = P;
|
||||||
|
|
||||||
_Circle() = default;
|
_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 const P& center() const BP2D_NOEXCEPT { return center_; }
|
||||||
inline void center(const RawPoint& c) { center_ = c; }
|
inline void center(const P& c) { center_ = c; }
|
||||||
|
|
||||||
inline double radius() const BP2D_NOEXCEPT { return radius_; }
|
inline double radius() const BP2D_NOEXCEPT { return radius_; }
|
||||||
inline void radius(double r) { radius_ = r; }
|
inline void radius(double r) { radius_ = r; }
|
||||||
@ -224,38 +225,38 @@ template<class S> struct PointType<_Circle<S>> {
|
|||||||
/**
|
/**
|
||||||
* \brief An abstraction of a directed line segment with two points.
|
* \brief An abstraction of a directed line segment with two points.
|
||||||
*/
|
*/
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
class _Segment: PointPair<RawPoint> {
|
class _Segment: PointPair<P> {
|
||||||
using PointPair<RawPoint>::p1;
|
using PointPair<P>::p1;
|
||||||
using PointPair<RawPoint>::p2;
|
using PointPair<P>::p2;
|
||||||
mutable Radians angletox_ = std::nan("");
|
mutable Radians angletox_ = std::nan("");
|
||||||
public:
|
public:
|
||||||
|
|
||||||
using PointType = RawPoint;
|
using PointType = P;
|
||||||
|
|
||||||
inline _Segment() = default;
|
inline _Segment() = default;
|
||||||
|
|
||||||
inline _Segment(const RawPoint& p, const RawPoint& pp):
|
inline _Segment(const P& p, const P& pp):
|
||||||
PointPair<RawPoint>({p, pp}) {}
|
PointPair<P>({p, pp}) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the first point.
|
* @brief Get the first point.
|
||||||
* @return Returns the starting 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.
|
* @brief The end point.
|
||||||
* @return Returns the end point of the segment.
|
* @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;
|
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;
|
angletox_ = std::nan(""); p2 = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +264,7 @@ public:
|
|||||||
inline Radians angleToXaxis() const;
|
inline Radians angleToXaxis() const;
|
||||||
|
|
||||||
/// The length of the segment in the measure of the coordinate system.
|
/// The length of the segment in the measure of the coordinate system.
|
||||||
template<class Unit = TCompute<RawPoint>> inline Unit sqlength() const;
|
template<class Unit = TCompute<P>> inline Unit sqlength() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -275,42 +276,42 @@ template<class S> struct PointType<_Segment<S>> {
|
|||||||
// used in friend declarations.
|
// used in friend declarations.
|
||||||
namespace pointlike {
|
namespace pointlike {
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
inline TCoord<RawPoint> x(const RawPoint& p)
|
inline TCoord<P> x(const P& p)
|
||||||
{
|
{
|
||||||
return p.x();
|
return p.x();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
inline TCoord<RawPoint> y(const RawPoint& p)
|
inline TCoord<P> y(const P& p)
|
||||||
{
|
{
|
||||||
return p.y();
|
return p.y();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
inline TCoord<RawPoint>& x(RawPoint& p)
|
inline TCoord<P>& x(P& p)
|
||||||
{
|
{
|
||||||
return p.x();
|
return p.x();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
inline TCoord<RawPoint>& y(RawPoint& p)
|
inline TCoord<P>& y(P& p)
|
||||||
{
|
{
|
||||||
return p.y();
|
return p.y();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint, class Unit = TCompute<RawPoint>>
|
template<class P, class Unit = TCompute<P>>
|
||||||
inline Unit squaredDistance(const RawPoint& p1, const RawPoint& p2)
|
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));
|
auto x1 = Unit(x(p1)), y1 = Unit(y(p1)), x2 = Unit(x(p2)), y2 = Unit(y(p2));
|
||||||
Unit a = (x2 - x1), b = (y2 - y1);
|
Unit a = (x2 - x1), b = (y2 - y1);
|
||||||
return a * a + b * b;
|
return a * a + b * b;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
inline double distance(const RawPoint& p1, const RawPoint& p2)
|
inline double distance(const P& p1, const P& p2)
|
||||||
{
|
{
|
||||||
return std::sqrt(squaredDistance<RawPoint, double>(p1, p2));
|
return std::sqrt(squaredDistance<P, double>(p1, p2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// create perpendicular vector
|
// create perpendicular vector
|
||||||
@ -339,9 +340,9 @@ inline Unit magnsq(const Pt& p)
|
|||||||
return Unit(x(p)) * x(p) + Unit(y(p)) * y(p);
|
return Unit(x(p)) * x(p) + Unit(y(p)) * y(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint, class Unit = TCompute<RawPoint>>
|
template<class P, class Unit = TCompute<P>>
|
||||||
inline std::pair<Unit, bool> horizontalDistance(
|
inline std::pair<Unit, bool> horizontalDistance(
|
||||||
const RawPoint& p, const _Segment<RawPoint>& s)
|
const P& p, const _Segment<P>& s)
|
||||||
{
|
{
|
||||||
namespace pl = pointlike;
|
namespace pl = pointlike;
|
||||||
auto x = Unit(pl::x(p)), y = Unit(pl::y(p));
|
auto x = Unit(pl::x(p)), y = Unit(pl::y(p));
|
||||||
@ -364,9 +365,9 @@ inline std::pair<Unit, bool> horizontalDistance(
|
|||||||
return {ret, true};
|
return {ret, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint, class Unit = TCompute<RawPoint>>
|
template<class P, class Unit = TCompute<P>>
|
||||||
inline std::pair<Unit, bool> verticalDistance(
|
inline std::pair<Unit, bool> verticalDistance(
|
||||||
const RawPoint& p, const _Segment<RawPoint>& s)
|
const P& p, const _Segment<P>& s)
|
||||||
{
|
{
|
||||||
namespace pl = pointlike;
|
namespace pl = pointlike;
|
||||||
auto x = Unit(pl::x(p)), y = Unit(pl::y(p));
|
auto x = Unit(pl::x(p)), y = Unit(pl::y(p));
|
||||||
@ -390,42 +391,42 @@ inline std::pair<Unit, bool> verticalDistance(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
TCoord<RawPoint> _Box<RawPoint>::width() const BP2D_NOEXCEPT
|
TCoord<P> _Box<P>::width() const BP2D_NOEXCEPT
|
||||||
{
|
{
|
||||||
return pointlike::x(maxCorner()) - pointlike::x(minCorner());
|
return pointlike::x(maxCorner()) - pointlike::x(minCorner());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
TCoord<RawPoint> _Box<RawPoint>::height() const BP2D_NOEXCEPT
|
TCoord<P> _Box<P>::height() const BP2D_NOEXCEPT
|
||||||
{
|
{
|
||||||
return pointlike::y(maxCorner()) - pointlike::y(minCorner());
|
return pointlike::y(maxCorner()) - pointlike::y(minCorner());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
TCoord<RawPoint> getX(const RawPoint& p) { return pointlike::x<RawPoint>(p); }
|
TCoord<P> getX(const P& p) { return pointlike::x<P>(p); }
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
TCoord<RawPoint> getY(const RawPoint& p) { return pointlike::y<RawPoint>(p); }
|
TCoord<P> getY(const P& p) { return pointlike::y<P>(p); }
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
void setX(RawPoint& p, const TCoord<RawPoint>& val)
|
void setX(P& p, const TCoord<P>& val)
|
||||||
{
|
{
|
||||||
pointlike::x<RawPoint>(p) = val;
|
pointlike::x<P>(p) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
void setY(RawPoint& p, const TCoord<RawPoint>& val)
|
void setY(P& p, const TCoord<P>& val)
|
||||||
{
|
{
|
||||||
pointlike::y<RawPoint>(p) = val;
|
pointlike::y<P>(p) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
inline Radians _Segment<RawPoint>::angleToXaxis() const
|
inline Radians _Segment<P>::angleToXaxis() const
|
||||||
{
|
{
|
||||||
if(std::isnan(static_cast<double>(angletox_))) {
|
if(std::isnan(static_cast<double>(angletox_))) {
|
||||||
TCoord<RawPoint> dx = getX(second()) - getX(first());
|
TCoord<P> dx = getX(second()) - getX(first());
|
||||||
TCoord<RawPoint> dy = getY(second()) - getY(first());
|
TCoord<P> dy = getY(second()) - getY(first());
|
||||||
|
|
||||||
double a = std::atan2(dy, dx);
|
double a = std::atan2(dy, dx);
|
||||||
auto s = std::signbit(a);
|
auto s = std::signbit(a);
|
||||||
@ -436,21 +437,48 @@ inline Radians _Segment<RawPoint>::angleToXaxis() const
|
|||||||
return angletox_;
|
return angletox_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class P>
|
||||||
template<class Unit>
|
template<class Unit>
|
||||||
inline Unit _Segment<RawPoint>::sqlength() const
|
inline Unit _Segment<P>::sqlength() const
|
||||||
{
|
{
|
||||||
return pointlike::squaredDistance<RawPoint, Unit>(first(), second());
|
return pointlike::squaredDistance<P, Unit>(first(), second());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawPoint>
|
template<class T>
|
||||||
inline RawPoint _Box<RawPoint>::center() const BP2D_NOEXCEPT {
|
enable_if_t<std::is_floating_point<T>::value, T> modulo(const T &v, const T &m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
enable_if_t<std::is_integral<T>::value, T> modulo(const T &v, const T &m)
|
||||||
|
{
|
||||||
|
return v % m;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class P>
|
||||||
|
inline _Box<P>::_Box(TCoord<P> width, TCoord<P> height, const P & center) :
|
||||||
|
PointPair<P>({center - P{width / 2, height / 2},
|
||||||
|
center + P{width / 2, height / 2} +
|
||||||
|
P{modulo(width, TCoord<P>(2)),
|
||||||
|
modulo(height, TCoord<P>(2))}}) {}
|
||||||
|
|
||||||
|
template<class P>
|
||||||
|
inline _Box<P>::_Box(const P& center) {
|
||||||
|
using C = TCoord<P>;
|
||||||
|
TCoord<P> M = std::max(getX(center), getY(center)) -
|
||||||
|
std::numeric_limits<C>::lowest();
|
||||||
|
maxCorner() = center + P{M, M};
|
||||||
|
minCorner() = center - P{M, M};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class P>
|
||||||
|
inline P _Box<P>::center() const BP2D_NOEXCEPT {
|
||||||
auto& minc = minCorner();
|
auto& minc = minCorner();
|
||||||
auto& maxc = maxCorner();
|
auto& maxc = maxCorner();
|
||||||
|
|
||||||
using Coord = TCoord<RawPoint>;
|
using Coord = TCoord<P>;
|
||||||
|
|
||||||
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( (getX(minc) + getX(maxc)) / Coord(2) ),
|
||||||
Coord( (getY(minc) + getY(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.
|
// used in friend declarations and can be aliased at class scope.
|
||||||
namespace shapelike {
|
namespace shapelike {
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline RawShape create(const TContour<RawShape>& contour,
|
inline S create(const TContour<S>& contour,
|
||||||
const THolesContainer<RawShape>& holes)
|
const THolesContainer<S>& holes)
|
||||||
{
|
{
|
||||||
return RawShape(contour, holes);
|
return S(contour, holes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline RawShape create(TContour<RawShape>&& contour,
|
inline S create(TContour<S>&& contour,
|
||||||
THolesContainer<RawShape>&& holes)
|
THolesContainer<S>&& holes)
|
||||||
{
|
{
|
||||||
return RawShape(contour, holes);
|
return S(contour, holes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline RawShape create(const TContour<RawShape>& contour)
|
inline S create(const TContour<S>& contour)
|
||||||
{
|
{
|
||||||
return create<RawShape>(contour, {});
|
return create<S>(contour, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline RawShape create(TContour<RawShape>&& contour)
|
inline S create(TContour<S>&& contour)
|
||||||
{
|
{
|
||||||
return create<RawShape>(contour, {});
|
return create<S>(contour, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline THolesContainer<RawShape>& holes(RawShape& /*sh*/)
|
inline THolesContainer<S>& holes(S& /*sh*/)
|
||||||
{
|
{
|
||||||
static THolesContainer<RawShape> empty;
|
static THolesContainer<S> empty;
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline const THolesContainer<RawShape>& holes(const RawShape& /*sh*/)
|
inline const THolesContainer<S>& holes(const S& /*sh*/)
|
||||||
{
|
{
|
||||||
static THolesContainer<RawShape> empty;
|
static THolesContainer<S> empty;
|
||||||
return empty;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline TContour<RawShape>& hole(RawShape& sh, unsigned long idx)
|
inline TContour<S>& hole(S& sh, unsigned long idx)
|
||||||
{
|
{
|
||||||
return holes(sh)[idx];
|
return holes(sh)[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline const TContour<RawShape>& hole(const RawShape& sh, unsigned long idx)
|
inline const TContour<S>& hole(const S& sh, unsigned long idx)
|
||||||
{
|
{
|
||||||
return holes(sh)[idx];
|
return holes(sh)[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline size_t holeCount(const RawShape& sh)
|
inline size_t holeCount(const S& sh)
|
||||||
{
|
{
|
||||||
return holes(sh).size();
|
return holes(sh).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline TContour<RawShape>& contour(RawShape& sh)
|
inline TContour<S>& contour(S& sh)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::contour() unimplemented!");
|
"shapelike::contour() unimplemented!");
|
||||||
return sh;
|
return sh;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline const TContour<RawShape>& contour(const RawShape& sh)
|
inline const TContour<S>& contour(const S& sh)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::contour() unimplemented!");
|
"shapelike::contour() unimplemented!");
|
||||||
return sh;
|
return sh;
|
||||||
}
|
}
|
||||||
@ -548,71 +576,71 @@ inline void reserve(RawPath& p, size_t vertex_capacity, const PathTag&)
|
|||||||
p.reserve(vertex_capacity);
|
p.reserve(vertex_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class...Args>
|
template<class S, class...Args>
|
||||||
inline void addVertex(RawShape& sh, const PathTag&, Args...args)
|
inline void addVertex(S& sh, const PathTag&, Args...args)
|
||||||
{
|
{
|
||||||
sh.emplace_back(std::forward<Args>(args)...);
|
sh.emplace_back(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class Fn>
|
template<class S, class Fn>
|
||||||
inline void foreachVertex(RawShape& sh, Fn fn, const PathTag&) {
|
inline void foreachVertex(S& sh, Fn fn, const PathTag&) {
|
||||||
std::for_each(sh.begin(), sh.end(), fn);
|
std::for_each(sh.begin(), sh.end(), fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline typename RawShape::iterator begin(RawShape& sh, const PathTag&)
|
inline typename S::iterator begin(S& sh, const PathTag&)
|
||||||
{
|
{
|
||||||
return sh.begin();
|
return sh.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline typename RawShape::iterator end(RawShape& sh, const PathTag&)
|
inline typename S::iterator end(S& sh, const PathTag&)
|
||||||
{
|
{
|
||||||
return sh.end();
|
return sh.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline typename RawShape::const_iterator
|
inline typename S::const_iterator
|
||||||
cbegin(const RawShape& sh, const PathTag&)
|
cbegin(const S& sh, const PathTag&)
|
||||||
{
|
{
|
||||||
return sh.cbegin();
|
return sh.cbegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline typename RawShape::const_iterator
|
inline typename S::const_iterator
|
||||||
cend(const RawShape& sh, const PathTag&)
|
cend(const S& sh, const PathTag&)
|
||||||
{
|
{
|
||||||
return sh.cend();
|
return sh.cend();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline std::string toString(const RawShape& /*sh*/)
|
inline std::string toString(const S& /*sh*/)
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Formats, class RawShape>
|
template<Formats, class S>
|
||||||
inline std::string serialize(const RawShape& /*sh*/, double /*scale*/=1)
|
inline std::string serialize(const S& /*sh*/, double /*scale*/=1)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::serialize() unimplemented!");
|
"shapelike::serialize() unimplemented!");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Formats, class RawShape>
|
template<Formats, class S>
|
||||||
inline void unserialize(RawShape& /*sh*/, const std::string& /*str*/)
|
inline void unserialize(S& /*sh*/, const std::string& /*str*/)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::unserialize() unimplemented!");
|
"shapelike::unserialize() unimplemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Cntr, class Unit = double>
|
template<class Cntr, class Unit = double>
|
||||||
inline Unit area(const Cntr& poly, const PathTag& );
|
inline Unit area(const Cntr& poly, const PathTag& );
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline bool intersects(const RawShape& /*sh*/, const RawShape& /*sh*/)
|
inline bool intersects(const S& /*sh*/, const S& /*sh*/)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::intersects() unimplemented!");
|
"shapelike::intersects() unimplemented!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -633,29 +661,29 @@ inline bool isInside(const TGuest&, const THost&,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline bool touches( const RawShape& /*shape*/,
|
inline bool touches( const S& /*shape*/,
|
||||||
const RawShape& /*shape*/)
|
const S& /*shape*/)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::touches(shape, shape) unimplemented!");
|
"shapelike::touches(shape, shape) unimplemented!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline bool touches( const TPoint<RawShape>& /*point*/,
|
inline bool touches( const TPoint<S>& /*point*/,
|
||||||
const RawShape& /*shape*/)
|
const S& /*shape*/)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::touches(point, shape) unimplemented!");
|
"shapelike::touches(point, shape) unimplemented!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline _Box<TPoint<RawShape>> boundingBox(const RawShape& /*sh*/,
|
inline _Box<TPoint<S>> boundingBox(const S& /*sh*/,
|
||||||
const PathTag&)
|
const PathTag&)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::boundingBox(shape) unimplemented!");
|
"shapelike::boundingBox(shape) unimplemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,34 +695,34 @@ boundingBox(const RawShapes& /*sh*/, const MultiPolygonTag&)
|
|||||||
"shapelike::boundingBox(shapes) unimplemented!");
|
"shapelike::boundingBox(shapes) unimplemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline RawShape convexHull(const RawShape& sh, const PathTag&);
|
inline S convexHull(const S& sh, const PathTag&);
|
||||||
|
|
||||||
template<class RawShapes, class S = typename RawShapes::value_type>
|
template<class RawShapes, class S = typename RawShapes::value_type>
|
||||||
inline S convexHull(const RawShapes& sh, const MultiPolygonTag&);
|
inline S convexHull(const RawShapes& sh, const MultiPolygonTag&);
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline void rotate(RawShape& /*sh*/, const Radians& /*rads*/)
|
inline void rotate(S& /*sh*/, const Radians& /*rads*/)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::rotate() unimplemented!");
|
"shapelike::rotate() unimplemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class RawPoint>
|
template<class S, class P>
|
||||||
inline void translate(RawShape& /*sh*/, const RawPoint& /*offs*/)
|
inline void translate(S& /*sh*/, const P& /*offs*/)
|
||||||
{
|
{
|
||||||
static_assert(always_false<RawShape>::value,
|
static_assert(always_false<S>::value,
|
||||||
"shapelike::translate() unimplemented!");
|
"shapelike::translate() unimplemented!");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline void offset(RawShape& /*sh*/, TCoord<TPoint<RawShape>> /*distance*/)
|
inline void offset(S& /*sh*/, TCoord<TPoint<S>> /*distance*/)
|
||||||
{
|
{
|
||||||
dout() << "The current geometry backend does not support offsetting!\n";
|
dout() << "The current geometry backend does not support offsetting!\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline std::pair<bool, std::string> isValid(const RawShape& /*sh*/)
|
inline std::pair<bool, std::string> isValid(const S& /*sh*/)
|
||||||
{
|
{
|
||||||
return {false, "shapelike::isValid() unimplemented!"};
|
return {false, "shapelike::isValid() unimplemented!"};
|
||||||
}
|
}
|
||||||
@ -735,56 +763,56 @@ template<class RawPath> inline bool isConvex(const RawPath& sh, const PathTag&)
|
|||||||
// No need to implement these
|
// No need to implement these
|
||||||
// *****************************************************************************
|
// *****************************************************************************
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline typename TContour<RawShape>::iterator
|
inline typename TContour<S>::iterator
|
||||||
begin(RawShape& sh, const PolygonTag&)
|
begin(S& sh, const PolygonTag&)
|
||||||
{
|
{
|
||||||
return begin(contour(sh), PathTag());
|
return begin(contour(sh), PathTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Tag dispatcher
|
template<class S> // Tag dispatcher
|
||||||
inline auto begin(RawShape& sh) -> decltype(begin(sh, Tag<RawShape>()))
|
inline auto begin(S& sh) -> decltype(begin(sh, Tag<S>()))
|
||||||
{
|
{
|
||||||
return begin(sh, Tag<RawShape>());
|
return begin(sh, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline typename TContour<RawShape>::const_iterator
|
inline typename TContour<S>::const_iterator
|
||||||
cbegin(const RawShape& sh, const PolygonTag&)
|
cbegin(const S& sh, const PolygonTag&)
|
||||||
{
|
{
|
||||||
return cbegin(contour(sh), PathTag());
|
return cbegin(contour(sh), PathTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Tag dispatcher
|
template<class S> // Tag dispatcher
|
||||||
inline auto cbegin(const RawShape& sh) -> decltype(cbegin(sh, Tag<RawShape>()))
|
inline auto cbegin(const S& sh) -> decltype(cbegin(sh, Tag<S>()))
|
||||||
{
|
{
|
||||||
return cbegin(sh, Tag<RawShape>());
|
return cbegin(sh, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline typename TContour<RawShape>::iterator
|
inline typename TContour<S>::iterator
|
||||||
end(RawShape& sh, const PolygonTag&)
|
end(S& sh, const PolygonTag&)
|
||||||
{
|
{
|
||||||
return end(contour(sh), PathTag());
|
return end(contour(sh), PathTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Tag dispatcher
|
template<class S> // Tag dispatcher
|
||||||
inline auto end(RawShape& sh) -> decltype(begin(sh, Tag<RawShape>()))
|
inline auto end(S& sh) -> decltype(begin(sh, Tag<S>()))
|
||||||
{
|
{
|
||||||
return end(sh, Tag<RawShape>());
|
return end(sh, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline typename TContour<RawShape>::const_iterator
|
inline typename TContour<S>::const_iterator
|
||||||
cend(const RawShape& sh, const PolygonTag&)
|
cend(const S& sh, const PolygonTag&)
|
||||||
{
|
{
|
||||||
return cend(contour(sh), PathTag());
|
return cend(contour(sh), PathTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Tag dispatcher
|
template<class S> // Tag dispatcher
|
||||||
inline auto cend(const RawShape& sh) -> decltype(cend(sh, Tag<RawShape>()))
|
inline auto cend(const S& sh) -> decltype(cend(sh, Tag<S>()))
|
||||||
{
|
{
|
||||||
return cend(sh, Tag<RawShape>());
|
return cend(sh, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class It> std::reverse_iterator<It> _backward(It iter) {
|
template<class It> std::reverse_iterator<It> _backward(It iter) {
|
||||||
@ -817,8 +845,8 @@ template<class P> TPoint<P> back (const P& p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Optional, does nothing by default
|
// Optional, does nothing by default
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline void reserve(RawShape& sh, size_t vertex_capacity, const PolygonTag&)
|
inline void reserve(S& sh, size_t vertex_capacity, const PolygonTag&)
|
||||||
{
|
{
|
||||||
reserve(contour(sh), vertex_capacity, PathTag());
|
reserve(contour(sh), vertex_capacity, PathTag());
|
||||||
}
|
}
|
||||||
@ -828,20 +856,20 @@ inline void reserve(T& sh, size_t vertex_capacity) {
|
|||||||
reserve(sh, vertex_capacity, Tag<T>());
|
reserve(sh, vertex_capacity, Tag<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class...Args>
|
template<class S, class...Args>
|
||||||
inline void addVertex(RawShape& sh, const PolygonTag&, Args...args)
|
inline void addVertex(S& sh, const PolygonTag&, Args...args)
|
||||||
{
|
{
|
||||||
addVertex(contour(sh), PathTag(), std::forward<Args>(args)...);
|
addVertex(contour(sh), PathTag(), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class...Args> // Tag dispatcher
|
template<class S, class...Args> // Tag dispatcher
|
||||||
inline void addVertex(RawShape& sh, Args...args)
|
inline void addVertex(S& sh, Args...args)
|
||||||
{
|
{
|
||||||
addVertex(sh, Tag<RawShape>(), std::forward<Args>(args)...);
|
addVertex(sh, Tag<S>(), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline _Box<TPoint<RawShape>> boundingBox(const RawShape& poly, const PolygonTag&)
|
inline _Box<TPoint<S>> boundingBox(const S& poly, const PolygonTag&)
|
||||||
{
|
{
|
||||||
return boundingBox(contour(poly), PathTag());
|
return boundingBox(contour(poly), PathTag());
|
||||||
}
|
}
|
||||||
@ -938,40 +966,40 @@ template<class S> inline double area(const S& poly, const PolygonTag& )
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Dispatching function
|
template<class S> // Dispatching function
|
||||||
inline double area(const RawShape& sh)
|
inline double area(const S& sh)
|
||||||
{
|
{
|
||||||
return area(sh, Tag<RawShape>());
|
return area(sh, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShapes>
|
template<class RawShapes>
|
||||||
inline double area(const RawShapes& shapes, const MultiPolygonTag&)
|
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,
|
return std::accumulate(shapes.begin(), shapes.end(), 0.0,
|
||||||
[](double a, const RawShape& b) {
|
[](double a, const S& b) {
|
||||||
return a += area(b);
|
return a += area(b);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline RawShape convexHull(const RawShape& sh, const PolygonTag&)
|
inline S convexHull(const S& sh, const PolygonTag&)
|
||||||
{
|
{
|
||||||
return create<RawShape>(convexHull(contour(sh), PathTag()));
|
return create<S>(convexHull(contour(sh), PathTag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline auto convexHull(const RawShape& sh)
|
inline auto convexHull(const S& sh)
|
||||||
-> decltype(convexHull(sh, Tag<RawShape>())) // TODO: C++14 could deduce
|
-> decltype(convexHull(sh, Tag<S>())) // TODO: C++14 could deduce
|
||||||
{
|
{
|
||||||
return convexHull(sh, Tag<RawShape>());
|
return convexHull(sh, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline RawShape convexHull(const RawShape& sh, const PathTag&)
|
inline S convexHull(const S& sh, const PathTag&)
|
||||||
{
|
{
|
||||||
using Unit = TCompute<RawShape>;
|
using Unit = TCompute<S>;
|
||||||
using Point = TPoint<RawShape>;
|
using Point = TPoint<S>;
|
||||||
namespace sl = shapelike;
|
namespace sl = shapelike;
|
||||||
|
|
||||||
size_t edges = sl::cend(sh) - sl::cbegin(sh);
|
size_t edges = sl::cend(sh) - sl::cbegin(sh);
|
||||||
@ -1016,8 +1044,8 @@ inline RawShape convexHull(const RawShape& sh, const PathTag&)
|
|||||||
++ik;
|
++ik;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawShape ret; reserve(ret, U.size() + L.size());
|
S ret; reserve(ret, U.size() + L.size());
|
||||||
if(is_clockwise<RawShape>()) {
|
if(is_clockwise<S>()) {
|
||||||
for(auto it = U.begin(); it != std::prev(U.end()); ++it)
|
for(auto it = U.begin(); it != std::prev(U.end()); ++it)
|
||||||
addVertex(ret, *it);
|
addVertex(ret, *it);
|
||||||
for(auto it = L.rbegin(); it != std::prev(L.rend()); ++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;
|
return px > minx && px < maxx && py > miny && py < maxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class TC>
|
template<class S, class TC>
|
||||||
inline bool isInside(const RawShape& sh, const TC& circ,
|
inline bool isInside(const S& sh, const TC& circ,
|
||||||
const PolygonTag&, const CircleTag&)
|
const PolygonTag&, const CircleTag&)
|
||||||
{
|
{
|
||||||
return std::all_of(cbegin(sh), cend(sh), [&circ](const TPoint<RawShape>& p)
|
return std::all_of(cbegin(sh), cend(sh), [&circ](const TPoint<S>& p)
|
||||||
{
|
{
|
||||||
return isInside(p, circ, PointTag(), CircleTag());
|
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;
|
return iminX > minX && imaxX < maxX && iminY > minY && imaxY < maxY;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class TB>
|
template<class S, class TB>
|
||||||
inline bool isInside(const RawShape& poly, const TB& box,
|
inline bool isInside(const S& poly, const TB& box,
|
||||||
const PolygonTag&, const BoxTag&)
|
const PolygonTag&, const BoxTag&)
|
||||||
{
|
{
|
||||||
return isInside(boundingBox(poly), box, BoxTag(), 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<TGuest>(), Tag<THost>());
|
return isInside(guest, host, Tag<TGuest>(), Tag<THost>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Potential O(1) implementation may exist
|
template<class S> // Potential O(1) implementation may exist
|
||||||
inline TPoint<RawShape>& vertex(RawShape& sh, unsigned long idx,
|
inline TPoint<S>& vertex(S& sh, unsigned long idx,
|
||||||
const PolygonTag&)
|
const PolygonTag&)
|
||||||
{
|
{
|
||||||
return *(shapelike::begin(contour(sh)) + idx);
|
return *(shapelike::begin(contour(sh)) + idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Potential O(1) implementation may exist
|
template<class S> // Potential O(1) implementation may exist
|
||||||
inline TPoint<RawShape>& vertex(RawShape& sh, unsigned long idx,
|
inline TPoint<S>& vertex(S& sh, unsigned long idx,
|
||||||
const PathTag&)
|
const PathTag&)
|
||||||
{
|
{
|
||||||
return *(shapelike::begin(sh) + idx);
|
return *(shapelike::begin(sh) + idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Potential O(1) implementation may exist
|
template<class S> // Potential O(1) implementation may exist
|
||||||
inline TPoint<RawShape>& vertex(RawShape& sh, unsigned long idx)
|
inline TPoint<S>& vertex(S& sh, unsigned long idx)
|
||||||
{
|
{
|
||||||
return vertex(sh, idx, Tag<RawShape>());
|
return vertex(sh, idx, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Potential O(1) implementation may exist
|
template<class S> // Potential O(1) implementation may exist
|
||||||
inline const TPoint<RawShape>& vertex(const RawShape& sh,
|
inline const TPoint<S>& vertex(const S& sh,
|
||||||
unsigned long idx,
|
unsigned long idx,
|
||||||
const PolygonTag&)
|
const PolygonTag&)
|
||||||
{
|
{
|
||||||
return *(shapelike::cbegin(contour(sh)) + idx);
|
return *(shapelike::cbegin(contour(sh)) + idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> // Potential O(1) implementation may exist
|
template<class S> // Potential O(1) implementation may exist
|
||||||
inline const TPoint<RawShape>& vertex(const RawShape& sh,
|
inline const TPoint<S>& vertex(const S& sh,
|
||||||
unsigned long idx,
|
unsigned long idx,
|
||||||
const PathTag&)
|
const PathTag&)
|
||||||
{
|
{
|
||||||
@ -1152,28 +1180,28 @@ inline const TPoint<RawShape>& vertex(const RawShape& sh,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class RawShape> // Potential O(1) implementation may exist
|
template<class S> // Potential O(1) implementation may exist
|
||||||
inline const TPoint<RawShape>& vertex(const RawShape& sh,
|
inline const TPoint<S>& vertex(const S& sh,
|
||||||
unsigned long idx)
|
unsigned long idx)
|
||||||
{
|
{
|
||||||
return vertex(sh, idx, Tag<RawShape>());
|
return vertex(sh, idx, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape>
|
template<class S>
|
||||||
inline size_t contourVertexCount(const RawShape& sh)
|
inline size_t contourVertexCount(const S& sh)
|
||||||
{
|
{
|
||||||
return shapelike::cend(sh) - shapelike::cbegin(sh);
|
return shapelike::cend(sh) - shapelike::cbegin(sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class Fn>
|
template<class S, class Fn>
|
||||||
inline void foreachVertex(RawShape& sh, Fn fn, const PolygonTag&) {
|
inline void foreachVertex(S& sh, Fn fn, const PolygonTag&) {
|
||||||
foreachVertex(contour(sh), fn, PathTag());
|
foreachVertex(contour(sh), fn, PathTag());
|
||||||
for(auto& h : holes(sh)) foreachVertex(h, fn, PathTag());
|
for(auto& h : holes(sh)) foreachVertex(h, fn, PathTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape, class Fn>
|
template<class S, class Fn>
|
||||||
inline void foreachVertex(RawShape& sh, Fn fn) {
|
inline void foreachVertex(S& sh, Fn fn) {
|
||||||
foreachVertex(sh, fn, Tag<RawShape>());
|
foreachVertex(sh, fn, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Poly> inline bool isConvex(const Poly& sh, const PolygonTag&)
|
template<class Poly> inline bool isConvex(const Poly& sh, const PolygonTag&)
|
||||||
@ -1184,9 +1212,9 @@ template<class Poly> inline bool isConvex(const Poly& sh, const PolygonTag&)
|
|||||||
return convex;
|
return convex;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class RawShape> inline bool isConvex(const RawShape& sh) // dispatch
|
template<class S> inline bool isConvex(const S& sh) // dispatch
|
||||||
{
|
{
|
||||||
return isConvex(sh, Tag<RawShape>());
|
return isConvex(sh, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user