mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-30 14:22:07 +00:00
Upgrade clipper & improve multi-thread performance (#7177)
* Clipper: Verify range of int32 coordinates on input. Cherry-picked from prusa3d/PrusaSlicer@fa7debf49d Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * ClipperLib: Optimized PointInPolygon() to calculate cross products with int64s instead of doubles. Cherry-picked from prusa3d/PrusaSlicer@9dca8403fe Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Reworked the ClipperLib / Polygon types to use the tbb::scallable_allocator to better scale on multiple threads. Cherry-picked from prusa3d/PrusaSlicer@9cde96993e Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * use tbb::scallable_allocator for Polygons and ExPolygon::holes to better scale on multiple threads Cherry-picked from prusa3d/PrusaSlicer@b67ad6434d Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Fixed compilation on GCC and CLang Cherry-picked from prusa3d/PrusaSlicer@b3b44681a9 Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Remove clipper2 which is not used * Removed shiny profiler from clipperlib Cherry-picked from prusa3d/PrusaSlicer@7e77048593 Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * ClipperLib: Further optimization of memory allocation using scalable_allocator. ClipperLib: SimplifyPolygon() - changed default winding number to positive, added strictly_simple parameter. ClipperUtlis simplify_polygons() - removed "remove_collinear" parameter Cherry-picked from prusa3d/PrusaSlicer@a7e17df25f Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * ClipperLib: emplace_back() instead of push_back(). Cherry-picked from prusa3d/PrusaSlicer@2e150795b1 Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Fixed issue in a 32bit clipper, where IntersectPoint() checked for the Y coordinate of the calculated intersection point for validity, but the Y coordinate was already rounded to 32bits, thus an overflow may have in rare cases masked invalidity of the result. Cherry-picked from prusa3d/PrusaSlicer@b39c33414f Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Fixed Vojtech's out of boundary assert in Clipper library. Cherry-picked from prusa3d/PrusaSlicer@0a202dcff3 Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> * Update clipper to 6.4.2. Cherry-picked from prusa3d/PrusaSlicer@b8b3cccb40 Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com> * Try fix cmake opencv --------- Co-authored-by: Vojtech Bubnik <bubnikv@gmail.com> Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com>
This commit is contained in:
@@ -9,74 +9,75 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
template <class PointClass>
|
||||
template <typename PointType, typename APointsType = std::vector<PointType>>
|
||||
class BoundingBoxBase
|
||||
{
|
||||
public:
|
||||
PointClass min;
|
||||
PointClass max;
|
||||
using PointsType = APointsType;
|
||||
PointType min;
|
||||
PointType max;
|
||||
bool defined;
|
||||
|
||||
BoundingBoxBase() : min(PointClass::Zero()), max(PointClass::Zero()), defined(false) {}
|
||||
BoundingBoxBase(const PointClass &pmin, const PointClass &pmax) :
|
||||
min(pmin), max(pmax), defined(pmin(0) < pmax(0) && pmin(1) < pmax(1)) {}
|
||||
BoundingBoxBase(const PointClass &p1, const PointClass &p2, const PointClass &p3) :
|
||||
BoundingBoxBase() : min(PointType::Zero()), max(PointType::Zero()), defined(false) {}
|
||||
BoundingBoxBase(const PointType &pmin, const PointType &pmax) :
|
||||
min(pmin), max(pmax), defined(pmin.x() < pmax.x() && pmin.y() < pmax.y()) {}
|
||||
BoundingBoxBase(const PointType &p1, const PointType &p2, const PointType &p3) :
|
||||
min(p1), max(p1), defined(false) { merge(p2); merge(p3); }
|
||||
|
||||
template<class It, class = IteratorOnly<It>>
|
||||
BoundingBoxBase(It from, It to)
|
||||
{ construct(*this, from, to); }
|
||||
|
||||
BoundingBoxBase(const std::vector<PointClass> &points)
|
||||
BoundingBoxBase(const PointsType &points)
|
||||
: BoundingBoxBase(points.begin(), points.end())
|
||||
{}
|
||||
|
||||
void reset() { this->defined = false; this->min = PointClass::Zero(); this->max = PointClass::Zero(); }
|
||||
void merge(const PointClass &point);
|
||||
void merge(const std::vector<PointClass> &points);
|
||||
void merge(const BoundingBoxBase<PointClass> &bb);
|
||||
void reset() { this->defined = false; this->min = PointType::Zero(); this->max = PointType::Zero(); }
|
||||
void merge(const PointType &point);
|
||||
void merge(const PointsType &points);
|
||||
void merge(const BoundingBoxBase<PointType, PointsType> &bb);
|
||||
void scale(double factor);
|
||||
PointClass size() const;
|
||||
PointType size() const;
|
||||
double radius() const;
|
||||
double area() const { return double(this->max(0) - this->min(0)) * (this->max(1) - this->min(1)); } // BBS
|
||||
void translate(coordf_t x, coordf_t y) { assert(this->defined); PointClass v(x, y); this->min += v; this->max += v; }
|
||||
void translate(const Vec2d& v0) { PointClass v(v0.x(), v0.y()); this->min += v; this->max += v; }
|
||||
void translate(coordf_t x, coordf_t y) { assert(this->defined); PointType v(x, y); this->min += v; this->max += v; }
|
||||
void translate(const PointType &v) { this->min += v; this->max += v; }
|
||||
void offset(coordf_t delta);
|
||||
BoundingBoxBase<PointClass> inflated(coordf_t delta) const throw() { BoundingBoxBase<PointClass> out(*this); out.offset(delta); return out; }
|
||||
PointClass center() const;
|
||||
bool contains(const PointClass &point) const {
|
||||
return point(0) >= this->min(0) && point(0) <= this->max(0)
|
||||
&& point(1) >= this->min(1) && point(1) <= this->max(1);
|
||||
BoundingBoxBase<PointType, PointsType> inflated(coordf_t delta) const throw() { BoundingBoxBase<PointType, PointsType> out(*this); out.offset(delta); return out; }
|
||||
PointType center() const;
|
||||
bool contains(const PointType &point) const {
|
||||
return point.x() >= this->min.x() && point.x() <= this->max.x()
|
||||
&& point.y() >= this->min.y() && point.y() <= this->max.y();
|
||||
}
|
||||
bool contains(const BoundingBoxBase<PointClass> &other) const {
|
||||
bool contains(const BoundingBoxBase<PointType, PointsType> &other) const {
|
||||
return contains(other.min) && contains(other.max);
|
||||
}
|
||||
bool overlap(const BoundingBoxBase<PointClass> &other) const {
|
||||
return ! (this->max(0) < other.min(0) || this->min(0) > other.max(0) ||
|
||||
this->max(1) < other.min(1) || this->min(1) > other.max(1));
|
||||
bool overlap(const BoundingBoxBase<PointType, PointsType> &other) const {
|
||||
return ! (this->max.x() < other.min.x() || this->min.x() > other.max.x() ||
|
||||
this->max.y() < other.min.y() || this->min.y() > other.max.y());
|
||||
}
|
||||
PointClass operator[](size_t idx) const {
|
||||
PointType operator[](size_t idx) const {
|
||||
switch (idx) {
|
||||
case 0:
|
||||
return min;
|
||||
break;
|
||||
case 1:
|
||||
return PointClass(max(0), min(1));
|
||||
return PointType(max(0), min(1));
|
||||
break;
|
||||
case 2:
|
||||
return max;
|
||||
break;
|
||||
case 3:
|
||||
return PointClass(min(0), max(1));
|
||||
return PointType(min(0), max(1));
|
||||
break;
|
||||
default:
|
||||
return PointClass();
|
||||
return PointType();
|
||||
break;
|
||||
}
|
||||
return PointClass();
|
||||
return PointType();
|
||||
}
|
||||
bool operator==(const BoundingBoxBase<PointClass> &rhs) { return this->min == rhs.min && this->max == rhs.max; }
|
||||
bool operator!=(const BoundingBoxBase<PointClass> &rhs) { return ! (*this == rhs); }
|
||||
bool operator==(const BoundingBoxBase<PointType, PointsType> &rhs) { return this->min == rhs.min && this->max == rhs.max; }
|
||||
bool operator!=(const BoundingBoxBase<PointType, PointsType> &rhs) { return ! (*this == rhs); }
|
||||
friend std::ostream &operator<<(std::ostream &os, const BoundingBoxBase &bbox)
|
||||
{
|
||||
os << "[" << bbox.max(0) - bbox.min(0) << " x " << bbox.max(1) - bbox.min(1) << "] from (" << bbox.min(0) << ", " << bbox.min(1) << ")";
|
||||
@@ -96,10 +97,10 @@ private:
|
||||
{
|
||||
if (from != to) {
|
||||
auto it = from;
|
||||
out.min = it->template cast<typename PointClass::Scalar>();
|
||||
out.min = it->template cast<typename PointType::Scalar>();
|
||||
out.max = out.min;
|
||||
for (++ it; it != to; ++ it) {
|
||||
auto vec = it->template cast<typename PointClass::Scalar>();
|
||||
auto vec = it->template cast<typename PointType::Scalar>();
|
||||
out.min = out.min.cwiseMin(vec);
|
||||
out.max = out.max.cwiseMax(vec);
|
||||
}
|
||||
@@ -108,16 +109,18 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <class PointClass>
|
||||
class BoundingBox3Base : public BoundingBoxBase<PointClass>
|
||||
template <class PointType>
|
||||
class BoundingBox3Base : public BoundingBoxBase<PointType, std::vector<PointType>>
|
||||
{
|
||||
public:
|
||||
BoundingBox3Base() : BoundingBoxBase<PointClass>() {}
|
||||
BoundingBox3Base(const PointClass &pmin, const PointClass &pmax) :
|
||||
BoundingBoxBase<PointClass>(pmin, pmax)
|
||||
{ if (pmin(2) >= pmax(2)) BoundingBoxBase<PointClass>::defined = false; }
|
||||
BoundingBox3Base(const PointClass &p1, const PointClass &p2, const PointClass &p3) :
|
||||
BoundingBoxBase<PointClass>(p1, p1) { merge(p2); merge(p3); }
|
||||
using PointsType = std::vector<PointType>;
|
||||
|
||||
BoundingBox3Base() : BoundingBoxBase<PointType>() {}
|
||||
BoundingBox3Base(const PointType &pmin, const PointType &pmax) :
|
||||
BoundingBoxBase<PointType>(pmin, pmax)
|
||||
{ if (pmin.z() >= pmax.z()) BoundingBoxBase<PointType>::defined = false; }
|
||||
BoundingBox3Base(const PointType &p1, const PointType &p2, const PointType &p3) :
|
||||
BoundingBoxBase<PointType>(p1, p1) { merge(p2); merge(p3); }
|
||||
|
||||
template<class It, class = IteratorOnly<It> > BoundingBox3Base(It from, It to)
|
||||
{
|
||||
@@ -125,66 +128,68 @@ public:
|
||||
throw Slic3r::InvalidArgument("Empty point set supplied to BoundingBox3Base constructor");
|
||||
|
||||
auto it = from;
|
||||
this->min = it->template cast<typename PointClass::Scalar>();
|
||||
this->min = it->template cast<typename PointType::Scalar>();
|
||||
this->max = this->min;
|
||||
for (++ it; it != to; ++ it) {
|
||||
auto vec = it->template cast<typename PointClass::Scalar>();
|
||||
auto vec = it->template cast<typename PointType::Scalar>();
|
||||
this->min = this->min.cwiseMin(vec);
|
||||
this->max = this->max.cwiseMax(vec);
|
||||
}
|
||||
this->defined = (this->min(0) < this->max(0)) && (this->min(1) < this->max(1)) && (this->min(2) < this->max(2));
|
||||
this->defined = (this->min.x() < this->max.x()) && (this->min.y() < this->max.y()) && (this->min.z() < this->max.z());
|
||||
}
|
||||
|
||||
BoundingBox3Base(const std::vector<PointClass> &points)
|
||||
BoundingBox3Base(const PointsType &points)
|
||||
: BoundingBox3Base(points.begin(), points.end())
|
||||
{}
|
||||
|
||||
Polygon polygon(bool is_scaled = false) const;//BBS: 2D footprint polygon
|
||||
void merge(const PointClass &point);
|
||||
void merge(const std::vector<PointClass> &points);
|
||||
void merge(const BoundingBox3Base<PointClass> &bb);
|
||||
PointClass size() const;
|
||||
void merge(const PointType &point);
|
||||
void merge(const PointsType &points);
|
||||
void merge(const BoundingBox3Base<PointType> &bb);
|
||||
PointType size() const;
|
||||
double radius() const;
|
||||
void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointClass v(x, y, z); this->min += v; this->max += v; }
|
||||
void translate(coordf_t x, coordf_t y, coordf_t z) { assert(this->defined); PointType v(x, y, z); this->min += v; this->max += v; }
|
||||
void translate(const Vec3d &v) { this->min += v; this->max += v; }
|
||||
void offset(coordf_t delta);
|
||||
BoundingBox3Base<PointClass> inflated(coordf_t delta) const throw() { BoundingBox3Base<PointClass> out(*this); out.offset(delta); return out; }
|
||||
PointClass center() const;
|
||||
BoundingBox3Base<PointType> inflated(coordf_t delta) const throw() { BoundingBox3Base<PointType> out(*this); out.offset(delta); return out; }
|
||||
PointType center() const;
|
||||
coordf_t max_size() const;
|
||||
|
||||
bool contains(const PointClass &point) const {
|
||||
return BoundingBoxBase<PointClass>::contains(point) && point(2) >= this->min(2) && point(2) <= this->max(2);
|
||||
bool contains(const PointType &point) const {
|
||||
return BoundingBoxBase<PointType>::contains(point) && point.z() >= this->min.z() && point.z() <= this->max.z();
|
||||
}
|
||||
|
||||
bool contains(const BoundingBox3Base<PointClass>& other) const {
|
||||
bool contains(const BoundingBox3Base<PointType>& other) const {
|
||||
return contains(other.min) && contains(other.max);
|
||||
}
|
||||
|
||||
bool intersects(const BoundingBox3Base<PointClass>& other) const {
|
||||
return (this->min(0) < other.max(0)) && (this->max(0) > other.min(0)) && (this->min(1) < other.max(1)) && (this->max(1) > other.min(1)) && (this->min(2) < other.max(2)) && (this->max(2) > other.min(2));
|
||||
// Intersects without boundaries.
|
||||
bool intersects(const BoundingBox3Base<PointType>& other) const {
|
||||
return this->min.x() < other.max.x() && this->max.x() > other.min.x() && this->min.y() < other.max.y() && this->max.y() > other.min.y() &&
|
||||
this->min.z() < other.max.z() && this->max.z() > other.min.z();
|
||||
}
|
||||
};
|
||||
|
||||
// Will prevent warnings caused by non existing definition of template in hpp
|
||||
extern template void BoundingBoxBase<Point>::scale(double factor);
|
||||
extern template void BoundingBoxBase<Point, Points>::scale(double factor);
|
||||
extern template void BoundingBoxBase<Vec2d>::scale(double factor);
|
||||
extern template void BoundingBoxBase<Vec3d>::scale(double factor);
|
||||
extern template void BoundingBoxBase<Point>::offset(coordf_t delta);
|
||||
extern template void BoundingBoxBase<Point, Points>::offset(coordf_t delta);
|
||||
extern template void BoundingBoxBase<Vec2d>::offset(coordf_t delta);
|
||||
extern template void BoundingBoxBase<Point>::merge(const Point &point);
|
||||
extern template void BoundingBoxBase<Point, Points>::merge(const Point &point);
|
||||
extern template void BoundingBoxBase<Vec2f>::merge(const Vec2f &point);
|
||||
extern template void BoundingBoxBase<Vec2d>::merge(const Vec2d &point);
|
||||
extern template void BoundingBoxBase<Point>::merge(const Points &points);
|
||||
extern template void BoundingBoxBase<Point, Points>::merge(const Points &points);
|
||||
extern template void BoundingBoxBase<Vec2d>::merge(const Pointfs &points);
|
||||
extern template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
|
||||
extern template void BoundingBoxBase<Point, Points>::merge(const BoundingBoxBase<Point, Points> &bb);
|
||||
extern template void BoundingBoxBase<Vec2f>::merge(const BoundingBoxBase<Vec2f> &bb);
|
||||
extern template void BoundingBoxBase<Vec2d>::merge(const BoundingBoxBase<Vec2d> &bb);
|
||||
extern template Point BoundingBoxBase<Point>::size() const;
|
||||
extern template Point BoundingBoxBase<Point, Points>::size() const;
|
||||
extern template Vec2f BoundingBoxBase<Vec2f>::size() const;
|
||||
extern template Vec2d BoundingBoxBase<Vec2d>::size() const;
|
||||
extern template double BoundingBoxBase<Point>::radius() const;
|
||||
extern template double BoundingBoxBase<Point, Points>::radius() const;
|
||||
extern template double BoundingBoxBase<Vec2d>::radius() const;
|
||||
extern template Point BoundingBoxBase<Point>::center() const;
|
||||
extern template Point BoundingBoxBase<Point, Points>::center() const;
|
||||
extern template Vec2f BoundingBoxBase<Vec2f>::center() const;
|
||||
extern template Vec2d BoundingBoxBase<Vec2d>::center() const;
|
||||
extern template void BoundingBox3Base<Vec3f>::merge(const Vec3f &point);
|
||||
@@ -200,7 +205,7 @@ extern template Vec3d BoundingBox3Base<Vec3d>::center() const;
|
||||
extern template coordf_t BoundingBox3Base<Vec3f>::max_size() const;
|
||||
extern template coordf_t BoundingBox3Base<Vec3d>::max_size() const;
|
||||
|
||||
class BoundingBox : public BoundingBoxBase<Point>
|
||||
class BoundingBox : public BoundingBoxBase<Point, Points>
|
||||
{
|
||||
public:
|
||||
void polygon(Polygon* polygon) const;
|
||||
@@ -213,9 +218,9 @@ public:
|
||||
// to encompass the original bounding box.
|
||||
void align_to_grid(const coord_t cell_size);
|
||||
|
||||
BoundingBox() : BoundingBoxBase<Point>() {}
|
||||
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point>(pmin, pmax) {}
|
||||
BoundingBox(const Points &points) : BoundingBoxBase<Point>(points) {}
|
||||
BoundingBox() : BoundingBoxBase<Point, Points>() {}
|
||||
BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase<Point, Points>(pmin, pmax) {}
|
||||
BoundingBox(const Points &points) : BoundingBoxBase<Point, Points>(points) {}
|
||||
|
||||
BoundingBox inflated(coordf_t delta) const throw() { BoundingBox out(*this); out.offset(delta); return out; }
|
||||
|
||||
@@ -248,22 +253,31 @@ public:
|
||||
BoundingBoxf3 transformed(const Transform3d& matrix) const;
|
||||
};
|
||||
|
||||
template<typename VT>
|
||||
inline bool empty(const BoundingBoxBase<VT> &bb)
|
||||
template<typename PointType, typename PointsType>
|
||||
inline bool empty(const BoundingBoxBase<PointType, PointsType> &bb)
|
||||
{
|
||||
return ! bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1);
|
||||
return ! bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y();
|
||||
}
|
||||
|
||||
template<typename VT>
|
||||
inline bool empty(const BoundingBox3Base<VT> &bb)
|
||||
template<typename PointType>
|
||||
inline bool empty(const BoundingBox3Base<PointType> &bb)
|
||||
{
|
||||
return ! bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1) || bb.min(2) >= bb.max(2);
|
||||
return ! bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y() || bb.min.z() >= bb.max.z();
|
||||
}
|
||||
|
||||
inline BoundingBox scaled(const BoundingBoxf &bb) { return {scaled(bb.min), scaled(bb.max)}; }
|
||||
inline BoundingBox3 scaled(const BoundingBoxf3 &bb) { return {scaled(bb.min), scaled(bb.max)}; }
|
||||
inline BoundingBoxf unscaled(const BoundingBox &bb) { return {unscaled(bb.min), unscaled(bb.max)}; }
|
||||
inline BoundingBoxf3 unscaled(const BoundingBox3 &bb) { return {unscaled(bb.min), unscaled(bb.max)}; }
|
||||
|
||||
template<class T = coord_t>
|
||||
BoundingBoxBase<Vec<2, T>> scaled(const BoundingBoxf &bb) { return {scaled<T>(bb.min), scaled<T>(bb.max)}; }
|
||||
|
||||
template<class T = coord_t>
|
||||
BoundingBox3Base<Vec<3, T>> scaled(const BoundingBoxf3 &bb) { return {scaled<T>(bb.min), scaled<T>(bb.max)}; }
|
||||
|
||||
template<class T = double>
|
||||
BoundingBoxBase<Vec<2, T>> unscaled(const BoundingBox &bb) { return {unscaled<T>(bb.min), unscaled<T>(bb.max)}; }
|
||||
|
||||
template<class T = double>
|
||||
BoundingBox3Base<Vec<3, T>> unscaled(const BoundingBox3 &bb) { return {unscaled<T>(bb.min), unscaled<T>(bb.max)}; }
|
||||
|
||||
template<class Tout, class Tin>
|
||||
auto cast(const BoundingBoxBase<Tin> &b)
|
||||
|
||||
Reference in New Issue
Block a user