mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-29 05:42:33 +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:
@@ -1,7 +1,6 @@
|
||||
#ifndef SRC_LIBSLIC3R_ALGORITHM_LINE_SPLIT_HPP_
|
||||
#define SRC_LIBSLIC3R_ALGORITHM_LINE_SPLIT_HPP_
|
||||
|
||||
#include "clipper2/clipper.core.h"
|
||||
#include "ClipperZUtils.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@@ -253,7 +253,7 @@ std::unique_ptr<LocToLineGrid> cre
|
||||
void fixSelfIntersections(const coord_t epsilon, Polygons &thiss)
|
||||
{
|
||||
if (epsilon < 1) {
|
||||
ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(thiss));
|
||||
ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(thiss), ClipperLib::pftEvenOdd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ void fixSelfIntersections(const coord_t epsilon, Polygons &thiss)
|
||||
}
|
||||
}
|
||||
|
||||
ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(thiss));
|
||||
ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(thiss), ClipperLib::pftEvenOdd);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -7,23 +7,19 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
template BoundingBoxBase<Point>::BoundingBoxBase(const std::vector<Point> &points);
|
||||
template BoundingBoxBase<Point, Points>::BoundingBoxBase(const Points &points);
|
||||
template BoundingBoxBase<Vec2d>::BoundingBoxBase(const std::vector<Vec2d> &points);
|
||||
|
||||
template BoundingBox3Base<Vec3d>::BoundingBox3Base(const std::vector<Vec3d> &points);
|
||||
|
||||
void BoundingBox::polygon(Polygon* polygon) const
|
||||
{
|
||||
polygon->points.clear();
|
||||
polygon->points.resize(4);
|
||||
polygon->points[0](0) = this->min(0);
|
||||
polygon->points[0](1) = this->min(1);
|
||||
polygon->points[1](0) = this->max(0);
|
||||
polygon->points[1](1) = this->min(1);
|
||||
polygon->points[2](0) = this->max(0);
|
||||
polygon->points[2](1) = this->max(1);
|
||||
polygon->points[3](0) = this->min(0);
|
||||
polygon->points[3](1) = this->max(1);
|
||||
polygon->points = {
|
||||
this->min,
|
||||
{ this->max.x(), this->min.y() },
|
||||
this->max,
|
||||
{ this->min.x(), this->max.y() }
|
||||
};
|
||||
}
|
||||
|
||||
Polygon BoundingBox::polygon() const
|
||||
@@ -38,8 +34,8 @@ BoundingBox BoundingBox::rotated(double angle) const
|
||||
BoundingBox out;
|
||||
out.merge(this->min.rotated(angle));
|
||||
out.merge(this->max.rotated(angle));
|
||||
out.merge(Point(this->min(0), this->max(1)).rotated(angle));
|
||||
out.merge(Point(this->max(0), this->min(1)).rotated(angle));
|
||||
out.merge(Point(this->min.x(), this->max.y()).rotated(angle));
|
||||
out.merge(Point(this->max.x(), this->min.y()).rotated(angle));
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -48,23 +44,23 @@ BoundingBox BoundingBox::rotated(double angle, const Point ¢er) const
|
||||
BoundingBox out;
|
||||
out.merge(this->min.rotated(angle, center));
|
||||
out.merge(this->max.rotated(angle, center));
|
||||
out.merge(Point(this->min(0), this->max(1)).rotated(angle, center));
|
||||
out.merge(Point(this->max(0), this->min(1)).rotated(angle, center));
|
||||
out.merge(Point(this->min.x(), this->max.y()).rotated(angle, center));
|
||||
out.merge(Point(this->max.x(), this->min.y()).rotated(angle, center));
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBoxBase<PointClass>::scale(double factor)
|
||||
template <class PointType, typename APointsType> void
|
||||
BoundingBoxBase<PointType, APointsType>::scale(double factor)
|
||||
{
|
||||
this->min *= factor;
|
||||
this->max *= factor;
|
||||
}
|
||||
template void BoundingBoxBase<Point>::scale(double factor);
|
||||
template void BoundingBoxBase<Point, Points>::scale(double factor);
|
||||
template void BoundingBoxBase<Vec2d>::scale(double factor);
|
||||
template void BoundingBoxBase<Vec3d>::scale(double factor);
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBoxBase<PointClass>::merge(const PointClass &point)
|
||||
template <class PointType, typename APointsType> void
|
||||
BoundingBoxBase<PointType, APointsType>::merge(const PointType &point)
|
||||
{
|
||||
if (this->defined) {
|
||||
this->min = this->min.cwiseMin(point);
|
||||
@@ -75,22 +71,22 @@ BoundingBoxBase<PointClass>::merge(const PointClass &point)
|
||||
this->defined = true;
|
||||
}
|
||||
}
|
||||
template void BoundingBoxBase<Point>::merge(const Point &point);
|
||||
template void BoundingBoxBase<Point, Points>::merge(const Point &point);
|
||||
template void BoundingBoxBase<Vec2f>::merge(const Vec2f &point);
|
||||
template void BoundingBoxBase<Vec2d>::merge(const Vec2d &point);
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBoxBase<PointClass>::merge(const std::vector<PointClass> &points)
|
||||
template <class PointType, typename APointsType> void
|
||||
BoundingBoxBase<PointType, APointsType>::merge(const PointsType &points)
|
||||
{
|
||||
this->merge(BoundingBoxBase(points));
|
||||
}
|
||||
template void BoundingBoxBase<Point>::merge(const Points &points);
|
||||
template void BoundingBoxBase<Point, Points>::merge(const Points &points);
|
||||
template void BoundingBoxBase<Vec2d>::merge(const Pointfs &points);
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
|
||||
template <class PointType, typename APointsType> void
|
||||
BoundingBoxBase<PointType, APointsType>::merge(const BoundingBoxBase<PointType, PointsType> &bb)
|
||||
{
|
||||
assert(bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1));
|
||||
assert(bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y());
|
||||
if (bb.defined) {
|
||||
if (this->defined) {
|
||||
this->min = this->min.cwiseMin(bb.min);
|
||||
@@ -102,13 +98,13 @@ BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
|
||||
}
|
||||
}
|
||||
}
|
||||
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
|
||||
template void BoundingBoxBase<Point, Points>::merge(const BoundingBoxBase<Point, Points> &bb);
|
||||
template void BoundingBoxBase<Vec2f>::merge(const BoundingBoxBase<Vec2f> &bb);
|
||||
template void BoundingBoxBase<Vec2d>::merge(const BoundingBoxBase<Vec2d> &bb);
|
||||
|
||||
//BBS
|
||||
template <class PointClass>
|
||||
Polygon BoundingBox3Base<PointClass>::polygon(bool is_scaled) const
|
||||
template <class PointType>
|
||||
Polygon BoundingBox3Base<PointType>::polygon(bool is_scaled) const
|
||||
{
|
||||
Polygon polygon;
|
||||
polygon.points.clear();
|
||||
@@ -127,8 +123,8 @@ Polygon BoundingBox3Base<PointClass>::polygon(bool is_scaled) const
|
||||
template Polygon BoundingBox3Base<Vec3f>::polygon(bool is_scaled) const;
|
||||
template Polygon BoundingBox3Base<Vec3d>::polygon(bool is_scaled) const;
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBox3Base<PointClass>::merge(const PointClass &point)
|
||||
template <class PointType> void
|
||||
BoundingBox3Base<PointType>::merge(const PointType &point)
|
||||
{
|
||||
if (this->defined) {
|
||||
this->min = this->min.cwiseMin(point);
|
||||
@@ -142,17 +138,17 @@ BoundingBox3Base<PointClass>::merge(const PointClass &point)
|
||||
template void BoundingBox3Base<Vec3f>::merge(const Vec3f &point);
|
||||
template void BoundingBox3Base<Vec3d>::merge(const Vec3d &point);
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBox3Base<PointClass>::merge(const std::vector<PointClass> &points)
|
||||
template <class PointType> void
|
||||
BoundingBox3Base<PointType>::merge(const PointsType &points)
|
||||
{
|
||||
this->merge(BoundingBox3Base(points));
|
||||
}
|
||||
template void BoundingBox3Base<Vec3d>::merge(const Pointf3s &points);
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
|
||||
template <class PointType> void
|
||||
BoundingBox3Base<PointType>::merge(const BoundingBox3Base<PointType> &bb)
|
||||
{
|
||||
assert(bb.defined || bb.min(0) >= bb.max(0) || bb.min(1) >= bb.max(1) || bb.min(2) >= bb.max(2));
|
||||
assert(bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y() || bb.min.z() >= bb.max.z());
|
||||
if (bb.defined) {
|
||||
if (this->defined) {
|
||||
this->min = this->min.cwiseMin(bb.min);
|
||||
@@ -166,83 +162,78 @@ BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
|
||||
}
|
||||
template void BoundingBox3Base<Vec3d>::merge(const BoundingBox3Base<Vec3d> &bb);
|
||||
|
||||
template <class PointClass> PointClass
|
||||
BoundingBoxBase<PointClass>::size() const
|
||||
template <class PointType, typename APointsType> PointType
|
||||
BoundingBoxBase<PointType, APointsType>::size() const
|
||||
{
|
||||
return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1));
|
||||
return this->max - this->min;
|
||||
}
|
||||
template Point BoundingBoxBase<Point>::size() const;
|
||||
template Point BoundingBoxBase<Point, Points>::size() const;
|
||||
template Vec2f BoundingBoxBase<Vec2f>::size() const;
|
||||
template Vec2d BoundingBoxBase<Vec2d>::size() const;
|
||||
|
||||
template <class PointClass> PointClass
|
||||
BoundingBox3Base<PointClass>::size() const
|
||||
template <class PointType> PointType
|
||||
BoundingBox3Base<PointType>::size() const
|
||||
{
|
||||
return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1), this->max(2) - this->min(2));
|
||||
return this->max - this->min;
|
||||
}
|
||||
template Vec3f BoundingBox3Base<Vec3f>::size() const;
|
||||
template Vec3d BoundingBox3Base<Vec3d>::size() const;
|
||||
|
||||
template <class PointClass> double BoundingBoxBase<PointClass>::radius() const
|
||||
template <class PointType, typename APointsType> double BoundingBoxBase<PointType, APointsType>::radius() const
|
||||
{
|
||||
assert(this->defined);
|
||||
double x = this->max(0) - this->min(0);
|
||||
double y = this->max(1) - this->min(1);
|
||||
return 0.5 * sqrt(x*x+y*y);
|
||||
return 0.5 * (this->max - this->min).template cast<double>().norm();
|
||||
}
|
||||
template double BoundingBoxBase<Point>::radius() const;
|
||||
template double BoundingBoxBase<Point, Points>::radius() const;
|
||||
template double BoundingBoxBase<Vec2d>::radius() const;
|
||||
|
||||
template <class PointClass> double BoundingBox3Base<PointClass>::radius() const
|
||||
template <class PointType> double BoundingBox3Base<PointType>::radius() const
|
||||
{
|
||||
double x = this->max(0) - this->min(0);
|
||||
double y = this->max(1) - this->min(1);
|
||||
double z = this->max(2) - this->min(2);
|
||||
return 0.5 * sqrt(x*x+y*y+z*z);
|
||||
return 0.5 * (this->max - this->min).template cast<double>().norm();
|
||||
}
|
||||
template double BoundingBox3Base<Vec3d>::radius() const;
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBoxBase<PointClass>::offset(coordf_t delta)
|
||||
template <class PointType, typename APointsType> void
|
||||
BoundingBoxBase<PointType, APointsType>::offset(coordf_t delta)
|
||||
{
|
||||
PointClass v(delta, delta);
|
||||
PointType v(delta, delta);
|
||||
this->min -= v;
|
||||
this->max += v;
|
||||
}
|
||||
template void BoundingBoxBase<Point>::offset(coordf_t delta);
|
||||
template void BoundingBoxBase<Point, Points>::offset(coordf_t delta);
|
||||
template void BoundingBoxBase<Vec2d>::offset(coordf_t delta);
|
||||
|
||||
template <class PointClass> void
|
||||
BoundingBox3Base<PointClass>::offset(coordf_t delta)
|
||||
template <class PointType> void
|
||||
BoundingBox3Base<PointType>::offset(coordf_t delta)
|
||||
{
|
||||
PointClass v(delta, delta, delta);
|
||||
PointType v(delta, delta, delta);
|
||||
this->min -= v;
|
||||
this->max += v;
|
||||
}
|
||||
template void BoundingBox3Base<Vec3d>::offset(coordf_t delta);
|
||||
|
||||
template <class PointClass> PointClass
|
||||
BoundingBoxBase<PointClass>::center() const
|
||||
template <class PointType, typename APointsType> PointType
|
||||
BoundingBoxBase<PointType, APointsType>::center() const
|
||||
{
|
||||
return (this->min + this->max) / 2;
|
||||
}
|
||||
template Point BoundingBoxBase<Point>::center() const;
|
||||
template Point BoundingBoxBase<Point, Points>::center() const;
|
||||
template Vec2f BoundingBoxBase<Vec2f>::center() const;
|
||||
template Vec2d BoundingBoxBase<Vec2d>::center() const;
|
||||
|
||||
template <class PointClass> PointClass
|
||||
BoundingBox3Base<PointClass>::center() const
|
||||
template <class PointType> PointType
|
||||
BoundingBox3Base<PointType>::center() const
|
||||
{
|
||||
return (this->min + this->max) / 2;
|
||||
}
|
||||
template Vec3f BoundingBox3Base<Vec3f>::center() const;
|
||||
template Vec3d BoundingBox3Base<Vec3d>::center() const;
|
||||
|
||||
template <class PointClass> coordf_t
|
||||
BoundingBox3Base<PointClass>::max_size() const
|
||||
template <class PointType> coordf_t
|
||||
BoundingBox3Base<PointType>::max_size() const
|
||||
{
|
||||
PointClass s = size();
|
||||
return std::max(s(0), std::max(s(1), s(2)));
|
||||
PointType s = size();
|
||||
return std::max(s.x(), std::max(s.y(), s.z()));
|
||||
}
|
||||
template coordf_t BoundingBox3Base<Vec3f>::max_size() const;
|
||||
template coordf_t BoundingBox3Base<Vec3d>::max_size() const;
|
||||
@@ -250,8 +241,8 @@ template coordf_t BoundingBox3Base<Vec3d>::max_size() const;
|
||||
void BoundingBox::align_to_grid(const coord_t cell_size)
|
||||
{
|
||||
if (this->defined) {
|
||||
min(0) = Slic3r::align_to_grid(min(0), cell_size);
|
||||
min(1) = Slic3r::align_to_grid(min(1), cell_size);
|
||||
min.x() = Slic3r::align_to_grid(min.x(), cell_size);
|
||||
min.y() = Slic3r::align_to_grid(min.y(), cell_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,14 +251,14 @@ BoundingBoxf3 BoundingBoxf3::transformed(const Transform3d& matrix) const
|
||||
typedef Eigen::Matrix<double, 3, 8, Eigen::DontAlign> Vertices;
|
||||
|
||||
Vertices src_vertices;
|
||||
src_vertices(0, 0) = min(0); src_vertices(1, 0) = min(1); src_vertices(2, 0) = min(2);
|
||||
src_vertices(0, 1) = max(0); src_vertices(1, 1) = min(1); src_vertices(2, 1) = min(2);
|
||||
src_vertices(0, 2) = max(0); src_vertices(1, 2) = max(1); src_vertices(2, 2) = min(2);
|
||||
src_vertices(0, 3) = min(0); src_vertices(1, 3) = max(1); src_vertices(2, 3) = min(2);
|
||||
src_vertices(0, 4) = min(0); src_vertices(1, 4) = min(1); src_vertices(2, 4) = max(2);
|
||||
src_vertices(0, 5) = max(0); src_vertices(1, 5) = min(1); src_vertices(2, 5) = max(2);
|
||||
src_vertices(0, 6) = max(0); src_vertices(1, 6) = max(1); src_vertices(2, 6) = max(2);
|
||||
src_vertices(0, 7) = min(0); src_vertices(1, 7) = max(1); src_vertices(2, 7) = max(2);
|
||||
src_vertices(0, 0) = min.x(); src_vertices(1, 0) = min.y(); src_vertices(2, 0) = min.z();
|
||||
src_vertices(0, 1) = max.x(); src_vertices(1, 1) = min.y(); src_vertices(2, 1) = min.z();
|
||||
src_vertices(0, 2) = max.x(); src_vertices(1, 2) = max.y(); src_vertices(2, 2) = min.z();
|
||||
src_vertices(0, 3) = min.x(); src_vertices(1, 3) = max.y(); src_vertices(2, 3) = min.z();
|
||||
src_vertices(0, 4) = min.x(); src_vertices(1, 4) = min.y(); src_vertices(2, 4) = max.z();
|
||||
src_vertices(0, 5) = max.x(); src_vertices(1, 5) = min.y(); src_vertices(2, 5) = max.z();
|
||||
src_vertices(0, 6) = max.x(); src_vertices(1, 6) = max.y(); src_vertices(2, 6) = max.z();
|
||||
src_vertices(0, 7) = min.x(); src_vertices(1, 7) = max.y(); src_vertices(2, 7) = max.z();
|
||||
|
||||
Vertices dst_vertices = matrix * src_vertices.colwise().homogeneous();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -21,6 +21,8 @@ if (TARGET OpenVDB::openvdb)
|
||||
set(OpenVDBUtils_SOURCES OpenVDBUtils.cpp OpenVDBUtils.hpp)
|
||||
endif()
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared libs" OFF)
|
||||
|
||||
set(lisbslic3r_sources
|
||||
ArcFitter.cpp
|
||||
ArcFitter.hpp
|
||||
@@ -52,8 +54,6 @@ set(lisbslic3r_sources
|
||||
clipper.hpp
|
||||
ClipperUtils.cpp
|
||||
ClipperUtils.hpp
|
||||
Clipper2Utils.cpp
|
||||
Clipper2Utils.hpp
|
||||
ClipperZUtils.hpp
|
||||
Color.cpp
|
||||
Color.hpp
|
||||
@@ -573,7 +573,6 @@ target_link_libraries(libslic3r
|
||||
PNG::PNG
|
||||
ZLIB::ZLIB
|
||||
${OCCT_LIBS}
|
||||
Clipper2
|
||||
mcut
|
||||
JPEG::JPEG
|
||||
qoi
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
#include "Clipper2Utils.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
//BBS: FIXME
|
||||
Slic3r::Polylines Paths64_to_polylines(const Clipper2Lib::Paths64& in)
|
||||
{
|
||||
Slic3r::Polylines out;
|
||||
out.reserve(in.size());
|
||||
for (const Clipper2Lib::Path64& path64 : in) {
|
||||
Slic3r::Points points;
|
||||
points.reserve(path64.size());
|
||||
for (const Clipper2Lib::Point64& point64 : path64)
|
||||
points.emplace_back(std::move(Slic3r::Point(point64.x, point64.y)));
|
||||
out.emplace_back(std::move(Slic3r::Polyline(points)));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
//BBS: FIXME
|
||||
template <typename T>
|
||||
Clipper2Lib::Paths64 Slic3rPoints_to_Paths64(const std::vector<T>& in)
|
||||
{
|
||||
Clipper2Lib::Paths64 out;
|
||||
out.reserve(in.size());
|
||||
for (const T& item: in) {
|
||||
Clipper2Lib::Path64 path;
|
||||
path.reserve(item.size());
|
||||
for (const Slic3r::Point& point : item.points)
|
||||
path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y())));
|
||||
out.emplace_back(std::move(path));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Polylines _clipper2_pl_open(Clipper2Lib::ClipType clipType, const Slic3r::Polylines& subject, const Slic3r::Polygons& clip)
|
||||
{
|
||||
Clipper2Lib::Clipper64 c;
|
||||
c.AddOpenSubject(Slic3rPoints_to_Paths64(subject));
|
||||
c.AddClip(Slic3rPoints_to_Paths64(clip));
|
||||
|
||||
Clipper2Lib::ClipType ct = clipType;
|
||||
Clipper2Lib::FillRule fr = Clipper2Lib::FillRule::NonZero;
|
||||
Clipper2Lib::Paths64 solution, solution_open;
|
||||
c.Execute(ct, fr, solution, solution_open);
|
||||
|
||||
Slic3r::Polylines out;
|
||||
out.reserve(solution.size() + solution_open.size());
|
||||
polylines_append(out, std::move(Paths64_to_polylines(solution)));
|
||||
polylines_append(out, std::move(Paths64_to_polylines(solution_open)));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip)
|
||||
{ return _clipper2_pl_open(Clipper2Lib::ClipType::Intersection, subject, clip); }
|
||||
Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip)
|
||||
{ return _clipper2_pl_open(Clipper2Lib::ClipType::Difference, subject, clip); }
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#ifndef slic3r_Clipper2Utils_hpp_
|
||||
#define slic3r_Clipper2Utils_hpp_
|
||||
|
||||
#include "libslic3r.h"
|
||||
#include "clipper2/clipper.h"
|
||||
#include "Polygon.hpp"
|
||||
#include "Polyline.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip);
|
||||
Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -61,8 +61,10 @@ Points SinglePathProvider::s_end;
|
||||
// Clip source polygon to be used as a clipping polygon with a bouding box around the source (to be clipped) polygon.
|
||||
// Useful as an optimization for expensive ClipperLib operations, for example when clipping source polygons one by one
|
||||
// with a set of polygons covering the whole layer below.
|
||||
template<typename PointType> inline void clip_clipper_polygon_with_subject_bbox_templ(const std::vector<PointType> &src, const BoundingBox &bbox, std::vector<PointType> &out, const bool get_entire_polygons=false)
|
||||
template<typename PointsType> inline void clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox, PointsType &out, const bool get_entire_polygons=false)
|
||||
{
|
||||
using PointType = typename PointsType::value_type;
|
||||
|
||||
out.clear();
|
||||
const size_t cnt = src.size();
|
||||
if (cnt < 3) return;
|
||||
@@ -112,9 +114,9 @@ template<typename PointType> inline void clip_clipper_polygon_with_subject_bbox_
|
||||
void clip_clipper_polygon_with_subject_bbox(const Points &src, const BoundingBox &bbox, Points &out, const bool get_entire_polygons) { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out, get_entire_polygons); }
|
||||
void clip_clipper_polygon_with_subject_bbox(const ZPoints &src, const BoundingBox &bbox, ZPoints &out) { clip_clipper_polygon_with_subject_bbox_templ(src, bbox, out); }
|
||||
|
||||
template<typename PointType> [[nodiscard]] std::vector<PointType> clip_clipper_polygon_with_subject_bbox_templ(const std::vector<PointType> &src, const BoundingBox &bbox)
|
||||
template<typename PointsType> [[nodiscard]] PointsType clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox)
|
||||
{
|
||||
std::vector<PointType> out;
|
||||
PointsType out;
|
||||
clip_clipper_polygon_with_subject_bbox(src, bbox, out);
|
||||
return out;
|
||||
}
|
||||
@@ -1001,31 +1003,26 @@ Polygons union_pt_chained_outside_in(const Polygons &subject)
|
||||
return retval;
|
||||
}
|
||||
|
||||
Polygons simplify_polygons(const Polygons &subject, bool preserve_collinear)
|
||||
Polygons simplify_polygons(const Polygons &subject)
|
||||
{
|
||||
ClipperLib::Paths output;
|
||||
if (preserve_collinear) {
|
||||
ClipperLib::Clipper c;
|
||||
c.PreserveCollinear(true);
|
||||
c.StrictlySimple(true);
|
||||
c.AddPaths(ClipperUtils::PolygonsProvider(subject), ClipperLib::ptSubject, true);
|
||||
c.Execute(ClipperLib::ctUnion, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
} else {
|
||||
output = ClipperLib::SimplifyPolygons(ClipperUtils::PolygonsProvider(subject), ClipperLib::pftNonZero);
|
||||
}
|
||||
|
||||
ClipperLib::Clipper c;
|
||||
// c.PreserveCollinear(true);
|
||||
//FIXME StrictlySimple is very expensive! Is it needed?
|
||||
c.StrictlySimple(true);
|
||||
c.AddPaths(ClipperUtils::PolygonsProvider(subject), ClipperLib::ptSubject, true);
|
||||
c.Execute(ClipperLib::ctUnion, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
|
||||
// convert into Slic3r polygons
|
||||
return to_polygons(std::move(output));
|
||||
}
|
||||
|
||||
ExPolygons simplify_polygons_ex(const Polygons &subject, bool preserve_collinear)
|
||||
ExPolygons simplify_polygons_ex(const Polygons &subject)
|
||||
{
|
||||
if (! preserve_collinear)
|
||||
return union_ex(simplify_polygons(subject, false));
|
||||
|
||||
ClipperLib::PolyTree polytree;
|
||||
ClipperLib::PolyTree polytree;
|
||||
ClipperLib::Clipper c;
|
||||
c.PreserveCollinear(true);
|
||||
// c.PreserveCollinear(true);
|
||||
//FIXME StrictlySimple is very expensive! Is it needed?
|
||||
c.StrictlySimple(true);
|
||||
c.AddPaths(ClipperUtils::PolygonsProvider(subject), ClipperLib::ptSubject, true);
|
||||
c.Execute(ClipperLib::ctUnion, polytree, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
|
||||
@@ -124,21 +124,21 @@ namespace ClipperUtils {
|
||||
const std::vector<PathType> &m_paths;
|
||||
};
|
||||
|
||||
template<typename MultiPointType>
|
||||
template<typename MultiPointsType>
|
||||
class MultiPointsProvider {
|
||||
public:
|
||||
MultiPointsProvider(const std::vector<MultiPointType> &multipoints) : m_multipoints(multipoints) {}
|
||||
MultiPointsProvider(const MultiPointsType &multipoints) : m_multipoints(multipoints) {}
|
||||
|
||||
struct iterator : public PathsProviderIteratorBase {
|
||||
public:
|
||||
explicit iterator(typename std::vector<MultiPointType>::const_iterator it) : m_it(it) {}
|
||||
explicit iterator(typename MultiPointsType::const_iterator it) : m_it(it) {}
|
||||
const Points& operator*() const { return m_it->points; }
|
||||
bool operator==(const iterator &rhs) const { return m_it == rhs.m_it; }
|
||||
bool operator!=(const iterator &rhs) const { return !(*this == rhs); }
|
||||
const Points& operator++(int) { return (m_it ++)->points; }
|
||||
iterator& operator++() { ++ m_it; return *this; }
|
||||
private:
|
||||
typename std::vector<MultiPointType>::const_iterator m_it;
|
||||
typename MultiPointsType::const_iterator m_it;
|
||||
};
|
||||
|
||||
iterator cbegin() const { return iterator(m_multipoints.begin()); }
|
||||
@@ -148,11 +148,11 @@ namespace ClipperUtils {
|
||||
size_t size() const { return m_multipoints.size(); }
|
||||
|
||||
private:
|
||||
const std::vector<MultiPointType> &m_multipoints;
|
||||
const MultiPointsType &m_multipoints;
|
||||
};
|
||||
|
||||
using PolygonsProvider = MultiPointsProvider<Polygon>;
|
||||
using PolylinesProvider = MultiPointsProvider<Polyline>;
|
||||
using PolygonsProvider = MultiPointsProvider<Polygons>;
|
||||
using PolylinesProvider = MultiPointsProvider<Polylines>;
|
||||
|
||||
struct ExPolygonProvider {
|
||||
ExPolygonProvider(const ExPolygon &expoly) : m_expoly(expoly) {}
|
||||
@@ -650,8 +650,8 @@ void traverse_pt(const ClipperLib::PolyNodes &nodes, ExOrJustPolygons *retval)
|
||||
|
||||
|
||||
/* OTHER */
|
||||
Slic3r::Polygons simplify_polygons(const Slic3r::Polygons &subject, bool preserve_collinear = false);
|
||||
Slic3r::ExPolygons simplify_polygons_ex(const Slic3r::Polygons &subject, bool preserve_collinear = false);
|
||||
Slic3r::Polygons simplify_polygons(const Slic3r::Polygons &subject);
|
||||
Slic3r::ExPolygons simplify_polygons_ex(const Slic3r::Polygons &subject);
|
||||
|
||||
Polygons top_level_islands(const Slic3r::Polygons &polygons);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
Contour() = default;
|
||||
Contour(const Slic3r::Point *begin, const Slic3r::Point *end, bool open) : m_begin(begin), m_end(end), m_open(open) {}
|
||||
Contour(const Slic3r::Point *data, size_t size, bool open) : Contour(data, data + size, open) {}
|
||||
Contour(const std::vector<Slic3r::Point> &pts, bool open) : Contour(pts.data(), pts.size(), open) {}
|
||||
Contour(const Points &pts, bool open) : Contour(pts.data(), pts.size(), open) {}
|
||||
|
||||
const Slic3r::Point *begin() const { return m_begin; }
|
||||
const Slic3r::Point *end() const { return m_end; }
|
||||
|
||||
@@ -440,7 +440,7 @@ bool has_duplicate_points(const ExPolygon &expoly)
|
||||
size_t cnt = expoly.contour.points.size();
|
||||
for (const Polygon &hole : expoly.holes)
|
||||
cnt += hole.points.size();
|
||||
std::vector<Point> allpts;
|
||||
Points allpts;
|
||||
allpts.reserve(cnt);
|
||||
allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end());
|
||||
for (const Polygon &hole : expoly.holes)
|
||||
@@ -461,14 +461,8 @@ bool has_duplicate_points(const ExPolygons &expolys)
|
||||
{
|
||||
#if 1
|
||||
// Check globally.
|
||||
size_t cnt = 0;
|
||||
for (const ExPolygon &expoly : expolys) {
|
||||
cnt += expoly.contour.points.size();
|
||||
for (const Polygon &hole : expoly.holes)
|
||||
cnt += hole.points.size();
|
||||
}
|
||||
std::vector<Point> allpts;
|
||||
allpts.reserve(cnt);
|
||||
Points allpts;
|
||||
allpts.reserve(count_points(expolys));
|
||||
for (const ExPolygon &expoly : expolys) {
|
||||
allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end());
|
||||
for (const Polygon &hole : expoly.holes)
|
||||
|
||||
@@ -6252,7 +6252,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp
|
||||
z_range.first = std::max(0.f, z_range.second - protect_z);
|
||||
std::vector<LayerPtrs> layers_of_objects;
|
||||
std::vector<BoundingBox> boundingBox_for_objects;
|
||||
std::vector<Points> objects_instances_shift;
|
||||
VecOfPoints objects_instances_shift;
|
||||
std::vector<size_t> idx_of_object_sorted = m_curr_print->layers_sorted_for_object(z_range.first, z_range.second, layers_of_objects, boundingBox_for_objects, objects_instances_shift);
|
||||
|
||||
std::vector<bool> is_layers_of_objects_sorted(layers_of_objects.size(), false);
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace ClipperLib {
|
||||
class PolyNode;
|
||||
using PolyNodes = std::vector<PolyNode*>;
|
||||
}
|
||||
|
||||
namespace Geometry {
|
||||
|
||||
// Generic result of an orientation predicate.
|
||||
|
||||
@@ -249,7 +249,7 @@ Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
|
||||
using QNode = astar::QNode<JPSTracer<Pixel, decltype(cell_query)>>;
|
||||
|
||||
std::unordered_map<size_t, QNode> astar_cache{};
|
||||
std::vector<Pixel> out_path;
|
||||
std::vector<Pixel, PointsAllocator<Pixel>> out_path;
|
||||
std::vector<decltype(tracer)::Node> out_nodes;
|
||||
|
||||
if (!astar::search_route(tracer, {start, {0, 0}}, std::back_inserter(out_nodes), astar_cache)) {
|
||||
@@ -288,7 +288,7 @@ Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
|
||||
svg.draw(scaled_point(start), "green", scale_(0.4));
|
||||
#endif
|
||||
|
||||
std::vector<Pixel> tmp_path;
|
||||
std::vector<Pixel, PointsAllocator<Pixel>> tmp_path;
|
||||
tmp_path.reserve(out_path.size());
|
||||
// Some path found, reverse and remove points that do not change direction
|
||||
std::reverse(out_path.begin(), out_path.end());
|
||||
|
||||
@@ -161,9 +161,9 @@ bool MultiPoint::intersections(const Line &line, Points *intersections) const
|
||||
return intersections->size() > intersections_size;
|
||||
}
|
||||
|
||||
std::vector<Point> MultiPoint::_douglas_peucker(const std::vector<Point>& pts, const double tolerance)
|
||||
Points MultiPoint::_douglas_peucker(const Points &pts, const double tolerance)
|
||||
{
|
||||
std::vector<Point> result_pts;
|
||||
Points result_pts;
|
||||
double tolerance_sq = tolerance * tolerance;
|
||||
if (! pts.empty()) {
|
||||
const Point *anchor = &pts.front();
|
||||
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
};
|
||||
|
||||
extern BoundingBox get_extents(const MultiPoint &mp);
|
||||
extern BoundingBox get_extents_rotated(const std::vector<Point> &points, double angle);
|
||||
extern BoundingBox get_extents_rotated(const Points &points, double angle);
|
||||
extern BoundingBox get_extents_rotated(const MultiPoint &mp, double angle);
|
||||
|
||||
inline double length(const Points &pts) {
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "ShortestPath.hpp"
|
||||
#include "VariableWidth.hpp"
|
||||
#include "CurveAnalyzer.hpp"
|
||||
#include "Clipper2Utils.hpp"
|
||||
#include "Arachne/WallToolPaths.hpp"
|
||||
#include "Geometry/ConvexHull.hpp"
|
||||
#include "ExPolygonCollection.hpp"
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <oneapi/tbb/scalable_allocator.h>
|
||||
|
||||
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include "LocalesUtils.hpp"
|
||||
|
||||
@@ -48,7 +52,9 @@ using Vec2d = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>;
|
||||
using Vec3d = Eigen::Matrix<double, 3, 1, Eigen::DontAlign>;
|
||||
using Vec4d = Eigen::Matrix<double, 4, 1, Eigen::DontAlign>;
|
||||
|
||||
using Points = std::vector<Point>;
|
||||
template<typename BaseType>
|
||||
using PointsAllocator = tbb::scalable_allocator<BaseType>;
|
||||
using Points = std::vector<Point, PointsAllocator<Point>>;
|
||||
using PointPtrs = std::vector<Point*>;
|
||||
using PointConstPtrs = std::vector<const Point*>;
|
||||
using Points3 = std::vector<Vec3crd>;
|
||||
@@ -56,7 +62,7 @@ using Pointfs = std::vector<Vec2d>;
|
||||
using Vec2ds = std::vector<Vec2d>;
|
||||
using Pointf3s = std::vector<Vec3d>;
|
||||
|
||||
using VecOfPoints = std::vector<Points>;
|
||||
using VecOfPoints = std::vector<Points, PointsAllocator<Points>>;
|
||||
|
||||
using Matrix2f = Eigen::Matrix<float, 2, 2, Eigen::DontAlign>;
|
||||
using Matrix2d = Eigen::Matrix<double, 2, 2, Eigen::DontAlign>;
|
||||
|
||||
@@ -437,11 +437,8 @@ bool has_duplicate_points(const Polygons &polys)
|
||||
{
|
||||
#if 1
|
||||
// Check globally.
|
||||
size_t cnt = 0;
|
||||
for (const Polygon &poly : polys)
|
||||
cnt += poly.points.size();
|
||||
std::vector<Point> allpts;
|
||||
allpts.reserve(cnt);
|
||||
Points allpts;
|
||||
allpts.reserve(count_points(polys));
|
||||
for (const Polygon &poly : polys)
|
||||
allpts.insert(allpts.end(), poly.points.begin(), poly.points.end());
|
||||
return has_duplicate_points(std::move(allpts));
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
namespace Slic3r {
|
||||
|
||||
class Polygon;
|
||||
using Polygons = std::vector<Polygon>;
|
||||
using PolygonPtrs = std::vector<Polygon*>;
|
||||
using ConstPolygonPtrs = std::vector<const Polygon*>;
|
||||
using Polygons = std::vector<Polygon, PointsAllocator<Polygon>>;
|
||||
using PolygonPtrs = std::vector<Polygon*, PointsAllocator<Polygon*>>;
|
||||
using ConstPolygonPtrs = std::vector<const Polygon*, PointsAllocator<const Polygon*>>;
|
||||
|
||||
// Returns true if inside. Returns border_result if on boundary.
|
||||
bool contains(const Polygon& polygon, const Point& p, bool border_result = true);
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace EdgeGrid {
|
||||
|
||||
struct TrimmedLoop
|
||||
{
|
||||
std::vector<Point> points;
|
||||
Points points;
|
||||
// Number of points per segment. Empty if the loop is
|
||||
std::vector<unsigned int> segments;
|
||||
|
||||
|
||||
@@ -529,7 +529,7 @@ bool Print::has_brim() const
|
||||
}
|
||||
|
||||
//BBS
|
||||
std::vector<size_t> Print::layers_sorted_for_object(float start, float end, std::vector<LayerPtrs> &layers_of_objects, std::vector<BoundingBox> &boundingBox_for_objects, std::vector<Points> &objects_instances_shift)
|
||||
std::vector<size_t> Print::layers_sorted_for_object(float start, float end, std::vector<LayerPtrs> &layers_of_objects, std::vector<BoundingBox> &boundingBox_for_objects, VecOfPoints &objects_instances_shift)
|
||||
{
|
||||
std::vector<size_t> idx_of_object_sorted;
|
||||
size_t idx = 0;
|
||||
@@ -2450,9 +2450,9 @@ Polygons Print::first_layer_islands() const
|
||||
return islands;
|
||||
}
|
||||
|
||||
std::vector<Point> Print::first_layer_wipe_tower_corners(bool check_wipe_tower_existance) const
|
||||
Points Print::first_layer_wipe_tower_corners(bool check_wipe_tower_existance) const
|
||||
{
|
||||
std::vector<Point> corners;
|
||||
Points corners;
|
||||
if (check_wipe_tower_existance && (!has_wipe_tower() || m_wipe_tower_data.tool_changes.empty()))
|
||||
return corners;
|
||||
{
|
||||
|
||||
@@ -433,7 +433,7 @@ public:
|
||||
//BBS
|
||||
BoundingBox get_first_layer_bbox(float& area, float& layer_height, std::string& name);
|
||||
void get_certain_layers(float start, float end, std::vector<LayerPtrs> &out, std::vector<BoundingBox> &boundingbox_objects);
|
||||
std::vector<Point> get_instances_shift_without_plate_offset();
|
||||
Points get_instances_shift_without_plate_offset();
|
||||
PrintObject* get_shared_object() const { return m_shared_object; }
|
||||
void set_shared_object(PrintObject *object);
|
||||
void clear_shared_object();
|
||||
@@ -900,7 +900,7 @@ public:
|
||||
// For Perl bindings.
|
||||
PrintObjectPtrs& objects_mutable() { return m_objects; }
|
||||
PrintRegionPtrs& print_regions_mutable() { return m_print_regions; }
|
||||
std::vector<size_t> layers_sorted_for_object(float start, float end, std::vector<LayerPtrs> &layers_of_objects, std::vector<BoundingBox> &boundingBox_for_objects, std::vector<Points>& objects_instances_shift);
|
||||
std::vector<size_t> layers_sorted_for_object(float start, float end, std::vector<LayerPtrs> &layers_of_objects, std::vector<BoundingBox> &boundingBox_for_objects, VecOfPoints& objects_instances_shift);
|
||||
const ExtrusionEntityCollection& skirt() const { return m_skirt; }
|
||||
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
|
||||
// It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
|
||||
@@ -954,7 +954,7 @@ public:
|
||||
ConflictResultOpt get_conflict_result() const { return m_conflict_result; }
|
||||
|
||||
// Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
|
||||
std::vector<Point> first_layer_wipe_tower_corners(bool check_wipe_tower_existance=true) const;
|
||||
Points first_layer_wipe_tower_corners(bool check_wipe_tower_existance=true) const;
|
||||
|
||||
//SoftFever
|
||||
bool &is_BBL_printer() { return m_isBBLPrinter; }
|
||||
|
||||
@@ -3358,9 +3358,9 @@ void PrintObject::get_certain_layers(float start, float end, std::vector<LayerPt
|
||||
out.emplace_back(std::move(out_temp));
|
||||
};
|
||||
|
||||
std::vector<Point> PrintObject::get_instances_shift_without_plate_offset()
|
||||
Points PrintObject::get_instances_shift_without_plate_offset()
|
||||
{
|
||||
std::vector<Point> out;
|
||||
Points out;
|
||||
out.reserve(m_instances.size());
|
||||
for (const auto& instance : m_instances)
|
||||
out.push_back(instance.shift_without_plate_offset());
|
||||
|
||||
@@ -43,7 +43,8 @@ Point ConcaveHull::centroid(const Points &pp)
|
||||
Points ConcaveHull::calculate_centroids() const
|
||||
{
|
||||
// We get the centroids of all the islands in the 2D slice
|
||||
Points centroids = reserve_vector<Point>(m_polys.size());
|
||||
Points centroids;
|
||||
centroids.reserve(m_polys.size());
|
||||
std::transform(m_polys.begin(), m_polys.end(),
|
||||
std::back_inserter(centroids),
|
||||
[](const Polygon &poly) { return centroid(poly); });
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include <libslic3r/Point.hpp>
|
||||
|
||||
struct indexed_triangle_set;
|
||||
|
||||
namespace Slic3r {
|
||||
@@ -13,7 +15,7 @@ namespace Slic3r {
|
||||
class ExPolygon;
|
||||
class Polygon;
|
||||
using ExPolygons = std::vector<ExPolygon>;
|
||||
using Polygons = std::vector<Polygon>;
|
||||
using Polygons = std::vector<Polygon, PointsAllocator<Polygon>>;
|
||||
|
||||
namespace sla {
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include <memory>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
#include <libslic3r/Polygon.hpp>
|
||||
#include <libslic3r/ExPolygon.hpp>
|
||||
|
||||
#include <libslic3r/SLA/Pad.hpp>
|
||||
#include <libslic3r/SLA/IndexedMesh.hpp>
|
||||
#include <libslic3r/SLA/SupportPoint.hpp>
|
||||
@@ -16,11 +19,6 @@ class TriangleMesh;
|
||||
class Model;
|
||||
class ModelInstance;
|
||||
class ModelObject;
|
||||
class Polygon;
|
||||
class ExPolygon;
|
||||
|
||||
using Polygons = std::vector<Polygon>;
|
||||
using ExPolygons = std::vector<ExPolygon>;
|
||||
|
||||
namespace sla {
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace ClipperLib { class PolyNode; }
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace ClipperLib {
|
||||
class PolyNode;
|
||||
using PolyNodes = std::vector<PolyNode*, PointsAllocator<PolyNode*>>;
|
||||
}
|
||||
|
||||
std::vector<size_t> chain_points(const Points &points, Point *start_near = nullptr);
|
||||
std::vector<size_t> chain_expolygons(const ExPolygons &input_exploy);
|
||||
|
||||
@@ -39,7 +42,7 @@ template<typename T> inline void reorder_by_shortest_traverse(std::vector<T> &po
|
||||
for (size_t i:order) polylines_out.emplace_back(std::move(Temp[i]));
|
||||
}
|
||||
|
||||
std::vector<ClipperLib::PolyNode*> chain_clipper_polynodes(const Points &points, const std::vector<ClipperLib::PolyNode*> &items);
|
||||
ClipperLib::PolyNodes chain_clipper_polynodes(const Points &points, const ClipperLib::PolyNodes &items);
|
||||
|
||||
// Chain instances of print objects by an approximate shortest path.
|
||||
// Returns pairs of PrintObject idx and instance of that PrintObject.
|
||||
|
||||
@@ -951,7 +951,7 @@ public:
|
||||
}
|
||||
::fclose(file);
|
||||
|
||||
m_support_polygons_deserialized = simplify_polygons(m_support_polygons_deserialized, false);
|
||||
m_support_polygons_deserialized = simplify_polygons(m_support_polygons_deserialized);
|
||||
//m_support_polygons_deserialized = to_polygons(union_ex(m_support_polygons_deserialized, false));
|
||||
|
||||
// Create an EdgeGrid, initialize it with projection, initialize signed distance field.
|
||||
|
||||
@@ -137,8 +137,8 @@ enum Axis {
|
||||
NUM_AXES_WITH_UNKNOWN,
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline void append(std::vector<T>& dest, const std::vector<T>& src)
|
||||
template <typename T, typename Alloc, typename Alloc2>
|
||||
inline void append(std::vector<T, Alloc> &dest, const std::vector<T, Alloc2> &src)
|
||||
{
|
||||
if (dest.empty())
|
||||
dest = src;
|
||||
@@ -146,8 +146,8 @@ inline void append(std::vector<T>& dest, const std::vector<T>& src)
|
||||
dest.insert(dest.end(), src.begin(), src.end());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void append(std::vector<T>& dest, std::vector<T>&& src)
|
||||
template <typename T, typename Alloc>
|
||||
inline void append(std::vector<T, Alloc> &dest, std::vector<T, Alloc> &&src)
|
||||
{
|
||||
if (dest.empty())
|
||||
dest = std::move(src);
|
||||
|
||||
Reference in New Issue
Block a user