mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-24 15:13:58 -06:00
Merge branch 'tm_vb_clipper_eigen'
This commit is contained in:
commit
9f4e9da5c6
50 changed files with 1209 additions and 1291 deletions
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "BoundingBox.hpp"
|
||||
|
||||
#include <libnest2d/backends/clipper/geometries.hpp>
|
||||
#include <libnest2d/backends/libslic3r/geometries.hpp>
|
||||
#include <libnest2d/optimizers/nlopt/subplex.hpp>
|
||||
#include <libnest2d/placers/nfpplacer.hpp>
|
||||
#include <libnest2d/selections/firstfit.hpp>
|
||||
|
@ -54,23 +54,22 @@ namespace Slic3r {
|
|||
|
||||
template<class Tout = double, class = FloatingOnly<Tout>, int...EigenArgs>
|
||||
inline constexpr Eigen::Matrix<Tout, 2, EigenArgs...> unscaled(
|
||||
const ClipperLib::IntPoint &v) noexcept
|
||||
const Slic3r::ClipperLib::IntPoint &v) noexcept
|
||||
{
|
||||
return Eigen::Matrix<Tout, 2, EigenArgs...>{unscaled<Tout>(v.X),
|
||||
unscaled<Tout>(v.Y)};
|
||||
return Eigen::Matrix<Tout, 2, EigenArgs...>{unscaled<Tout>(v.x()),
|
||||
unscaled<Tout>(v.y())};
|
||||
}
|
||||
|
||||
namespace arrangement {
|
||||
|
||||
using namespace libnest2d;
|
||||
namespace clppr = ClipperLib;
|
||||
|
||||
// Get the libnest2d types for clipper backend
|
||||
using Item = _Item<clppr::Polygon>;
|
||||
using Box = _Box<clppr::IntPoint>;
|
||||
using Circle = _Circle<clppr::IntPoint>;
|
||||
using Segment = _Segment<clppr::IntPoint>;
|
||||
using MultiPolygon = TMultiShape<clppr::Polygon>;
|
||||
using Item = _Item<ExPolygon>;
|
||||
using Box = _Box<Point>;
|
||||
using Circle = _Circle<Point>;
|
||||
using Segment = _Segment<Point>;
|
||||
using MultiPolygon = ExPolygons;
|
||||
|
||||
// Summon the spatial indexing facilities from boost
|
||||
namespace bgi = boost::geometry::index;
|
||||
|
@ -127,8 +126,8 @@ template<class TBin>
|
|||
class AutoArranger {
|
||||
public:
|
||||
// Useful type shortcuts...
|
||||
using Placer = typename placers::_NofitPolyPlacer<clppr::Polygon, TBin>;
|
||||
using Selector = selections::_FirstFitSelection<clppr::Polygon>;
|
||||
using Placer = typename placers::_NofitPolyPlacer<ExPolygon, TBin>;
|
||||
using Selector = selections::_FirstFitSelection<ExPolygon>;
|
||||
using Packer = _Nester<Placer, Selector>;
|
||||
using PConfig = typename Packer::PlacementConfig;
|
||||
using Distance = TCoord<PointImpl>;
|
||||
|
@ -168,7 +167,7 @@ protected:
|
|||
// as it possibly can be but at the same time, it has to provide
|
||||
// reasonable results.
|
||||
std::tuple<double /*score*/, Box /*farthest point from bin center*/>
|
||||
objfunc(const Item &item, const clppr::IntPoint &bincenter)
|
||||
objfunc(const Item &item, const Point &bincenter)
|
||||
{
|
||||
const double bin_area = m_bin_area;
|
||||
const SpatIndex& spatindex = m_rtree;
|
||||
|
@ -220,12 +219,12 @@ protected:
|
|||
|
||||
switch (compute_case) {
|
||||
case BIG_ITEM: {
|
||||
const clppr::IntPoint& minc = ibb.minCorner(); // bottom left corner
|
||||
const clppr::IntPoint& maxc = ibb.maxCorner(); // top right corner
|
||||
const Point& minc = ibb.minCorner(); // bottom left corner
|
||||
const Point& maxc = ibb.maxCorner(); // top right corner
|
||||
|
||||
// top left and bottom right corners
|
||||
clppr::IntPoint top_left{getX(minc), getY(maxc)};
|
||||
clppr::IntPoint bottom_right{getX(maxc), getY(minc)};
|
||||
Point top_left{getX(minc), getY(maxc)};
|
||||
Point bottom_right{getX(maxc), getY(minc)};
|
||||
|
||||
// Now the distance of the gravity center will be calculated to the
|
||||
// five anchor points and the smallest will be chosen.
|
||||
|
@ -452,7 +451,7 @@ template<> std::function<double(const Item&)> AutoArranger<Circle>::get_objfn()
|
|||
// Specialization for a generalized polygon.
|
||||
// Warning: this is unfinished business. It may or may not work.
|
||||
template<>
|
||||
std::function<double(const Item &)> AutoArranger<clppr::Polygon>::get_objfn()
|
||||
std::function<double(const Item &)> AutoArranger<ExPolygon>::get_objfn()
|
||||
{
|
||||
auto bincenter = sl::boundingBox(m_bin).center();
|
||||
return [this, bincenter](const Item &item) {
|
||||
|
@ -521,7 +520,7 @@ void _arrange(
|
|||
|
||||
inline Box to_nestbin(const BoundingBox &bb) { return Box{{bb.min(X), bb.min(Y)}, {bb.max(X), bb.max(Y)}};}
|
||||
inline Circle to_nestbin(const CircleBed &c) { return Circle({c.center()(0), c.center()(1)}, c.radius()); }
|
||||
inline clppr::Polygon to_nestbin(const Polygon &p) { return sl::create<clppr::Polygon>(Slic3rMultiPoint_to_ClipperPath(p)); }
|
||||
inline ExPolygon to_nestbin(const Polygon &p) { return ExPolygon{p}; }
|
||||
inline Box to_nestbin(const InfiniteBed &bed) { return Box::infinite({bed.center.x(), bed.center.y()}); }
|
||||
|
||||
inline coord_t width(const BoundingBox& box) { return box.max.x() - box.min.x(); }
|
||||
|
@ -568,19 +567,12 @@ static void process_arrangeable(const ArrangePolygon &arrpoly,
|
|||
const Vec2crd &offs = arrpoly.translation;
|
||||
double rotation = arrpoly.rotation;
|
||||
|
||||
if (p.is_counter_clockwise()) p.reverse();
|
||||
|
||||
clppr::Polygon clpath(Slic3rMultiPoint_to_ClipperPath(p));
|
||||
|
||||
// This fixes:
|
||||
// https://github.com/prusa3d/PrusaSlicer/issues/2209
|
||||
if (clpath.Contour.size() < 3)
|
||||
if (p.points.size() < 3)
|
||||
return;
|
||||
|
||||
auto firstp = clpath.Contour.front();
|
||||
clpath.Contour.emplace_back(firstp);
|
||||
|
||||
outp.emplace_back(std::move(clpath));
|
||||
outp.emplace_back(std::move(p));
|
||||
outp.back().rotation(rotation);
|
||||
outp.back().translation({offs.x(), offs.y()});
|
||||
outp.back().binId(arrpoly.bed_idx);
|
||||
|
@ -624,7 +616,7 @@ void arrange(ArrangePolygons & arrangables,
|
|||
const BedT & bed,
|
||||
const ArrangeParams & params)
|
||||
{
|
||||
namespace clppr = ClipperLib;
|
||||
namespace clppr = Slic3r::ClipperLib;
|
||||
|
||||
std::vector<Item> items, fixeditems;
|
||||
items.reserve(arrangables.size());
|
||||
|
@ -643,8 +635,8 @@ void arrange(ArrangePolygons & arrangables,
|
|||
_arrange(items, fixeditems, to_nestbin(bed), params, pri, cfn);
|
||||
|
||||
for(size_t i = 0; i < items.size(); ++i) {
|
||||
clppr::IntPoint tr = items[i].translation();
|
||||
arrangables[i].translation = {coord_t(tr.X), coord_t(tr.Y)};
|
||||
Point tr = items[i].translation();
|
||||
arrangables[i].translation = {coord_t(tr.x()), coord_t(tr.y())};
|
||||
arrangables[i].rotation = items[i].rotation();
|
||||
arrangables[i].bed_idx = items[i].binId();
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print)
|
|||
// Assign the maximum Z from four points. This values is valid index of the island
|
||||
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, const ClipperLib_Z::IntPoint &e2bot,
|
||||
const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) {
|
||||
pt.Z = std::max(std::max(e1bot.Z, e1top.Z), std::max(e2bot.Z, e2top.Z));
|
||||
pt.z() = std::max(std::max(e1bot.z(), e1top.z()), std::max(e2bot.z(), e2top.z()));
|
||||
});
|
||||
// Add islands
|
||||
clipper.AddPaths(islands_clip, ClipperLib_Z::ptSubject, true);
|
||||
|
@ -90,9 +90,9 @@ static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print)
|
|||
ConstPrintObjectPtrs top_level_objects_with_brim;
|
||||
for (int i = 0; i < islands_polytree.ChildCount(); ++i) {
|
||||
for (const ClipperLib_Z::IntPoint &point : islands_polytree.Childs[i]->Contour) {
|
||||
if (point.Z != 0 && processed_objects_idx.find(island_to_object[point.Z - 1]->id().id) == processed_objects_idx.end()) {
|
||||
top_level_objects_with_brim.emplace_back(island_to_object[point.Z - 1]);
|
||||
processed_objects_idx.insert(island_to_object[point.Z - 1]->id().id);
|
||||
if (point.z() != 0 && processed_objects_idx.find(island_to_object[point.z() - 1]->id().id) == processed_objects_idx.end()) {
|
||||
top_level_objects_with_brim.emplace_back(island_to_object[point.z() - 1]);
|
||||
processed_objects_idx.insert(island_to_object[point.z() - 1]->id().id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -456,7 +456,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
|
|||
clipper.ZFillFunction([](const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, const ClipperLib_Z::IntPoint& e2bot, const ClipperLib_Z::IntPoint& e2top, ClipperLib_Z::IntPoint& pt) {
|
||||
// Assign a valid input loop identifier. Such an identifier is strictly positive, the next line is safe even in case one side of a segment
|
||||
// hat the Z coordinate not set to the contour coordinate.
|
||||
pt.Z = std::max(std::max(e1bot.Z, e1top.Z), std::max(e2bot.Z, e2top.Z));
|
||||
pt.z() = std::max(std::max(e1bot.z(), e1top.z()), std::max(e2bot.z(), e2top.z()));
|
||||
});
|
||||
// add polygons
|
||||
clipper.AddPaths(input_clip, ClipperLib_Z::ptSubject, false);
|
||||
|
@ -474,8 +474,8 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
|
|||
for (const ClipperLib_Z::Path &path : loops_trimmed) {
|
||||
size_t input_idx = 0;
|
||||
for (const ClipperLib_Z::IntPoint &pt : path)
|
||||
if (pt.Z > 0) {
|
||||
input_idx = (size_t)pt.Z;
|
||||
if (pt.z() > 0) {
|
||||
input_idx = (size_t)pt.z();
|
||||
break;
|
||||
}
|
||||
assert(input_idx != 0);
|
||||
|
@ -492,14 +492,14 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
|
|||
size_t j = i + 1;
|
||||
for (; j < loops_trimmed_order.size() && loops_trimmed_order[i].second == loops_trimmed_order[j].second; ++ j) ;
|
||||
const ClipperLib_Z::Path &first_path = *loops_trimmed_order[i].first;
|
||||
if (i + 1 == j && first_path.size() > 3 && first_path.front().X == first_path.back().X && first_path.front().Y == first_path.back().Y) {
|
||||
if (i + 1 == j && first_path.size() > 3 && first_path.front().x() == first_path.back().x() && first_path.front().y() == first_path.back().y()) {
|
||||
auto *loop = new ExtrusionLoop();
|
||||
brim.entities.emplace_back(loop);
|
||||
loop->paths.emplace_back(erSkirt, float(flow.mm3_per_mm()), float(flow.width()), float(print.skirt_first_layer_height()));
|
||||
Points &points = loop->paths.front().polyline.points;
|
||||
points.reserve(first_path.size());
|
||||
for (const ClipperLib_Z::IntPoint &pt : first_path)
|
||||
points.emplace_back(coord_t(pt.X), coord_t(pt.Y));
|
||||
points.emplace_back(coord_t(pt.x()), coord_t(pt.y()));
|
||||
i = j;
|
||||
} else {
|
||||
//FIXME The path chaining here may not be optimal.
|
||||
|
@ -511,7 +511,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
|
|||
Points &points = static_cast<ExtrusionPath*>(this_loop_trimmed.entities.back())->polyline.points;
|
||||
points.reserve(path.size());
|
||||
for (const ClipperLib_Z::IntPoint &pt : path)
|
||||
points.emplace_back(coord_t(pt.X), coord_t(pt.Y));
|
||||
points.emplace_back(coord_t(pt.x()), coord_t(pt.y()));
|
||||
}
|
||||
chain_and_reorder_extrusion_entities(this_loop_trimmed.entities, &last_pt);
|
||||
brim.entities.reserve(brim.entities.size() + this_loop_trimmed.entities.size());
|
||||
|
|
|
@ -23,6 +23,8 @@ add_library(libslic3r STATIC
|
|||
BridgeDetector.hpp
|
||||
Brim.cpp
|
||||
Brim.hpp
|
||||
clipper.cpp
|
||||
clipper.hpp
|
||||
ClipperUtils.cpp
|
||||
ClipperUtils.hpp
|
||||
Config.cpp
|
||||
|
|
|
@ -131,7 +131,7 @@ Slic3r::Polygon ClipperPath_to_Slic3rPolygon(const ClipperLib::Path &input)
|
|||
{
|
||||
Polygon retval;
|
||||
for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
|
||||
retval.points.emplace_back(pit->X, pit->Y);
|
||||
retval.points.emplace_back(pit->x(), pit->y());
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ Slic3r::Polyline ClipperPath_to_Slic3rPolyline(const ClipperLib::Path &input)
|
|||
{
|
||||
Polyline retval;
|
||||
for (ClipperLib::Path::const_iterator pit = input.begin(); pit != input.end(); ++pit)
|
||||
retval.points.emplace_back(pit->X, pit->Y);
|
||||
retval.points.emplace_back(pit->x(), pit->y());
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -752,7 +752,7 @@ ClipperLib::PolyNodes order_nodes(const ClipperLib::PolyNodes &nodes)
|
|||
|
||||
for (const ClipperLib::PolyNode *node : nodes)
|
||||
ordering_points.emplace_back(
|
||||
Point(node->Contour.front().X, node->Contour.front().Y));
|
||||
Point(node->Contour.front().x(), node->Contour.front().y()));
|
||||
|
||||
// perform the ordering
|
||||
ClipperLib::PolyNodes ordered_nodes =
|
||||
|
@ -777,7 +777,7 @@ static void traverse_pt_outside_in(const ClipperLib::PolyNodes &nodes, Polygons
|
|||
Points ordering_points;
|
||||
ordering_points.reserve(nodes.size());
|
||||
for (const ClipperLib::PolyNode *node : nodes)
|
||||
ordering_points.emplace_back(node->Contour.front().X, node->Contour.front().Y);
|
||||
ordering_points.emplace_back(node->Contour.front().x(), node->Contour.front().y());
|
||||
|
||||
// Perform the ordering, push results recursively.
|
||||
//FIXME pass the last point to chain_clipper_polynodes?
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
#include "Surface.hpp"
|
||||
|
||||
// import these wherever we're included
|
||||
using ClipperLib::jtMiter;
|
||||
using ClipperLib::jtRound;
|
||||
using ClipperLib::jtSquare;
|
||||
using Slic3r::ClipperLib::jtMiter;
|
||||
using Slic3r::ClipperLib::jtRound;
|
||||
using Slic3r::ClipperLib::jtSquare;
|
||||
|
||||
#define CLIPPERUTILS_UNSAFE_OFFSET
|
||||
|
||||
|
|
|
@ -360,6 +360,8 @@ extern std::vector<BoundingBox> get_extents_vector(const ExPolygons &polygons);
|
|||
extern bool remove_sticks(ExPolygon &poly);
|
||||
extern void keep_largest_contour_only(ExPolygons &polygons);
|
||||
|
||||
inline double area(const ExPolygon &poly) { return poly.area(); }
|
||||
|
||||
inline double area(const ExPolygons &polys)
|
||||
{
|
||||
double s = 0.;
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
// Borrowed from C++20
|
||||
template<class T>
|
||||
using remove_cvref_t = std::remove_reference_t<std::remove_cv_t<T>>;
|
||||
|
||||
// Override for valid execution policies
|
||||
template<class EP> struct IsExecutionPolicy_ : public std::false_type {};
|
||||
|
||||
|
|
|
@ -595,7 +595,6 @@ static inline bool line_rounded_thick_segment_collision(
|
|||
// Very short line vector. Just test whether the center point is inside the offset line.
|
||||
Vec2d lpt = 0.5 * (line_a + line_b);
|
||||
if (segment_l > SCALED_EPSILON) {
|
||||
struct Linef { Vec2d a, b; };
|
||||
intersects = line_alg::distance_to_squared(Linef{ segment_a, segment_b }, lpt) < offset2;
|
||||
} else
|
||||
intersects = (0.5 * (segment_a + segment_b) - lpt).squaredNorm() < offset2;
|
||||
|
@ -1196,8 +1195,6 @@ static inline void mark_boundary_segments_overlapping_infill(
|
|||
// Spacing (width) of the infill lines.
|
||||
const double spacing)
|
||||
{
|
||||
struct Linef { Vec2d a; Vec2d b; };
|
||||
|
||||
for (ContourIntersectionPoint &cp : graph.map_infill_end_point_to_boundary) {
|
||||
const Points &contour = graph.boundary[cp.contour_idx];
|
||||
const std::vector<double> &contour_params = graph.boundary_params[cp.contour_idx];
|
||||
|
@ -2003,9 +2000,8 @@ static double evaluate_support_arch_cost(const Polyline &pl)
|
|||
|
||||
double dmax = 0;
|
||||
// Maximum distance in Y axis out of the (ymin, ymax) band and from the (front, back) line.
|
||||
struct Linef { Vec2d a, b; };
|
||||
Linef line { front.cast<double>(), back.cast<double>() };
|
||||
for (const Point pt : pl.points)
|
||||
for (const Point &pt : pl.points)
|
||||
dmax = std::max<double>(std::max(dmax, line_alg::distance_to(line, Vec2d(pt.cast<double>()))), std::max(pt.y() - ymax, ymin - pt.y()));
|
||||
return dmax;
|
||||
}
|
||||
|
|
|
@ -22,12 +22,14 @@
|
|||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
namespace ClipperLib {
|
||||
class PolyNode;
|
||||
using PolyNodes = std::vector<PolyNode*>;
|
||||
}
|
||||
namespace Slic3r {
|
||||
|
||||
namespace Slic3r { namespace Geometry {
|
||||
namespace ClipperLib {
|
||||
class PolyNode;
|
||||
using PolyNodes = std::vector<PolyNode*>;
|
||||
}
|
||||
|
||||
namespace Geometry {
|
||||
|
||||
// Generic result of an orientation predicate.
|
||||
enum Orientation
|
||||
|
@ -530,6 +532,6 @@ inline bool is_rotation_ninety_degrees(const Vec3d &rotation)
|
|||
return is_rotation_ninety_degrees(rotation.x()) && is_rotation_ninety_degrees(rotation.y()) && is_rotation_ninety_degrees(rotation.z());
|
||||
}
|
||||
|
||||
} }
|
||||
} } // namespace Slicer::Geometry
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "libslic3r.h"
|
||||
#include "Point.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class BoundingBox;
|
||||
|
@ -20,12 +22,28 @@ Linef3 transform(const Linef3& line, const Transform3d& t);
|
|||
|
||||
namespace line_alg {
|
||||
|
||||
template<class L, class En = void> struct Traits {
|
||||
static constexpr int Dim = L::Dim;
|
||||
using Scalar = typename L::Scalar;
|
||||
|
||||
static Vec<Dim, Scalar>& get_a(L &l) { return l.a; }
|
||||
static Vec<Dim, Scalar>& get_b(L &l) { return l.b; }
|
||||
static const Vec<Dim, Scalar>& get_a(const L &l) { return l.a; }
|
||||
static const Vec<Dim, Scalar>& get_b(const L &l) { return l.b; }
|
||||
};
|
||||
|
||||
template<class L> const constexpr int Dim = Traits<remove_cvref_t<L>>::Dim;
|
||||
template<class L> using Scalar = typename Traits<remove_cvref_t<L>>::Scalar;
|
||||
|
||||
template<class L> auto get_a(L &&l) { return Traits<remove_cvref_t<L>>::get_a(l); }
|
||||
template<class L> auto get_b(L &&l) { return Traits<remove_cvref_t<L>>::get_b(l); }
|
||||
|
||||
// Distance to the closest point of line.
|
||||
template<class L, class T, int N>
|
||||
double distance_to_squared(const L &line, const Vec<N, T> &point)
|
||||
template<class L>
|
||||
double distance_to_squared(const L &line, const Vec<Dim<L>, Scalar<L>> &point)
|
||||
{
|
||||
const Vec<N, double> v = (line.b - line.a).template cast<double>();
|
||||
const Vec<N, double> va = (point - line.a).template cast<double>();
|
||||
const Vec<Dim<L>, double> v = (get_b(line) - get_a(line)).template cast<double>();
|
||||
const Vec<Dim<L>, double> va = (point - get_a(line)).template cast<double>();
|
||||
const double l2 = v.squaredNorm(); // avoid a sqrt
|
||||
if (l2 == 0.0)
|
||||
// a == b case
|
||||
|
@ -35,12 +53,12 @@ double distance_to_squared(const L &line, const Vec<N, T> &point)
|
|||
// It falls where t = [(this-a) . (b-a)] / |b-a|^2
|
||||
const double t = va.dot(v) / l2;
|
||||
if (t < 0.0) return va.squaredNorm(); // beyond the 'a' end of the segment
|
||||
else if (t > 1.0) return (point - line.b).template cast<double>().squaredNorm(); // beyond the 'b' end of the segment
|
||||
else if (t > 1.0) return (point - get_b(line)).template cast<double>().squaredNorm(); // beyond the 'b' end of the segment
|
||||
return (t * v - va).squaredNorm();
|
||||
}
|
||||
|
||||
template<class L, class T, int N>
|
||||
double distance_to(const L &line, const Vec<N, T> &point)
|
||||
template<class L>
|
||||
double distance_to(const L &line, const Vec<Dim<L>, Scalar<L>> &point)
|
||||
{
|
||||
return std::sqrt(distance_to_squared(line, point));
|
||||
}
|
||||
|
@ -84,6 +102,9 @@ public:
|
|||
|
||||
Point a;
|
||||
Point b;
|
||||
|
||||
static const constexpr int Dim = 2;
|
||||
using Scalar = Point::Scalar;
|
||||
};
|
||||
|
||||
class ThickLine : public Line
|
||||
|
@ -107,6 +128,9 @@ public:
|
|||
|
||||
Vec3crd a;
|
||||
Vec3crd b;
|
||||
|
||||
static const constexpr int Dim = 3;
|
||||
using Scalar = Vec3crd::Scalar;
|
||||
};
|
||||
|
||||
class Linef
|
||||
|
@ -117,6 +141,9 @@ public:
|
|||
|
||||
Vec2d a;
|
||||
Vec2d b;
|
||||
|
||||
static const constexpr int Dim = 2;
|
||||
using Scalar = Vec2d::Scalar;
|
||||
};
|
||||
|
||||
class Linef3
|
||||
|
@ -133,6 +160,9 @@ public:
|
|||
|
||||
Vec3d a;
|
||||
Vec3d b;
|
||||
|
||||
static const constexpr int Dim = 3;
|
||||
using Scalar = Vec3d::Scalar;
|
||||
};
|
||||
|
||||
BoundingBox get_extents(const Lines &lines);
|
||||
|
|
|
@ -106,8 +106,8 @@ template<class C> bool all_of(const C &container)
|
|||
});
|
||||
}
|
||||
|
||||
template<class T>
|
||||
using remove_cvref_t = std::remove_reference_t<std::remove_cv_t<T>>;
|
||||
//template<class T>
|
||||
//using remove_cvref_t = std::remove_reference_t<std::remove_cv_t<T>>;
|
||||
|
||||
/// Exactly like Matlab https://www.mathworks.com/help/matlab/ref/linspace.html
|
||||
template<class T, class I, class = IntegerOnly<I>>
|
||||
|
|
|
@ -14,55 +14,9 @@
|
|||
#include <boost/multiprecision/integer.hpp>
|
||||
#endif
|
||||
|
||||
#include <libnest2d/geometry_traits.hpp>
|
||||
#include <libnest2d/backends/libslic3r/geometries.hpp>
|
||||
#include <libnest2d/utils/rotcalipers.hpp>
|
||||
|
||||
namespace libnest2d {
|
||||
|
||||
template<> struct PointType<Slic3r::Points> { using Type = Slic3r::Point; };
|
||||
template<> struct CoordType<Slic3r::Point> { using Type = coord_t; };
|
||||
template<> struct ShapeTag<Slic3r::ExPolygon> { using Type = PolygonTag; };
|
||||
template<> struct ShapeTag<Slic3r::Polygon> { using Type = PolygonTag; };
|
||||
template<> struct ShapeTag<Slic3r::Points> { using Type = PathTag; };
|
||||
template<> struct ShapeTag<Slic3r::Point> { using Type = PointTag; };
|
||||
template<> struct ContourType<Slic3r::ExPolygon> { using Type = Slic3r::Points; };
|
||||
template<> struct ContourType<Slic3r::Polygon> { using Type = Slic3r::Points; };
|
||||
|
||||
namespace pointlike {
|
||||
|
||||
template<> inline coord_t x(const Slic3r::Point& p) { return p.x(); }
|
||||
template<> inline coord_t y(const Slic3r::Point& p) { return p.y(); }
|
||||
template<> inline coord_t& x(Slic3r::Point& p) { return p.x(); }
|
||||
template<> inline coord_t& y(Slic3r::Point& p) { return p.y(); }
|
||||
|
||||
} // pointlike
|
||||
|
||||
namespace shapelike {
|
||||
template<> inline Slic3r::Points& contour(Slic3r::ExPolygon& sh) { return sh.contour.points; }
|
||||
template<> inline const Slic3r::Points& contour(const Slic3r::ExPolygon& sh) { return sh.contour.points; }
|
||||
template<> inline Slic3r::Points& contour(Slic3r::Polygon& sh) { return sh.points; }
|
||||
template<> inline const Slic3r::Points& contour(const Slic3r::Polygon& sh) { return sh.points; }
|
||||
|
||||
template<> Slic3r::Points::iterator begin(Slic3r::Points& pts, const PathTag&) { return pts.begin();}
|
||||
template<> Slic3r::Points::const_iterator cbegin(const Slic3r::Points& pts, const PathTag&) { return pts.cbegin(); }
|
||||
template<> Slic3r::Points::iterator end(Slic3r::Points& pts, const PathTag&) { return pts.end();}
|
||||
template<> Slic3r::Points::const_iterator cend(const Slic3r::Points& pts, const PathTag&) { return pts.cend(); }
|
||||
|
||||
template<> inline Slic3r::ExPolygon create<Slic3r::ExPolygon>(Slic3r::Points&& contour)
|
||||
{
|
||||
Slic3r::ExPolygon expoly; expoly.contour.points.swap(contour);
|
||||
return expoly;
|
||||
}
|
||||
|
||||
template<> inline Slic3r::Polygon create<Slic3r::Polygon>(Slic3r::Points&& contour)
|
||||
{
|
||||
Slic3r::Polygon poly; poly.points.swap(contour);
|
||||
return poly;
|
||||
}
|
||||
|
||||
} // shapelike
|
||||
} // libnest2d
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// Used as compute type.
|
||||
|
@ -74,13 +28,22 @@ using Rational = boost::rational<boost::multiprecision::int128_t>;
|
|||
using Rational = boost::rational<__int128>;
|
||||
#endif
|
||||
|
||||
template<class P>
|
||||
libnest2d::RotatedBox<Point, Unit> minAreaBoundigBox_(
|
||||
const P &p, MinAreaBoundigBox::PolygonLevel lvl)
|
||||
{
|
||||
P chull = lvl == MinAreaBoundigBox::pcConvex ?
|
||||
p :
|
||||
libnest2d::sl::convexHull(p);
|
||||
|
||||
libnest2d::removeCollinearPoints(chull);
|
||||
|
||||
return libnest2d::minAreaBoundingBox<P, Unit, Rational>(chull);
|
||||
}
|
||||
|
||||
MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc)
|
||||
{
|
||||
const Polygon &chull = pc == pcConvex ? p :
|
||||
libnest2d::sl::convexHull(p);
|
||||
|
||||
libnest2d::RotatedBox<Point, Unit> box =
|
||||
libnest2d::minAreaBoundingBox<Polygon, Unit, Rational>(chull);
|
||||
libnest2d::RotatedBox<Point, Unit> box = minAreaBoundigBox_(p, pc);
|
||||
|
||||
m_right = libnest2d::cast<long double>(box.right_extent());
|
||||
m_bottom = libnest2d::cast<long double>(box.bottom_extent());
|
||||
|
@ -89,11 +52,7 @@ MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc)
|
|||
|
||||
MinAreaBoundigBox::MinAreaBoundigBox(const ExPolygon &p, PolygonLevel pc)
|
||||
{
|
||||
const ExPolygon &chull = pc == pcConvex ? p :
|
||||
libnest2d::sl::convexHull(p);
|
||||
|
||||
libnest2d::RotatedBox<Point, Unit> box =
|
||||
libnest2d::minAreaBoundingBox<ExPolygon, Unit, Rational>(chull);
|
||||
libnest2d::RotatedBox<Point, Unit> box = minAreaBoundigBox_(p, pc);
|
||||
|
||||
m_right = libnest2d::cast<long double>(box.right_extent());
|
||||
m_bottom = libnest2d::cast<long double>(box.bottom_extent());
|
||||
|
@ -102,11 +61,7 @@ MinAreaBoundigBox::MinAreaBoundigBox(const ExPolygon &p, PolygonLevel pc)
|
|||
|
||||
MinAreaBoundigBox::MinAreaBoundigBox(const Points &pts, PolygonLevel pc)
|
||||
{
|
||||
const Points &chull = pc == pcConvex ? pts :
|
||||
libnest2d::sl::convexHull(pts);
|
||||
|
||||
libnest2d::RotatedBox<Point, Unit> box =
|
||||
libnest2d::minAreaBoundingBox<Points, Unit, Rational>(chull);
|
||||
libnest2d::RotatedBox<Point, Unit> box = minAreaBoundigBox_(pts, pc);
|
||||
|
||||
m_right = libnest2d::cast<long double>(box.right_extent());
|
||||
m_bottom = libnest2d::cast<long double>(box.bottom_extent());
|
||||
|
|
|
@ -26,12 +26,8 @@ public:
|
|||
};
|
||||
|
||||
// Constructors with various types of geometry data used in Slic3r.
|
||||
// If the convexity is known apriory, pcConvex can be used to skip
|
||||
// convex hull calculation. It is very important that the input polygons
|
||||
// do NOT have any collinear points (except for the first and the last
|
||||
// vertex being the same -- meaning a closed polygon for boost)
|
||||
// To make sure this constraint is satisfied, you can call
|
||||
// remove_collinear_points on the input polygon before handing over here)
|
||||
// If the convexity is known apriory, pcConvex can be used to skip
|
||||
// convex hull calculation.
|
||||
explicit MinAreaBoundigBox(const Polygon&, PolygonLevel = pcSimple);
|
||||
explicit MinAreaBoundigBox(const ExPolygon&, PolygonLevel = pcSimple);
|
||||
explicit MinAreaBoundigBox(const Points&, PolygonLevel = pcSimple);
|
||||
|
|
|
@ -84,6 +84,13 @@ public:
|
|||
|
||||
static Points _douglas_peucker(const Points &points, const double tolerance);
|
||||
static Points visivalingam(const Points& pts, const double& tolerance);
|
||||
|
||||
inline auto begin() { return points.begin(); }
|
||||
inline auto begin() const { return points.begin(); }
|
||||
inline auto end() { return points.end(); }
|
||||
inline auto end() const { return points.end(); }
|
||||
inline auto cbegin() const { return points.begin(); }
|
||||
inline auto cend() const { return points.end(); }
|
||||
};
|
||||
|
||||
class MultiPoint3
|
||||
|
|
|
@ -17,42 +17,42 @@ class BoundingBox;
|
|||
class Line;
|
||||
class MultiPoint;
|
||||
class Point;
|
||||
typedef Point Vector;
|
||||
using Vector = Point;
|
||||
|
||||
// Eigen types, to replace the Slic3r's own types in the future.
|
||||
// Vector types with a fixed point coordinate base type.
|
||||
typedef Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign> Vec2crd;
|
||||
typedef Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign> Vec3crd;
|
||||
typedef Eigen::Matrix<int, 2, 1, Eigen::DontAlign> Vec2i;
|
||||
typedef Eigen::Matrix<int, 3, 1, Eigen::DontAlign> Vec3i;
|
||||
typedef Eigen::Matrix<int32_t, 2, 1, Eigen::DontAlign> Vec2i32;
|
||||
typedef Eigen::Matrix<int64_t, 2, 1, Eigen::DontAlign> Vec2i64;
|
||||
typedef Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign> Vec3i32;
|
||||
typedef Eigen::Matrix<int64_t, 3, 1, Eigen::DontAlign> Vec3i64;
|
||||
using Vec2crd = Eigen::Matrix<coord_t, 2, 1, Eigen::DontAlign>;
|
||||
using Vec3crd = Eigen::Matrix<coord_t, 3, 1, Eigen::DontAlign>;
|
||||
using Vec2i = Eigen::Matrix<int, 2, 1, Eigen::DontAlign>;
|
||||
using Vec3i = Eigen::Matrix<int, 3, 1, Eigen::DontAlign>;
|
||||
using Vec2i32 = Eigen::Matrix<int32_t, 2, 1, Eigen::DontAlign>;
|
||||
using Vec2i64 = Eigen::Matrix<int64_t, 2, 1, Eigen::DontAlign>;
|
||||
using Vec3i32 = Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign>;
|
||||
using Vec3i64 = Eigen::Matrix<int64_t, 3, 1, Eigen::DontAlign>;
|
||||
|
||||
// Vector types with a double coordinate base type.
|
||||
typedef Eigen::Matrix<float, 2, 1, Eigen::DontAlign> Vec2f;
|
||||
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> Vec3f;
|
||||
typedef Eigen::Matrix<double, 2, 1, Eigen::DontAlign> Vec2d;
|
||||
typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> Vec3d;
|
||||
using Vec2f = Eigen::Matrix<float, 2, 1, Eigen::DontAlign>;
|
||||
using Vec3f = Eigen::Matrix<float, 3, 1, Eigen::DontAlign>;
|
||||
using Vec2d = Eigen::Matrix<double, 2, 1, Eigen::DontAlign>;
|
||||
using Vec3d = Eigen::Matrix<double, 3, 1, Eigen::DontAlign>;
|
||||
|
||||
typedef std::vector<Point> Points;
|
||||
typedef std::vector<Point*> PointPtrs;
|
||||
typedef std::vector<const Point*> PointConstPtrs;
|
||||
typedef std::vector<Vec3crd> Points3;
|
||||
typedef std::vector<Vec2d> Pointfs;
|
||||
typedef std::vector<Vec2d> Vec2ds;
|
||||
typedef std::vector<Vec3d> Pointf3s;
|
||||
using Points = std::vector<Point>;
|
||||
using PointPtrs = std::vector<Point*>;
|
||||
using PointConstPtrs = std::vector<const Point*>;
|
||||
using Points3 = std::vector<Vec3crd>;
|
||||
using Pointfs = std::vector<Vec2d>;
|
||||
using Vec2ds = std::vector<Vec2d>;
|
||||
using Pointf3s = std::vector<Vec3d>;
|
||||
|
||||
typedef Eigen::Matrix<float, 2, 2, Eigen::DontAlign> Matrix2f;
|
||||
typedef Eigen::Matrix<double, 2, 2, Eigen::DontAlign> Matrix2d;
|
||||
typedef Eigen::Matrix<float, 3, 3, Eigen::DontAlign> Matrix3f;
|
||||
typedef Eigen::Matrix<double, 3, 3, Eigen::DontAlign> Matrix3d;
|
||||
using Matrix2f = Eigen::Matrix<float, 2, 2, Eigen::DontAlign>;
|
||||
using Matrix2d = Eigen::Matrix<double, 2, 2, Eigen::DontAlign>;
|
||||
using Matrix3f = Eigen::Matrix<float, 3, 3, Eigen::DontAlign>;
|
||||
using Matrix3d = Eigen::Matrix<double, 3, 3, Eigen::DontAlign>;
|
||||
|
||||
typedef Eigen::Transform<float, 2, Eigen::Affine, Eigen::DontAlign> Transform2f;
|
||||
typedef Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAlign> Transform2d;
|
||||
typedef Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign> Transform3f;
|
||||
typedef Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign> Transform3d;
|
||||
using Transform2f = Eigen::Transform<float, 2, Eigen::Affine, Eigen::DontAlign>;
|
||||
using Transform2d = Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAlign>;
|
||||
using Transform3f = Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign>;
|
||||
using Transform3d = Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign>;
|
||||
|
||||
inline bool operator<(const Vec2d &lhs, const Vec2d &rhs) { return lhs(0) < rhs(0) || (lhs(0) == rhs(0) && lhs(1) < rhs(1)); }
|
||||
|
||||
|
@ -101,7 +101,7 @@ template<int N, class T> using Vec = Eigen::Matrix<T, N, 1, Eigen::DontAlign, N
|
|||
class Point : public Vec2crd
|
||||
{
|
||||
public:
|
||||
typedef coord_t coord_type;
|
||||
using coord_type = coord_t;
|
||||
|
||||
Point() : Vec2crd(0, 0) {}
|
||||
Point(int32_t x, int32_t y) : Vec2crd(coord_t(x), coord_t(y)) {}
|
||||
|
@ -337,7 +337,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
typedef typename std::unordered_multimap<Vec2crd, ValueType, PointHash> map_type;
|
||||
using map_type = typename std::unordered_multimap<Vec2crd, ValueType, PointHash>;
|
||||
PointAccessor m_point_accessor;
|
||||
map_type m_map;
|
||||
coord_t m_search_radius;
|
||||
|
@ -439,11 +439,11 @@ inline Point align_to_grid(Point coord, Point spacing, Point base)
|
|||
#include <boost/polygon/polygon.hpp>
|
||||
namespace boost { namespace polygon {
|
||||
template <>
|
||||
struct geometry_concept<Slic3r::Point> { typedef point_concept type; };
|
||||
struct geometry_concept<Slic3r::Point> { using type = point_concept; };
|
||||
|
||||
template <>
|
||||
struct point_traits<Slic3r::Point> {
|
||||
typedef coord_t coordinate_type;
|
||||
using coordinate_type = coord_t;
|
||||
|
||||
static inline coordinate_type get(const Slic3r::Point& point, orientation_2d orient) {
|
||||
return static_cast<coordinate_type>(point((orient == HORIZONTAL) ? 0 : 1));
|
||||
|
@ -452,7 +452,7 @@ namespace boost { namespace polygon {
|
|||
|
||||
template <>
|
||||
struct point_mutable_traits<Slic3r::Point> {
|
||||
typedef coord_t coordinate_type;
|
||||
using coordinate_type = coord_t;
|
||||
static inline void set(Slic3r::Point& point, orientation_2d orient, coord_t value) {
|
||||
point((orient == HORIZONTAL) ? 0 : 1) = value;
|
||||
}
|
||||
|
|
|
@ -72,6 +72,9 @@ public:
|
|||
// Projection of a point onto the polygon.
|
||||
Point point_projection(const Point &point) const;
|
||||
std::vector<float> parameter_by_length() const;
|
||||
|
||||
using iterator = Points::iterator;
|
||||
using const_iterator = Points::const_iterator;
|
||||
};
|
||||
|
||||
inline bool operator==(const Polygon &lhs, const Polygon &rhs) { return lhs.points == rhs.points; }
|
||||
|
@ -90,6 +93,8 @@ inline double total_length(const Polygons &polylines) {
|
|||
return total;
|
||||
}
|
||||
|
||||
inline double area(const Polygon &poly) { return poly.area(); }
|
||||
|
||||
inline double area(const Polygons &polys)
|
||||
{
|
||||
double s = 0.;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <libslic3r/SLA/RasterBase.hpp>
|
||||
#include "libslic3r/ExPolygon.hpp"
|
||||
#include "libslic3r/MTUtils.hpp"
|
||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
||||
|
||||
// For rasterizing
|
||||
#include <agg/agg_basics.h>
|
||||
|
@ -21,10 +20,7 @@
|
|||
namespace Slic3r {
|
||||
|
||||
inline const Polygon& contour(const ExPolygon& p) { return p.contour; }
|
||||
inline const ClipperLib::Path& contour(const ClipperLib::Polygon& p) { return p.Contour; }
|
||||
|
||||
inline const Polygons& holes(const ExPolygon& p) { return p.holes; }
|
||||
inline const ClipperLib::Paths& holes(const ClipperLib::Polygon& p) { return p.Holes; }
|
||||
|
||||
namespace sla {
|
||||
|
||||
|
@ -77,8 +73,6 @@ protected:
|
|||
double getPx(const Point &p) { return p(0) * m_pxdim_scaled.w_mm; }
|
||||
double getPy(const Point &p) { return p(1) * m_pxdim_scaled.h_mm; }
|
||||
agg::path_storage to_path(const Polygon &poly) { return to_path(poly.points); }
|
||||
double getPx(const ClipperLib::IntPoint &p) { return p.X * m_pxdim_scaled.w_mm; }
|
||||
double getPy(const ClipperLib::IntPoint& p) { return p.Y * m_pxdim_scaled.h_mm; }
|
||||
|
||||
template<class PointVec> agg::path_storage _to_path(const PointVec& v)
|
||||
{
|
||||
|
@ -168,7 +162,6 @@ public:
|
|||
}
|
||||
|
||||
void draw(const ExPolygon &poly) override { _draw(poly); }
|
||||
void draw(const ClipperLib::Polygon &poly) override { _draw(poly); }
|
||||
|
||||
EncodedRaster encode(RasterEncoder encoder) const override
|
||||
{
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#include <libslic3r/ExPolygon.hpp>
|
||||
#include <libslic3r/SLA/Concurrency.hpp>
|
||||
|
||||
namespace ClipperLib { struct Polygon; }
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
template<class T> using uqptr = std::unique_ptr<T>;
|
||||
|
@ -92,7 +90,6 @@ public:
|
|||
|
||||
/// Draw a polygon with holes.
|
||||
virtual void draw(const ExPolygon& poly) = 0;
|
||||
virtual void draw(const ClipperLib::Polygon& poly) = 0;
|
||||
|
||||
/// Get the resolution of the raster.
|
||||
virtual Resolution resolution() const = 0;
|
||||
|
|
|
@ -12,11 +12,9 @@
|
|||
#include "ClipperUtils.hpp"
|
||||
#include "Tesselate.hpp"
|
||||
#include "ExPolygonCollection.hpp"
|
||||
#include "MinAreaBoundingBox.hpp"
|
||||
#include "libslic3r.h"
|
||||
|
||||
#include "libnest2d/backends/clipper/geometries.hpp"
|
||||
#include "libnest2d/utils/rotcalipers.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
|
||||
|
@ -400,7 +398,7 @@ std::vector<Vec2f> sample_expolygon(const ExPolygons &expolys, float samples_per
|
|||
void sample_expolygon_boundary(const ExPolygon & expoly,
|
||||
float samples_per_mm,
|
||||
std::vector<Vec2f> &out,
|
||||
std::mt19937 & rng)
|
||||
std::mt19937 & /*rng*/)
|
||||
{
|
||||
double point_stepping_scaled = scale_(1.f) / samples_per_mm;
|
||||
for (size_t i_contour = 0; i_contour <= expoly.holes.size(); ++ i_contour) {
|
||||
|
@ -553,9 +551,8 @@ void SupportPointGenerator::uniformly_cover(const ExPolygons& islands, Structure
|
|||
// auto bb = get_extents(islands);
|
||||
|
||||
if (flags & icfIsNew) {
|
||||
auto chull_ex = ExPolygonCollection{islands}.convex_hull();
|
||||
auto chull = Slic3rMultiPoint_to_ClipperPath(chull_ex);
|
||||
auto rotbox = libnest2d::minAreaBoundingBox(chull);
|
||||
auto chull = ExPolygonCollection{islands}.convex_hull();
|
||||
auto rotbox = MinAreaBoundigBox{chull, MinAreaBoundigBox::pcConvex};
|
||||
Vec2d bbdim = {unscaled(rotbox.width()), unscaled(rotbox.height())};
|
||||
|
||||
if (bbdim.x() > bbdim.y()) std::swap(bbdim.x(), bbdim.y());
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "Point.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
#include "Zipper.hpp"
|
||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -483,7 +482,7 @@ public:
|
|||
// The collection of slice records for the current level.
|
||||
std::vector<std::reference_wrapper<const SliceRecord>> m_slices;
|
||||
|
||||
std::vector<ClipperLib::Polygon> m_transformed_slices;
|
||||
ExPolygons m_transformed_slices;
|
||||
|
||||
template<class Container> void transformed_slices(Container&& c)
|
||||
{
|
||||
|
@ -507,7 +506,7 @@ public:
|
|||
|
||||
auto slices() const -> const decltype (m_slices)& { return m_slices; }
|
||||
|
||||
const std::vector<ClipperLib::Polygon> & transformed_slices() const {
|
||||
const ExPolygons & transformed_slices() const {
|
||||
return m_transformed_slices;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
#include <libslic3r/ClipperUtils.hpp>
|
||||
|
||||
// For geometry algorithms with native Clipper types (no copies and conversions)
|
||||
#include <libnest2d/backends/clipper/geometries.hpp>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "I18N.hpp"
|
||||
|
@ -717,55 +714,49 @@ void SLAPrint::Steps::slice_supports(SLAPrintObject &po) {
|
|||
report_status(-2, "", SlicingStatus::RELOAD_SLA_PREVIEW);
|
||||
}
|
||||
|
||||
using ClipperPoint = ClipperLib::IntPoint;
|
||||
using ClipperPolygon = ClipperLib::Polygon; // see clipper_polygon.hpp in libnest2d
|
||||
using ClipperPolygons = std::vector<ClipperPolygon>;
|
||||
//static ClipperPolygons polyunion(const ClipperPolygons &subjects)
|
||||
//{
|
||||
// ClipperLib::Clipper clipper;
|
||||
|
||||
static ClipperPolygons polyunion(const ClipperPolygons &subjects)
|
||||
{
|
||||
ClipperLib::Clipper clipper;
|
||||
// bool closed = true;
|
||||
|
||||
bool closed = true;
|
||||
// for(auto& path : subjects) {
|
||||
// clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
|
||||
// clipper.AddPaths(path.Holes, ClipperLib::ptSubject, closed);
|
||||
// }
|
||||
|
||||
for(auto& path : subjects) {
|
||||
clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
|
||||
clipper.AddPaths(path.Holes, ClipperLib::ptSubject, closed);
|
||||
}
|
||||
// auto mode = ClipperLib::pftPositive;
|
||||
|
||||
auto mode = ClipperLib::pftPositive;
|
||||
// return libnest2d::clipper_execute(clipper, ClipperLib::ctUnion, mode, mode);
|
||||
//}
|
||||
|
||||
return libnest2d::clipper_execute(clipper, ClipperLib::ctUnion, mode, mode);
|
||||
}
|
||||
//static ClipperPolygons polydiff(const ClipperPolygons &subjects, const ClipperPolygons& clips)
|
||||
//{
|
||||
// ClipperLib::Clipper clipper;
|
||||
|
||||
static ClipperPolygons polydiff(const ClipperPolygons &subjects, const ClipperPolygons& clips)
|
||||
{
|
||||
ClipperLib::Clipper clipper;
|
||||
// bool closed = true;
|
||||
|
||||
bool closed = true;
|
||||
// for(auto& path : subjects) {
|
||||
// clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
|
||||
// clipper.AddPaths(path.Holes, ClipperLib::ptSubject, closed);
|
||||
// }
|
||||
|
||||
for(auto& path : subjects) {
|
||||
clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
|
||||
clipper.AddPaths(path.Holes, ClipperLib::ptSubject, closed);
|
||||
}
|
||||
// for(auto& path : clips) {
|
||||
// clipper.AddPath(path.Contour, ClipperLib::ptClip, closed);
|
||||
// clipper.AddPaths(path.Holes, ClipperLib::ptClip, closed);
|
||||
// }
|
||||
|
||||
for(auto& path : clips) {
|
||||
clipper.AddPath(path.Contour, ClipperLib::ptClip, closed);
|
||||
clipper.AddPaths(path.Holes, ClipperLib::ptClip, closed);
|
||||
}
|
||||
// auto mode = ClipperLib::pftPositive;
|
||||
|
||||
auto mode = ClipperLib::pftPositive;
|
||||
|
||||
return libnest2d::clipper_execute(clipper, ClipperLib::ctDifference, mode, mode);
|
||||
}
|
||||
// return libnest2d::clipper_execute(clipper, ClipperLib::ctDifference, mode, mode);
|
||||
//}
|
||||
|
||||
// get polygons for all instances in the object
|
||||
static ClipperPolygons get_all_polygons(const SliceRecord& record, SliceOrigin o)
|
||||
static ExPolygons get_all_polygons(const SliceRecord& record, SliceOrigin o)
|
||||
{
|
||||
namespace sl = libnest2d::sl;
|
||||
|
||||
if (!record.print_obj()) return {};
|
||||
|
||||
ClipperPolygons polygons;
|
||||
ExPolygons polygons;
|
||||
auto &input_polygons = record.get_slice(o);
|
||||
auto &instances = record.print_obj()->instances();
|
||||
bool is_lefthanded = record.print_obj()->is_left_handed();
|
||||
|
@ -776,43 +767,42 @@ static ClipperPolygons get_all_polygons(const SliceRecord& record, SliceOrigin o
|
|||
|
||||
for (size_t i = 0; i < instances.size(); ++i)
|
||||
{
|
||||
ClipperPolygon poly;
|
||||
ExPolygon poly;
|
||||
|
||||
// We need to reverse if is_lefthanded is true but
|
||||
bool needreverse = is_lefthanded;
|
||||
|
||||
// should be a move
|
||||
poly.Contour.reserve(polygon.contour.size() + 1);
|
||||
poly.contour.points.reserve(polygon.contour.size() + 1);
|
||||
|
||||
auto& cntr = polygon.contour.points;
|
||||
if(needreverse)
|
||||
for(auto it = cntr.rbegin(); it != cntr.rend(); ++it)
|
||||
poly.Contour.emplace_back(it->x(), it->y());
|
||||
poly.contour.points.emplace_back(it->x(), it->y());
|
||||
else
|
||||
for(auto& p : cntr)
|
||||
poly.Contour.emplace_back(p.x(), p.y());
|
||||
poly.contour.points.emplace_back(p.x(), p.y());
|
||||
|
||||
for(auto& h : polygon.holes) {
|
||||
poly.Holes.emplace_back();
|
||||
auto& hole = poly.Holes.back();
|
||||
hole.reserve(h.points.size() + 1);
|
||||
poly.holes.emplace_back();
|
||||
auto& hole = poly.holes.back();
|
||||
hole.points.reserve(h.points.size() + 1);
|
||||
|
||||
if(needreverse)
|
||||
for(auto it = h.points.rbegin(); it != h.points.rend(); ++it)
|
||||
hole.emplace_back(it->x(), it->y());
|
||||
hole.points.emplace_back(it->x(), it->y());
|
||||
else
|
||||
for(auto& p : h.points)
|
||||
hole.emplace_back(p.x(), p.y());
|
||||
hole.points.emplace_back(p.x(), p.y());
|
||||
}
|
||||
|
||||
if(is_lefthanded) {
|
||||
for(auto& p : poly.Contour) p.X = -p.X;
|
||||
for(auto& h : poly.Holes) for(auto& p : h) p.X = -p.X;
|
||||
for(auto& p : poly.contour) p.x() = -p.x();
|
||||
for(auto& h : poly.holes) for(auto& p : h) p.x() = -p.x();
|
||||
}
|
||||
|
||||
sl::rotate(poly, double(instances[i].rotation));
|
||||
sl::translate(poly, ClipperPoint{instances[i].shift.x(),
|
||||
instances[i].shift.y()});
|
||||
poly.rotate(double(instances[i].rotation));
|
||||
poly.translate(Point{instances[i].shift.x(), instances[i].shift.y()});
|
||||
|
||||
polygons.emplace_back(std::move(poly));
|
||||
}
|
||||
|
@ -878,9 +868,6 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
|||
|
||||
print_statistics.clear();
|
||||
|
||||
// libnest calculates positive area for clockwise polygons, Slic3r is in counter-clockwise
|
||||
auto areafn = [](const ClipperPolygon& poly) { return - libnest2d::sl::area(poly); };
|
||||
|
||||
const double area_fill = printer_config.area_fill.getFloat()*0.01;// 0.5 (50%);
|
||||
const double fast_tilt = printer_config.fast_tilt_time.getFloat();// 5.0;
|
||||
const double slow_tilt = printer_config.slow_tilt_time.getFloat();// 8.0;
|
||||
|
@ -913,7 +900,7 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
|||
// Going to parallel:
|
||||
auto printlayerfn = [this,
|
||||
// functions and read only vars
|
||||
areafn, area_fill, display_area, exp_time, init_exp_time, fast_tilt, slow_tilt, delta_fade_time,
|
||||
area_fill, display_area, exp_time, init_exp_time, fast_tilt, slow_tilt, delta_fade_time,
|
||||
|
||||
// write vars
|
||||
&mutex, &models_volume, &supports_volume, &estim_time, &slow_layers,
|
||||
|
@ -931,8 +918,8 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
|||
|
||||
// Calculation of the consumed material
|
||||
|
||||
ClipperPolygons model_polygons;
|
||||
ClipperPolygons supports_polygons;
|
||||
ExPolygons model_polygons;
|
||||
ExPolygons supports_polygons;
|
||||
|
||||
size_t c = std::accumulate(layer.slices().begin(),
|
||||
layer.slices().end(),
|
||||
|
@ -954,44 +941,44 @@ void SLAPrint::Steps::merge_slices_and_eval_stats() {
|
|||
|
||||
for(const SliceRecord& record : layer.slices()) {
|
||||
|
||||
ClipperPolygons modelslices = get_all_polygons(record, soModel);
|
||||
for(ClipperPolygon& p_tmp : modelslices) model_polygons.emplace_back(std::move(p_tmp));
|
||||
ExPolygons modelslices = get_all_polygons(record, soModel);
|
||||
for(ExPolygon& p_tmp : modelslices) model_polygons.emplace_back(std::move(p_tmp));
|
||||
|
||||
ClipperPolygons supportslices = get_all_polygons(record, soSupport);
|
||||
for(ClipperPolygon& p_tmp : supportslices) supports_polygons.emplace_back(std::move(p_tmp));
|
||||
ExPolygons supportslices = get_all_polygons(record, soSupport);
|
||||
for(ExPolygon& p_tmp : supportslices) supports_polygons.emplace_back(std::move(p_tmp));
|
||||
|
||||
}
|
||||
|
||||
model_polygons = polyunion(model_polygons);
|
||||
model_polygons = union_ex(model_polygons);
|
||||
double layer_model_area = 0;
|
||||
for (const ClipperPolygon& polygon : model_polygons)
|
||||
layer_model_area += areafn(polygon);
|
||||
for (const ExPolygon& polygon : model_polygons)
|
||||
layer_model_area += area(polygon);
|
||||
|
||||
if (layer_model_area < 0 || layer_model_area > 0) {
|
||||
Lock lck(mutex); models_volume += layer_model_area * l_height;
|
||||
}
|
||||
|
||||
if(!supports_polygons.empty()) {
|
||||
if(model_polygons.empty()) supports_polygons = polyunion(supports_polygons);
|
||||
else supports_polygons = polydiff(supports_polygons, model_polygons);
|
||||
if(model_polygons.empty()) supports_polygons = union_ex(supports_polygons);
|
||||
else supports_polygons = diff_ex(supports_polygons, model_polygons);
|
||||
// allegedly, union of subject is done withing the diff according to the pftPositive polyFillType
|
||||
}
|
||||
|
||||
double layer_support_area = 0;
|
||||
for (const ClipperPolygon& polygon : supports_polygons)
|
||||
layer_support_area += areafn(polygon);
|
||||
for (const ExPolygon& polygon : supports_polygons)
|
||||
layer_support_area += area(polygon);
|
||||
|
||||
if (layer_support_area < 0 || layer_support_area > 0) {
|
||||
Lock lck(mutex); supports_volume += layer_support_area * l_height;
|
||||
}
|
||||
|
||||
// Here we can save the expensively calculated polygons for printing
|
||||
ClipperPolygons trslices;
|
||||
ExPolygons trslices;
|
||||
trslices.reserve(model_polygons.size() + supports_polygons.size());
|
||||
for(ClipperPolygon& poly : model_polygons) trslices.emplace_back(std::move(poly));
|
||||
for(ClipperPolygon& poly : supports_polygons) trslices.emplace_back(std::move(poly));
|
||||
for(ExPolygon& poly : model_polygons) trslices.emplace_back(std::move(poly));
|
||||
for(ExPolygon& poly : supports_polygons) trslices.emplace_back(std::move(poly));
|
||||
|
||||
layer.transformed_slices(polyunion(trslices));
|
||||
layer.transformed_slices(union_ex(trslices));
|
||||
|
||||
// Calculation of the slow and fast layers to the future controlling those values on FW
|
||||
|
||||
|
@ -1074,7 +1061,7 @@ void SLAPrint::Steps::rasterize()
|
|||
PrintLayer& printlayer = m_print->m_printer_input[idx];
|
||||
if(canceled()) return;
|
||||
|
||||
for (const ClipperLib::Polygon& poly : printlayer.transformed_slices())
|
||||
for (const ExPolygon& poly : printlayer.transformed_slices())
|
||||
raster.draw(poly);
|
||||
|
||||
// Status indication guarded with the spinlock
|
||||
|
|
|
@ -273,8 +273,8 @@ std::string SVG::get_path_d(const ClipperLib::Path &path, double scale, bool clo
|
|||
std::ostringstream d;
|
||||
d << "M ";
|
||||
for (ClipperLib::Path::const_iterator p = path.begin(); p != path.end(); ++p) {
|
||||
d << to_svg_x(scale * p->X - origin(0)) << " ";
|
||||
d << to_svg_y(scale * p->Y - origin(1)) << " ";
|
||||
d << to_svg_x(scale * p->x() - origin(0)) << " ";
|
||||
d << to_svg_y(scale * p->y() - origin(1)) << " ";
|
||||
}
|
||||
if (closed) d << "z";
|
||||
return d.str();
|
||||
|
|
13
src/libslic3r/clipper.cpp
Normal file
13
src/libslic3r/clipper.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Hackish wrapper around the ClipperLib library to compile the Clipper library using Slic3r::Point.
|
||||
|
||||
#include "clipper.hpp"
|
||||
|
||||
// Don't include <clipper/clipper.hpp> for the second time.
|
||||
#define clipper_hpp
|
||||
|
||||
// Override ClipperLib namespace to Slic3r::ClipperLib
|
||||
#define CLIPPERLIB_NAMESPACE_PREFIX Slic3r
|
||||
// Override Slic3r::ClipperLib::IntPoint to Slic3r::Point
|
||||
#define CLIPPERLIB_INTPOINT_TYPE Slic3r::Point
|
||||
|
||||
#include <clipper/clipper.cpp>
|
26
src/libslic3r/clipper.hpp
Normal file
26
src/libslic3r/clipper.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Hackish wrapper around the ClipperLib library to compile the Clipper library using Slic3r's own Point type.
|
||||
|
||||
#ifndef slic3r_clipper_hpp
|
||||
|
||||
#ifdef clipper_hpp
|
||||
#error "You should include the libslic3r/clipper.hpp before clipper/clipper.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef CLIPPERLIB_USE_XYZ
|
||||
#error "Something went wrong. Using clipper.hpp with Slic3r Point type, but CLIPPERLIB_USE_XYZ is defined."
|
||||
#endif
|
||||
|
||||
#define slic3r_clipper_hpp
|
||||
|
||||
#include "Point.hpp"
|
||||
|
||||
#define CLIPPERLIB_NAMESPACE_PREFIX Slic3r
|
||||
#define CLIPPERLIB_INTPOINT_TYPE Slic3r::Point
|
||||
|
||||
#include <clipper/clipper.hpp>
|
||||
|
||||
#undef clipper_hpp
|
||||
#undef CLIPPERLIB_NAMESPACE_PREFIX
|
||||
#undef CLIPPERLIB_INTPOINT_TYPE
|
||||
|
||||
#endif // slic3r_clipper_hpp
|
|
@ -308,6 +308,10 @@ IntegerOnly<I, std::vector<T, Args...>> reserve_vector(I capacity)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// Borrowed from C++20
|
||||
template<class T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
#include <cereal/types/base_class.hpp>
|
||||
|
||||
#include <clipper/clipper_z.hpp>
|
||||
#include <clipper/clipper.hpp>
|
||||
#include "clipper.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Config.hpp"
|
||||
|
@ -129,8 +129,6 @@
|
|||
#include "libslic3r.h"
|
||||
#include "libslic3r_version.h"
|
||||
|
||||
#include "clipper.hpp"
|
||||
|
||||
#include <Shiny/Shiny.h>
|
||||
|
||||
#include <admesh/stl.h>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue