diff --git a/CMakeLists.txt b/CMakeLists.txt index e19d3147bf..66b9a777b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -406,6 +406,7 @@ endif() set(TBB_DEBUG 1) find_package(TBB REQUIRED) slic3r_remap_configs(TBB::tbb RelWithDebInfo Release) +slic3r_remap_configs(TBB::tbbmalloc RelWithDebInfo Release) # include_directories(${TBB_INCLUDE_DIRS}) # add_definitions(${TBB_DEFINITIONS}) # if(MSVC) diff --git a/src/clipper/CMakeLists.txt b/src/clipper/CMakeLists.txt index 3cb7cb6bbd..1c1cfd5a7c 100644 --- a/src/clipper/CMakeLists.txt +++ b/src/clipper/CMakeLists.txt @@ -8,3 +8,5 @@ add_library(clipper STATIC clipper_z.cpp clipper_z.hpp ) + +target_link_libraries(clipper TBB::tbb TBB::tbbmalloc) diff --git a/src/clipper/clipper.cpp b/src/clipper/clipper.cpp index c4b7e8bc29..c775a3226c 100644 --- a/src/clipper/clipper.cpp +++ b/src/clipper/clipper.cpp @@ -784,7 +784,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) return false; // Allocate a new edge array. - std::vector edges(highI + 1); + Edges edges(highI + 1); // Fill in the edge array. bool result = AddPathInternal(pg, highI, PolyTyp, Closed, edges.data()); if (result) @@ -1079,7 +1079,7 @@ Clipper::Clipper(int initOptions) : void Clipper::Reset() { ClipperBase::Reset(); - m_Scanbeam = std::priority_queue(); + m_Scanbeam = std::priority_queue{}; m_Maxima.clear(); m_ActiveEdges = 0; m_SortedEdges = 0; @@ -2226,8 +2226,8 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) if (!eLastHorz->NextInLML) eMaxPair = GetMaximaPair(eLastHorz); - std::vector::const_iterator maxIt; - std::vector::const_reverse_iterator maxRit; + cInts::const_iterator maxIt; + cInts::const_reverse_iterator maxRit; if (!m_Maxima.empty()) { //get the first maxima in range (X) ... @@ -3941,7 +3941,7 @@ void CleanPolygon(const Path& in_poly, Path& out_poly, double distance) return; } - std::vector outPts(size); + OutPts outPts(size); for (size_t i = 0; i < size; ++i) { outPts[i].Pt = in_poly[i]; diff --git a/src/clipper/clipper.hpp b/src/clipper/clipper.hpp index 849672a8f9..d190d09b5d 100644 --- a/src/clipper/clipper.hpp +++ b/src/clipper/clipper.hpp @@ -39,6 +39,8 @@ #include +#include + #define CLIPPER_VERSION "6.2.6" //CLIPPERLIB_USE_XYZ: adds a Z member to IntPoint. Adds a minor cost to perfomance. @@ -112,8 +114,11 @@ using DoublePoint = Eigen::Matrix; //------------------------------------------------------------------------------ -typedef std::vector Path; -typedef std::vector Paths; +template +using Allocator = tbb::scalable_allocator; +//using Allocator = std::allocator; +using Path = std::vector>; +using Paths = std::vector>; inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;} inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;} @@ -133,7 +138,7 @@ enum JoinType {jtSquare, jtRound, jtMiter}; enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; class PolyNode; -typedef std::vector< PolyNode* > PolyNodes; +typedef std::vector> PolyNodes; class PolyNode { @@ -186,7 +191,7 @@ public: private: PolyTree(const PolyTree &src) = delete; PolyTree& operator=(const PolyTree &src) = delete; - std::vector AllNodes; + std::vector> AllNodes; friend class Clipper; //to access AllNodes }; @@ -277,6 +282,8 @@ enum EdgeSide { esLeft = 1, esRight = 2}; OutPt *Prev; }; + using OutPts = std::vector>; + struct OutRec; struct Join { Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) : @@ -312,7 +319,7 @@ public: if (num_paths == 1) return AddPath(*paths_provider.begin(), PolyTyp, Closed); - std::vector num_edges(num_paths, 0); + std::vector> num_edges(num_paths, 0); int num_edges_total = 0; size_t i = 0; for (const Path &pg : paths_provider) { @@ -333,7 +340,7 @@ public: return false; // Allocate a new edge array. - std::vector edges(num_edges_total); + std::vector> edges(num_edges_total); // Fill in the edge array. bool result = false; TEdge *p_edge = edges.data(); @@ -369,7 +376,7 @@ protected: void AscendToMax(TEdge *&E, bool Appending, bool IsClosed); // Local minima (Y, left edge, right edge) sorted by ascending Y. - std::vector m_MinimaList; + std::vector> m_MinimaList; #ifdef CLIPPERLIB_INT32 static constexpr const bool m_UseFullRange = false; @@ -380,7 +387,8 @@ protected: #endif // CLIPPERLIB_INT32 // A vector of edges per each input path. - std::vector> m_edges; + using Edges = std::vector>; + std::vector> m_edges; // Don't remove intermediate vertices of a collinear sequence of points. bool m_PreserveCollinear; // Is any of the paths inserted by AddPath() or AddPaths() open? @@ -424,22 +432,23 @@ protected: private: // Output polygons. - std::vector m_PolyOuts; + std::vector> m_PolyOuts; // Output points, allocated by a continuous sets of m_OutPtsChunkSize. - std::vector m_OutPts; + std::vector> m_OutPts; // List of free output points, to be used before taking a point from m_OutPts or allocating a new chunk. OutPt *m_OutPtsFree; size_t m_OutPtsChunkSize; size_t m_OutPtsChunkLast; - std::vector m_Joins; - std::vector m_GhostJoins; - std::vector m_IntersectList; + std::vector> m_Joins; + std::vector> m_GhostJoins; + std::vector> m_IntersectList; ClipType m_ClipType; // A priority queue (a binary heap) of Y coordinates. - std::priority_queue m_Scanbeam; + using cInts = std::vector>; + std::priority_queue m_Scanbeam; // Maxima are collected by ProcessEdgesAtTopOfScanbeam(), consumed by ProcessHorizontal(). - std::vector m_Maxima; + cInts m_Maxima; TEdge *m_ActiveEdges; TEdge *m_SortedEdges; PolyFillType m_ClipFillType; @@ -530,7 +539,7 @@ private: Paths m_destPolys; Path m_srcPoly; Path m_destPoly; - std::vector m_normals; + std::vector> m_normals; double m_delta, m_sinA, m_sin, m_cos; double m_miterLim, m_StepsPerRad; // x: index of the lowest contour in m_polyNodes diff --git a/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt index c18dc31cb4..154c965e5b 100644 --- a/src/libnest2d/CMakeLists.txt +++ b/src/libnest2d/CMakeLists.txt @@ -24,5 +24,5 @@ set(LIBNEST2D_SRCFILES add_library(libnest2d STATIC ${LIBNEST2D_SRCFILES}) target_include_directories(libnest2d PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) -target_link_libraries(libnest2d PUBLIC NLopt::nlopt TBB::tbb Boost::boost libslic3r) +target_link_libraries(libnest2d PUBLIC NLopt::nlopt TBB::tbb TBB::tbbmalloc Boost::boost libslic3r) target_compile_definitions(libnest2d PUBLIC LIBNEST2D_THREADING_tbb LIBNEST2D_STATIC LIBNEST2D_OPTIMIZER_nlopt LIBNEST2D_GEOMETRIES_libslic3r) diff --git a/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp b/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp index 381f18b700..26d2dbeee3 100644 --- a/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp +++ b/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -181,7 +180,7 @@ void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type& } else { - std::vector discretized = discretize(vd_edge, segments); + Points discretized = discretize(vd_edge, segments); assert(discretized.size() >= 2); if(discretized.size() < 2) { @@ -236,7 +235,7 @@ void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type& } } -std::vector SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const std::vector& segments) +Points SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const std::vector& segments) { /*Terminology in this function assumes that the edge moves horizontally from left to right. This is not necessarily the case; the edge can go in any @@ -257,7 +256,7 @@ std::vector SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_ bool point_right = right_cell->contains_point(); if ((!point_left && !point_right) || vd_edge.is_secondary()) // Source vert is directly connected to source segment { - return std::vector({ start, end }); + return Points({ start, end }); } else if (point_left != point_right) //This is a parabolic edge between a point and a line. { @@ -311,7 +310,7 @@ std::vector SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_ //Start generating points along the edge. Point a = start; Point b = end; - std::vector ret; + Points ret; ret.emplace_back(a); //Introduce an extra edge at the borders of the markings? @@ -522,9 +521,11 @@ static bool has_missing_twin_edge(const SkeletalTrapezoidationGraph &graph) return false; } -inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph, - const double fix_angle, - const std::unordered_map &vertex_mapping) +using PointMap = SkeletalTrapezoidation::PointMap; + +inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph, + const double fix_angle, + const PointMap &vertex_mapping) { for (STHalfEdgeNode &node : graph.nodes) { // If a mapping exists between a rotated point and an original point, use this mapping. Otherwise, rotate a point in the opposite direction. @@ -588,7 +589,7 @@ VoronoiDiagramStatus detect_voronoi_diagram_known_issues(const Geometry::Voronoi return VoronoiDiagramStatus::NO_ISSUE_DETECTED; } -inline static std::pair, double> try_to_fix_degenerated_voronoi_diagram_by_rotation( +inline static std::pair try_to_fix_degenerated_voronoi_diagram_by_rotation( Geometry::VoronoiDiagram &voronoi_diagram, const Polygons &polys, Polygons &polys_rotated, @@ -597,7 +598,7 @@ inline static std::pair, double> try { const Polygons polys_rotated_original = polys_rotated; double fixed_by_angle = fix_angles.front(); - std::unordered_map vertex_mapping; + PointMap vertex_mapping; for (const double &fix_angle : fix_angles) { vertex_mapping.clear(); @@ -685,7 +686,7 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys) const std::vector fix_angles = {PI / 6, PI / 5, PI / 7, PI / 11}; double fixed_by_angle = fix_angles.front(); - std::unordered_map vertex_mapping; + PointMap vertex_mapping; // polys_copy is referenced through items stored in the std::vector segments. Polygons polys_copy = polys; if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) { @@ -813,9 +814,11 @@ process_voronoi_diagram: edge.from->incident_edge = &edge; } +using NodeSet = SkeletalTrapezoidation::NodeSet; + void SkeletalTrapezoidation::separatePointyQuadEndNodes() { - std::unordered_set visited_nodes; + NodeSet visited_nodes; for (edge_t& edge : graph.edges) { if (edge.prev) @@ -2285,16 +2288,18 @@ void SkeletalTrapezoidation::addToolpathSegment(const ExtrusionJunction& from, c void SkeletalTrapezoidation::connectJunctions(ptr_vector_t& edge_junctions) { - std::unordered_set unprocessed_quad_starts(graph.edges.size() * 5 / 2); + using EdgeSet = ankerl::unordered_dense::set; + + EdgeSet unprocessed_quad_starts(graph.edges.size() * 5 / 2); for (edge_t& edge : graph.edges) { if (!edge.prev) { - unprocessed_quad_starts.insert(&edge); + unprocessed_quad_starts.emplace(&edge); } } - std::unordered_set passed_odd_edges; + EdgeSet passed_odd_edges; while (!unprocessed_quad_starts.empty()) { diff --git a/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp b/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp index b4029d586d..e2a013b154 100644 --- a/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp +++ b/src/libslic3r/Arachne/SkeletalTrapezoidation.hpp @@ -7,8 +7,10 @@ #include #include // smart pointers -#include #include // pair + +#include + #include #include "utils/HalfEdgeGraph.hpp" @@ -80,7 +82,9 @@ class SkeletalTrapezoidation const BeadingStrategy& beading_strategy; public: - using Segment = PolygonsSegmentIndex; + using Segment = PolygonsSegmentIndex; + using PointMap = ankerl::unordered_dense::map; + using NodeSet = ankerl::unordered_dense::set; /*! * Construct a new trapezoidation problem to solve. @@ -164,8 +168,8 @@ protected: * mapping each voronoi VD edge to the corresponding halfedge HE edge * In case the result segment is discretized, we map the VD edge to the *last* HE edge */ - std::unordered_map vd_edge_to_he_edge; - std::unordered_map vd_node_to_he_node; + ankerl::unordered_dense::map vd_edge_to_he_edge; + ankerl::unordered_dense::map vd_node_to_he_node; node_t& makeNode(vd_t::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet. /*! @@ -204,7 +208,7 @@ protected: * \return A number of coordinates along the edge where the edge is broken * up into discrete pieces. */ - std::vector discretize(const vd_t::edge_type& segment, const std::vector& segments); + Points discretize(const vd_t::edge_type& segment, const std::vector& segments); /*! * Compute the range of line segments that surround a cell of the skeletal diff --git a/src/libslic3r/Arachne/SkeletalTrapezoidationGraph.cpp b/src/libslic3r/Arachne/SkeletalTrapezoidationGraph.cpp index 4ef96eda1a..4629396e86 100644 --- a/src/libslic3r/Arachne/SkeletalTrapezoidationGraph.cpp +++ b/src/libslic3r/Arachne/SkeletalTrapezoidationGraph.cpp @@ -2,7 +2,8 @@ //CuraEngine is released under the terms of the AGPLv3 or higher. #include "SkeletalTrapezoidationGraph.hpp" -#include + +#include #include @@ -180,8 +181,8 @@ bool STHalfEdgeNode::isLocalMaximum(bool strict) const void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist) { - std::unordered_map::iterator> edge_locator; - std::unordered_map::iterator> node_locator; + ankerl::unordered_dense::map edge_locator; + ankerl::unordered_dense::map node_locator; for (auto edge_it = edges.begin(); edge_it != edges.end(); ++edge_it) { @@ -193,7 +194,7 @@ void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist) node_locator.emplace(&*node_it, node_it); } - auto safelyRemoveEdge = [this, &edge_locator](edge_t* to_be_removed, std::list::iterator& current_edge_it, bool& edge_it_is_updated) + auto safelyRemoveEdge = [this, &edge_locator](edge_t* to_be_removed, Edges::iterator& current_edge_it, bool& edge_it_is_updated) { if (current_edge_it != edges.end() && to_be_removed == &*current_edge_it) diff --git a/src/libslic3r/Arachne/WallToolPaths.cpp b/src/libslic3r/Arachne/WallToolPaths.cpp index dd2cda2713..fce69d5e4c 100644 --- a/src/libslic3r/Arachne/WallToolPaths.cpp +++ b/src/libslic3r/Arachne/WallToolPaths.cpp @@ -2,7 +2,6 @@ // CuraEngine is released under the terms of the AGPLv3 or higher. #include //For std::partition_copy and std::min_element. -#include #include "WallToolPaths.hpp" @@ -341,7 +340,7 @@ void removeSmallAreas(Polygons &thiss, const double min_area_size, const bool re } } else { // For each polygon, computes the signed area, move small outlines at the end of the vector and keep pointer on small holes - std::vector small_holes; + Polygons small_holes; for (auto it = thiss.begin(); it < new_end;) { if (double area = ClipperLib::Area(to_path(*it)); fabs(area) < min_area_size) { if (area >= 0) { @@ -767,9 +766,9 @@ bool WallToolPaths::removeEmptyToolPaths(std::vector &toolpa * * \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one. */ -std::unordered_set, boost::hash>> WallToolPaths::getRegionOrder(const std::vector &input, const bool outer_to_inner) +WallToolPaths::ExtrusionLineSet WallToolPaths::getRegionOrder(const std::vector &input, const bool outer_to_inner) { - std::unordered_set, boost::hash>> order_requirements; + ExtrusionLineSet order_requirements; // We build a grid where we map toolpath vertex locations to toolpaths, // so that we can easily find which two toolpaths are next to each other, diff --git a/src/libslic3r/Arachne/WallToolPaths.hpp b/src/libslic3r/Arachne/WallToolPaths.hpp index b0bed1241a..44f3affb69 100644 --- a/src/libslic3r/Arachne/WallToolPaths.hpp +++ b/src/libslic3r/Arachne/WallToolPaths.hpp @@ -5,7 +5,8 @@ #define CURAENGINE_WALLTOOLPATHS_H #include -#include + +#include #include "BeadingStrategy/BeadingStrategyFactory.hpp" #include "utils/ExtrusionLine.hpp" @@ -73,6 +74,7 @@ public: */ static bool removeEmptyToolPaths(std::vector &toolpaths); + using ExtrusionLineSet = ankerl::unordered_dense::set, boost::hash>>; /*! * Get the order constraints of the insets when printing walls per region / hole. * Each returned pair consists of adjacent wall lines where the left has an inset_idx one lower than the right. @@ -81,7 +83,7 @@ public: * * \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one. */ - static std::unordered_set, boost::hash>> getRegionOrder(const std::vector &input, bool outer_to_inner); + static ExtrusionLineSet getRegionOrder(const std::vector &input, bool outer_to_inner); protected: /*! diff --git a/src/libslic3r/Arachne/utils/HalfEdgeGraph.hpp b/src/libslic3r/Arachne/utils/HalfEdgeGraph.hpp index 99efff6a07..17b06f2be2 100644 --- a/src/libslic3r/Arachne/utils/HalfEdgeGraph.hpp +++ b/src/libslic3r/Arachne/utils/HalfEdgeGraph.hpp @@ -21,8 +21,10 @@ class HalfEdgeGraph public: using edge_t = derived_edge_t; using node_t = derived_node_t; - std::list edges; - std::list nodes; + using Edges = std::list; + using Nodes = std::list; + Edges edges; + Nodes nodes; }; } // namespace Slic3r::Arachne diff --git a/src/libslic3r/Arachne/utils/PolylineStitcher.hpp b/src/libslic3r/Arachne/utils/PolylineStitcher.hpp index 2ab770a3ec..113761ce15 100644 --- a/src/libslic3r/Arachne/utils/PolylineStitcher.hpp +++ b/src/libslic3r/Arachne/utils/PolylineStitcher.hpp @@ -7,7 +7,6 @@ #include "SparsePointGrid.hpp" #include "PolygonsPointIndex.hpp" #include "../../Polygon.hpp" -#include #include namespace Slic3r::Arachne diff --git a/src/libslic3r/Arachne/utils/SparseGrid.hpp b/src/libslic3r/Arachne/utils/SparseGrid.hpp index be461d4241..45876fb9a7 100644 --- a/src/libslic3r/Arachne/utils/SparseGrid.hpp +++ b/src/libslic3r/Arachne/utils/SparseGrid.hpp @@ -6,7 +6,6 @@ #define UTILS_SPARSE_GRID_H #include -#include #include #include diff --git a/src/libslic3r/Arachne/utils/SparseLineGrid.hpp b/src/libslic3r/Arachne/utils/SparseLineGrid.hpp index a9b5368697..0b38988f92 100644 --- a/src/libslic3r/Arachne/utils/SparseLineGrid.hpp +++ b/src/libslic3r/Arachne/utils/SparseLineGrid.hpp @@ -6,7 +6,6 @@ #define UTILS_SPARSE_LINE_GRID_H #include -#include #include #include diff --git a/src/libslic3r/Arachne/utils/SparsePointGrid.hpp b/src/libslic3r/Arachne/utils/SparsePointGrid.hpp index 31c1965357..7bb51d7038 100644 --- a/src/libslic3r/Arachne/utils/SparsePointGrid.hpp +++ b/src/libslic3r/Arachne/utils/SparsePointGrid.hpp @@ -6,7 +6,6 @@ #define UTILS_SPARSE_POINT_GRID_H #include -#include #include #include "SparseGrid.hpp" diff --git a/src/libslic3r/Arachne/utils/SquareGrid.hpp b/src/libslic3r/Arachne/utils/SquareGrid.hpp index c59c3ee1b9..5787e3bf12 100644 --- a/src/libslic3r/Arachne/utils/SquareGrid.hpp +++ b/src/libslic3r/Arachne/utils/SquareGrid.hpp @@ -7,7 +7,6 @@ #include "../../Point.hpp" #include -#include #include #include diff --git a/src/libslic3r/Arachne/utils/VoronoiUtils.cpp b/src/libslic3r/Arachne/utils/VoronoiUtils.cpp index 069e1f5ad5..675a0ebb42 100644 --- a/src/libslic3r/Arachne/utils/VoronoiUtils.cpp +++ b/src/libslic3r/Arachne/utils/VoronoiUtils.cpp @@ -138,9 +138,9 @@ public: return Point(coord_t(p.x() * matrix[0] + p.y() * matrix[2]), coord_t(p.x() * matrix[1] + p.y() * matrix[3])); } }; -std::vector VoronoiUtils::discretizeParabola(const Point& p, const Segment& segment, Point s, Point e, coord_t approximate_step_size, float transitioning_angle) +Points VoronoiUtils::discretizeParabola(const Point& p, const Segment& segment, Point s, Point e, coord_t approximate_step_size, float transitioning_angle) { - std::vector discretized; + Points discretized; // x is distance of point projected on the segment ab // xx is point projected on the segment ab const Point a = segment.from(); diff --git a/src/libslic3r/Arachne/utils/VoronoiUtils.hpp b/src/libslic3r/Arachne/utils/VoronoiUtils.hpp index aa46936437..ea6a8495a1 100644 --- a/src/libslic3r/Arachne/utils/VoronoiUtils.hpp +++ b/src/libslic3r/Arachne/utils/VoronoiUtils.hpp @@ -34,7 +34,7 @@ public: * Discretize a parabola based on (approximate) step size. * The \p approximate_step_size is measured parallel to the \p source_segment, not along the parabola. */ - static std::vector discretizeParabola(const Point &source_point, const Segment &source_segment, Point start, Point end, coord_t approximate_step_size, float transitioning_angle); + static Points discretizeParabola(const Point &source_point, const Segment &source_segment, Point start, Point end, coord_t approximate_step_size, float transitioning_angle); static inline bool is_finite(const VoronoiUtils::vd_t::vertex_type &vertex) { diff --git a/src/libslic3r/BoundingBox.cpp b/src/libslic3r/BoundingBox.cpp index 4f52c5108d..7e88eb92df 100644 --- a/src/libslic3r/BoundingBox.cpp +++ b/src/libslic3r/BoundingBox.cpp @@ -6,23 +6,19 @@ namespace Slic3r { -template BoundingBoxBase::BoundingBoxBase(const std::vector &points); +template BoundingBoxBase::BoundingBoxBase(const Points &points); template BoundingBoxBase::BoundingBoxBase(const std::vector &points); template BoundingBox3Base::BoundingBox3Base(const std::vector &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 @@ -37,8 +33,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; } @@ -47,23 +43,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 void -BoundingBoxBase::scale(double factor) +template void +BoundingBoxBase::scale(double factor) { this->min *= factor; this->max *= factor; } -template void BoundingBoxBase::scale(double factor); +template void BoundingBoxBase::scale(double factor); template void BoundingBoxBase::scale(double factor); template void BoundingBoxBase::scale(double factor); -template void -BoundingBoxBase::merge(const PointClass &point) +template void +BoundingBoxBase::merge(const PointType &point) { if (this->defined) { this->min = this->min.cwiseMin(point); @@ -74,22 +70,22 @@ BoundingBoxBase::merge(const PointClass &point) this->defined = true; } } -template void BoundingBoxBase::merge(const Point &point); +template void BoundingBoxBase::merge(const Point &point); template void BoundingBoxBase::merge(const Vec2f &point); template void BoundingBoxBase::merge(const Vec2d &point); -template void -BoundingBoxBase::merge(const std::vector &points) +template void +BoundingBoxBase::merge(const PointsType &points) { this->merge(BoundingBoxBase(points)); } -template void BoundingBoxBase::merge(const Points &points); +template void BoundingBoxBase::merge(const Points &points); template void BoundingBoxBase::merge(const Pointfs &points); -template void -BoundingBoxBase::merge(const BoundingBoxBase &bb) +template void +BoundingBoxBase::merge(const BoundingBoxBase &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); @@ -101,12 +97,12 @@ BoundingBoxBase::merge(const BoundingBoxBase &bb) } } } -template void BoundingBoxBase::merge(const BoundingBoxBase &bb); +template void BoundingBoxBase::merge(const BoundingBoxBase &bb); template void BoundingBoxBase::merge(const BoundingBoxBase &bb); template void BoundingBoxBase::merge(const BoundingBoxBase &bb); -template void -BoundingBox3Base::merge(const PointClass &point) +template void +BoundingBox3Base::merge(const PointType &point) { if (this->defined) { this->min = this->min.cwiseMin(point); @@ -120,17 +116,17 @@ BoundingBox3Base::merge(const PointClass &point) template void BoundingBox3Base::merge(const Vec3f &point); template void BoundingBox3Base::merge(const Vec3d &point); -template void -BoundingBox3Base::merge(const std::vector &points) +template void +BoundingBox3Base::merge(const PointsType &points) { this->merge(BoundingBox3Base(points)); } template void BoundingBox3Base::merge(const Pointf3s &points); -template void -BoundingBox3Base::merge(const BoundingBox3Base &bb) +template void +BoundingBox3Base::merge(const BoundingBox3Base &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); @@ -144,83 +140,78 @@ BoundingBox3Base::merge(const BoundingBox3Base &bb) } template void BoundingBox3Base::merge(const BoundingBox3Base &bb); -template PointClass -BoundingBoxBase::size() const +template PointType +BoundingBoxBase::size() const { - return PointClass(this->max(0) - this->min(0), this->max(1) - this->min(1)); + return this->max - this->min; } -template Point BoundingBoxBase::size() const; +template Point BoundingBoxBase::size() const; template Vec2f BoundingBoxBase::size() const; template Vec2d BoundingBoxBase::size() const; -template PointClass -BoundingBox3Base::size() const +template PointType +BoundingBox3Base::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::size() const; template Vec3d BoundingBox3Base::size() const; -template double BoundingBoxBase::radius() const +template double BoundingBoxBase::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().norm(); } -template double BoundingBoxBase::radius() const; +template double BoundingBoxBase::radius() const; template double BoundingBoxBase::radius() const; -template double BoundingBox3Base::radius() const +template double BoundingBox3Base::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().norm(); } template double BoundingBox3Base::radius() const; -template void -BoundingBoxBase::offset(coordf_t delta) +template void +BoundingBoxBase::offset(coordf_t delta) { - PointClass v(delta, delta); + PointType v(delta, delta); this->min -= v; this->max += v; } -template void BoundingBoxBase::offset(coordf_t delta); +template void BoundingBoxBase::offset(coordf_t delta); template void BoundingBoxBase::offset(coordf_t delta); -template void -BoundingBox3Base::offset(coordf_t delta) +template void +BoundingBox3Base::offset(coordf_t delta) { - PointClass v(delta, delta, delta); + PointType v(delta, delta, delta); this->min -= v; this->max += v; } template void BoundingBox3Base::offset(coordf_t delta); -template PointClass -BoundingBoxBase::center() const +template PointType +BoundingBoxBase::center() const { return (this->min + this->max) / 2; } -template Point BoundingBoxBase::center() const; +template Point BoundingBoxBase::center() const; template Vec2f BoundingBoxBase::center() const; template Vec2d BoundingBoxBase::center() const; -template PointClass -BoundingBox3Base::center() const +template PointType +BoundingBox3Base::center() const { return (this->min + this->max) / 2; } template Vec3f BoundingBox3Base::center() const; template Vec3d BoundingBox3Base::center() const; -template coordf_t -BoundingBox3Base::max_size() const +template coordf_t +BoundingBox3Base::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::max_size() const; template coordf_t BoundingBox3Base::max_size() const; @@ -228,8 +219,8 @@ template coordf_t BoundingBox3Base::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); } } @@ -238,14 +229,14 @@ BoundingBoxf3 BoundingBoxf3::transformed(const Transform3d& matrix) const typedef Eigen::Matrix 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(); diff --git a/src/libslic3r/BoundingBox.hpp b/src/libslic3r/BoundingBox.hpp index d741be36cc..fc1b500740 100644 --- a/src/libslic3r/BoundingBox.hpp +++ b/src/libslic3r/BoundingBox.hpp @@ -8,53 +8,54 @@ namespace Slic3r { -template +template > 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) : + 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 PointClass &p1, const PointClass &p2, const PointClass &p3) : + BoundingBoxBase(const PointType &p1, const PointType &p2, const PointType &p3) : min(p1), max(p1), defined(false) { merge(p2); merge(p3); } template> BoundingBoxBase(It from, It to) { construct(*this, from, to); } - BoundingBoxBase(const std::vector &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 &points); - void merge(const BoundingBoxBase &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 &bb); void scale(double factor); - PointClass size() const; + PointType size() const; double radius() const; - void translate(coordf_t x, coordf_t y) { assert(this->defined); PointClass v(x, y); this->min += v; this->max += v; } - void translate(const PointClass &v) { 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 inflated(coordf_t delta) const throw() { BoundingBoxBase out(*this); out.offset(delta); return out; } - PointClass center() const; - bool contains(const PointClass &point) const { + BoundingBoxBase inflated(coordf_t delta) const throw() { BoundingBoxBase 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 &other) const { + bool contains(const BoundingBoxBase &other) const { return contains(other.min) && contains(other.max); } - bool overlap(const BoundingBoxBase &other) const { + bool overlap(const BoundingBoxBase &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()); } - bool operator==(const BoundingBoxBase &rhs) { return this->min == rhs.min && this->max == rhs.max; } - bool operator!=(const BoundingBoxBase &rhs) { return ! (*this == rhs); } + bool operator==(const BoundingBoxBase &rhs) { return this->min == rhs.min && this->max == rhs.max; } + bool operator!=(const BoundingBoxBase &rhs) { return ! (*this == rhs); } private: // to access construct() @@ -69,10 +70,10 @@ private: { if (from != to) { auto it = from; - out.min = it->template cast(); + out.min = it->template cast(); out.max = out.min; for (++ it; it != to; ++ it) { - auto vec = it->template cast(); + auto vec = it->template cast(); out.min = out.min.cwiseMin(vec); out.max = out.max.cwiseMax(vec); } @@ -81,16 +82,18 @@ private: } }; -template -class BoundingBox3Base : public BoundingBoxBase +template +class BoundingBox3Base : public BoundingBoxBase> { public: - BoundingBox3Base() : BoundingBoxBase() {} - BoundingBox3Base(const PointClass &pmin, const PointClass &pmax) : - BoundingBoxBase(pmin, pmax) - { if (pmin.z() >= pmax.z()) BoundingBoxBase::defined = false; } - BoundingBox3Base(const PointClass &p1, const PointClass &p2, const PointClass &p3) : - BoundingBoxBase(p1, p1) { merge(p2); merge(p3); } + using PointsType = std::vector; + + BoundingBox3Base() : BoundingBoxBase() {} + BoundingBox3Base(const PointType &pmin, const PointType &pmax) : + BoundingBoxBase(pmin, pmax) + { if (pmin.z() >= pmax.z()) BoundingBoxBase::defined = false; } + BoundingBox3Base(const PointType &p1, const PointType &p2, const PointType &p3) : + BoundingBoxBase(p1, p1) { merge(p2); merge(p3); } template > BoundingBox3Base(It from, It to) { @@ -98,67 +101,67 @@ public: throw Slic3r::InvalidArgument("Empty point set supplied to BoundingBox3Base constructor"); auto it = from; - this->min = it->template cast(); + this->min = it->template cast(); this->max = this->min; for (++ it; it != to; ++ it) { - auto vec = it->template cast(); + auto vec = it->template cast(); this->min = this->min.cwiseMin(vec); this->max = this->max.cwiseMax(vec); } this->defined = (this->min.x() < this->max.x()) && (this->min.y() < this->max.y()) && (this->min.z() < this->max.z()); } - BoundingBox3Base(const std::vector &points) + BoundingBox3Base(const PointsType &points) : BoundingBox3Base(points.begin(), points.end()) {} - void merge(const PointClass &point); - void merge(const std::vector &points); - void merge(const BoundingBox3Base &bb); - PointClass size() const; + void merge(const PointType &point); + void merge(const PointsType &points); + void merge(const BoundingBox3Base &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 inflated(coordf_t delta) const throw() { BoundingBox3Base out(*this); out.offset(delta); return out; } - PointClass center() const; + BoundingBox3Base inflated(coordf_t delta) const throw() { BoundingBox3Base out(*this); out.offset(delta); return out; } + PointType center() const; coordf_t max_size() const; - bool contains(const PointClass &point) const { - return BoundingBoxBase::contains(point) && point.z() >= this->min.z() && point.z() <= this->max.z(); + bool contains(const PointType &point) const { + return BoundingBoxBase::contains(point) && point.z() >= this->min.z() && point.z() <= this->max.z(); } - bool contains(const BoundingBox3Base& other) const { + bool contains(const BoundingBox3Base& other) const { return contains(other.min) && contains(other.max); } // Intersects without boundaries. - bool intersects(const BoundingBox3Base& other) const { + bool intersects(const BoundingBox3Base& 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::scale(double factor); +extern template void BoundingBoxBase::scale(double factor); extern template void BoundingBoxBase::scale(double factor); extern template void BoundingBoxBase::scale(double factor); -extern template void BoundingBoxBase::offset(coordf_t delta); +extern template void BoundingBoxBase::offset(coordf_t delta); extern template void BoundingBoxBase::offset(coordf_t delta); -extern template void BoundingBoxBase::merge(const Point &point); +extern template void BoundingBoxBase::merge(const Point &point); extern template void BoundingBoxBase::merge(const Vec2f &point); extern template void BoundingBoxBase::merge(const Vec2d &point); -extern template void BoundingBoxBase::merge(const Points &points); +extern template void BoundingBoxBase::merge(const Points &points); extern template void BoundingBoxBase::merge(const Pointfs &points); -extern template void BoundingBoxBase::merge(const BoundingBoxBase &bb); +extern template void BoundingBoxBase::merge(const BoundingBoxBase &bb); extern template void BoundingBoxBase::merge(const BoundingBoxBase &bb); extern template void BoundingBoxBase::merge(const BoundingBoxBase &bb); -extern template Point BoundingBoxBase::size() const; +extern template Point BoundingBoxBase::size() const; extern template Vec2f BoundingBoxBase::size() const; extern template Vec2d BoundingBoxBase::size() const; -extern template double BoundingBoxBase::radius() const; +extern template double BoundingBoxBase::radius() const; extern template double BoundingBoxBase::radius() const; -extern template Point BoundingBoxBase::center() const; +extern template Point BoundingBoxBase::center() const; extern template Vec2f BoundingBoxBase::center() const; extern template Vec2d BoundingBoxBase::center() const; extern template void BoundingBox3Base::merge(const Vec3f &point); @@ -174,7 +177,7 @@ extern template Vec3d BoundingBox3Base::center() const; extern template coordf_t BoundingBox3Base::max_size() const; extern template coordf_t BoundingBox3Base::max_size() const; -class BoundingBox : public BoundingBoxBase +class BoundingBox : public BoundingBoxBase { public: void polygon(Polygon* polygon) const; @@ -187,9 +190,9 @@ public: // to encompass the original bounding box. void align_to_grid(const coord_t cell_size); - BoundingBox() : BoundingBoxBase() {} - BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase(pmin, pmax) {} - BoundingBox(const Points &points) : BoundingBoxBase(points) {} + BoundingBox() : BoundingBoxBase() {} + BoundingBox(const Point &pmin, const Point &pmax) : BoundingBoxBase(pmin, pmax) {} + BoundingBox(const Points &points) : BoundingBoxBase(points) {} BoundingBox inflated(coordf_t delta) const throw() { BoundingBox out(*this); out.offset(delta); return out; } @@ -222,14 +225,14 @@ public: BoundingBoxf3 transformed(const Transform3d& matrix) const; }; -template -inline bool empty(const BoundingBoxBase &bb) +template +inline bool empty(const BoundingBoxBase &bb) { return ! bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y(); } -template -inline bool empty(const BoundingBox3Base &bb) +template +inline bool empty(const BoundingBox3Base &bb) { return ! bb.defined || bb.min.x() >= bb.max.x() || bb.min.y() >= bb.max.y() || bb.min.z() >= bb.max.z(); } diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 61046e961a..53074d3bd8 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -485,6 +485,7 @@ target_link_libraries(libslic3r qhull semver TBB::tbb + TBB::tbbmalloc libslic3r_cgal ${CMAKE_DL_LIBS} PNG::PNG diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index 2869d0c870..95a5337185 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -3,6 +3,20 @@ #include "ShortestPath.hpp" #include "Utils.hpp" +// #define CLIPPER_UTILS_TIMING + +#ifdef CLIPPER_UTILS_TIMING + // time limit for one ClipperLib operation (union / diff / offset), in ms + #define CLIPPER_UTILS_TIME_LIMIT_DEFAULT 50 + #include + #include "Timer.hpp" + #define CLIPPER_UTILS_TIME_LIMIT_SECONDS(limit) Timing::TimeLimitAlarm time_limit_alarm(uint64_t(limit) * 1000000000l, BOOST_CURRENT_FUNCTION) + #define CLIPPER_UTILS_TIME_LIMIT_MILLIS(limit) Timing::TimeLimitAlarm time_limit_alarm(uint64_t(limit) * 1000000l, BOOST_CURRENT_FUNCTION) +#else + #define CLIPPER_UTILS_TIME_LIMIT_SECONDS(limit) do {} while(false) + #define CLIPPER_UTILS_TIME_LIMIT_MILLIS(limit) do {} while(false) +#endif // CLIPPER_UTILS_TIMING + // #define CLIPPER_UTILS_DEBUG #ifdef CLIPPER_UTILS_DEBUG @@ -51,9 +65,11 @@ namespace ClipperUtils { // 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 - inline void clip_clipper_polygon_with_subject_bbox_templ(const std::vector &src, const BoundingBox &bbox, std::vector &out) + template + inline void clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox, PointsType &out) { + using PointType = typename PointsType::value_type; + out.clear(); const size_t cnt = src.size(); if (cnt < 3) @@ -108,10 +124,10 @@ namespace ClipperUtils { 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 - [[nodiscard]] std::vector clip_clipper_polygon_with_subject_bbox_templ(const std::vector &src, const BoundingBox &bbox) + template + [[nodiscard]] PointsType clip_clipper_polygon_with_subject_bbox_templ(const PointsType &src, const BoundingBox &bbox) { - std::vector out; + PointsType out; clip_clipper_polygon_with_subject_bbox(src, bbox, out); return out; } @@ -258,6 +274,8 @@ bool has_duplicate_points(const ClipperLib::PolyTree &polytree) template static ClipperLib::Paths raw_offset(PathsProvider &&paths, float offset, ClipperLib::JoinType joinType, double miterLimit) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::ClipperOffset co; ClipperLib::Paths out; out.reserve(paths.size()); @@ -299,6 +317,8 @@ TResult clipper_do( TClip && clip, const ClipperLib::PolyFillType fillType) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Clipper clipper; clipper.AddPaths(std::forward(subject), ClipperLib::ptSubject, true); clipper.AddPaths(std::forward(clip), ClipperLib::ptClip, true); @@ -328,6 +348,8 @@ TResult clipper_union( // fillType pftNonZero and pftPositive "should" produce the same result for "normalized with implicit union" set of polygons const ClipperLib::PolyFillType fillType = ClipperLib::pftNonZero) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Clipper clipper; clipper.AddPaths(std::forward(subject), ClipperLib::ptSubject, true); TResult retval; @@ -366,6 +388,8 @@ template<> void remove_outermost_polygon(ClipperLib::PolyT template static TResult shrink_paths(PathsProvider &&paths, float offset, ClipperLib::JoinType joinType, double miterLimit) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + assert(offset > 0); TResult out; if (auto raw = raw_offset(std::forward(paths), - offset, joinType, miterLimit); ! raw.empty()) { @@ -405,6 +429,8 @@ Slic3r::Polygons offset(const Slic3r::Polylines &polylines, const float delta, C // returns number of expolygons collected (0 or 1). static int offset_expolygon_inner(const Slic3r::ExPolygon &expoly, const float delta, ClipperLib::JoinType joinType, double miterLimit, ClipperLib::Paths &out) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + // 1) Offset the outer contour. ClipperLib::Paths contours; { @@ -613,6 +639,8 @@ inline ClipperLib::PolyTree clipper_do_polytree( PathProvider2 &&clip, const ClipperLib::PolyFillType fillType) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + // Perform the operation with the output to input_subject. // This pass does not generate a PolyTree, which is a very expensive operation with the current Clipper library // if there are overapping edges. @@ -751,6 +779,8 @@ Slic3r::ExPolygons union_ex(const Slic3r::Surfaces &subject) template Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subject, PathsProvider2 &&clip) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Clipper clipper; clipper.AddPaths(std::forward(subject), ClipperLib::ptSubject, false); clipper.AddPaths(std::forward(clip), ClipperLib::ptClip, true); @@ -936,6 +966,8 @@ Polygons union_pt_chained_outside_in(const Polygons &subject) Polygons simplify_polygons(const Polygons &subject, bool preserve_collinear) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Paths output; if (preserve_collinear) { ClipperLib::Clipper c; @@ -953,6 +985,8 @@ Polygons simplify_polygons(const Polygons &subject, bool preserve_collinear) ExPolygons simplify_polygons_ex(const Polygons &subject, bool preserve_collinear) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + if (! preserve_collinear) return union_ex(simplify_polygons(subject, false)); @@ -969,6 +1003,8 @@ ExPolygons simplify_polygons_ex(const Polygons &subject, bool preserve_collinear Polygons top_level_islands(const Slic3r::Polygons &polygons) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + // init Clipper ClipperLib::Clipper clipper; clipper.Clear(); @@ -992,6 +1028,8 @@ ClipperLib::Paths fix_after_outer_offset( ClipperLib::PolyFillType filltype, // = ClipperLib::pftPositive bool reverse_result) // = false { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Paths solution; if (! input.empty()) { ClipperLib::Clipper clipper; @@ -1010,6 +1048,8 @@ ClipperLib::Paths fix_after_inner_offset( ClipperLib::PolyFillType filltype, // = ClipperLib::pftNegative bool reverse_result) // = true { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Paths solution; if (! input.empty()) { ClipperLib::Clipper clipper; @@ -1030,6 +1070,8 @@ ClipperLib::Paths fix_after_inner_offset( ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::vector &deltas, double miter_limit) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + assert(contour.size() == deltas.size()); #ifndef NDEBUG @@ -1170,6 +1212,8 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v static void variable_offset_inner_raw(const ExPolygon &expoly, const std::vector> &deltas, double miter_limit, ClipperLib::Paths &contours, ClipperLib::Paths &holes) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + #ifndef NDEBUG // Verify that the deltas are all non positive. for (const std::vector &ds : deltas) @@ -1203,6 +1247,8 @@ static void variable_offset_inner_raw(const ExPolygon &expoly, const std::vector Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector> &deltas, double miter_limit) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Paths contours, holes; variable_offset_inner_raw(expoly, deltas, miter_limit, contours, holes); @@ -1225,6 +1271,8 @@ Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector> &deltas, double miter_limit) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Paths contours, holes; variable_offset_inner_raw(expoly, deltas, miter_limit, contours, holes); @@ -1251,6 +1299,8 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector> &deltas, double miter_limit, ClipperLib::Paths &contours, ClipperLib::Paths &holes) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + #ifndef NDEBUG // Verify that the deltas are all non positive. for (const std::vector &ds : deltas) @@ -1286,6 +1336,8 @@ static void variable_offset_outer_raw(const ExPolygon &expoly, const std::vector Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector> &deltas, double miter_limit) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Paths contours, holes; variable_offset_outer_raw(expoly, deltas, miter_limit, contours, holes); @@ -1307,6 +1359,8 @@ Polygons variable_offset_outer(const ExPolygon &expoly, const std::vector> &deltas, double miter_limit) { + CLIPPER_UTILS_TIME_LIMIT_MILLIS(CLIPPER_UTILS_TIME_LIMIT_DEFAULT); + ClipperLib::Paths contours, holes; variable_offset_outer_raw(expoly, deltas, miter_limit, contours, holes); diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp index 5f495788b0..aaa06107da 100644 --- a/src/libslic3r/ClipperUtils.hpp +++ b/src/libslic3r/ClipperUtils.hpp @@ -133,21 +133,21 @@ namespace ClipperUtils { const std::vector &m_paths; }; - template + template class MultiPointsProvider { public: - MultiPointsProvider(const std::vector &multipoints) : m_multipoints(multipoints) {} + MultiPointsProvider(const MultiPointsType &multipoints) : m_multipoints(multipoints) {} struct iterator : public PathsProviderIteratorBase { public: - explicit iterator(typename std::vector::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::const_iterator m_it; + typename MultiPointsType::const_iterator m_it; }; iterator cbegin() const { return iterator(m_multipoints.begin()); } @@ -157,11 +157,11 @@ namespace ClipperUtils { size_t size() const { return m_multipoints.size(); } private: - const std::vector &m_multipoints; + const MultiPointsType &m_multipoints; }; - using PolygonsProvider = MultiPointsProvider; - using PolylinesProvider = MultiPointsProvider; + using PolygonsProvider = MultiPointsProvider; + using PolylinesProvider = MultiPointsProvider; struct ExPolygonProvider { ExPolygonProvider(const ExPolygon &expoly) : m_expoly(expoly) {} diff --git a/src/libslic3r/ClipperZUtils.hpp b/src/libslic3r/ClipperZUtils.hpp index 4ae78ae235..001a3f2daa 100644 --- a/src/libslic3r/ClipperZUtils.hpp +++ b/src/libslic3r/ClipperZUtils.hpp @@ -40,7 +40,7 @@ inline ZPath to_zpath(const Points &path, coord_t z) // Convert multiple paths to paths with a given Z coordinate. // If Open, then duplicate the first point of each path at its end. template -inline ZPaths to_zpaths(const std::vector &paths, coord_t z) +inline ZPaths to_zpaths(const VecOfPoints &paths, coord_t z) { ZPaths out; out.reserve(paths.size()); @@ -86,16 +86,16 @@ inline Points from_zpath(const ZPoints &path) // Convert multiple paths to paths with a given Z coordinate. // If Open, then duplicate the first point of each path at its end. template -inline void from_zpaths(const ZPaths &paths, std::vector &out) +inline void from_zpaths(const ZPaths &paths, VecOfPoints &out) { out.reserve(out.size() + paths.size()); for (const ZPoints &path : paths) out.emplace_back(from_zpath(path)); } template -inline std::vector from_zpaths(const ZPaths &paths) +inline VecOfPoints from_zpaths(const ZPaths &paths) { - std::vector out; + VecOfPoints out; from_zpaths(paths, out); return out; } diff --git a/src/libslic3r/EdgeGrid.hpp b/src/libslic3r/EdgeGrid.hpp index 4be2bdd07c..744a23e186 100644 --- a/src/libslic3r/EdgeGrid.hpp +++ b/src/libslic3r/EdgeGrid.hpp @@ -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 &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; } diff --git a/src/libslic3r/ExPolygon.cpp b/src/libslic3r/ExPolygon.cpp index b6d12a6023..42f026e0b2 100644 --- a/src/libslic3r/ExPolygon.cpp +++ b/src/libslic3r/ExPolygon.cpp @@ -397,7 +397,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 allpts; + Points allpts; allpts.reserve(cnt); allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end()); for (const Polygon &hole : expoly.holes) @@ -420,7 +420,7 @@ bool has_duplicate_points(const ExPolygons &expolys) // Check globally. #if 0 // Detect duplicates by sorting with quicksort. It is quite fast, but ankerl::unordered_dense is around 1/4 faster. - std::vector allpts; + Points allpts; allpts.reserve(count_points(expolys)); for (const ExPolygon &expoly : expolys) { allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end()); diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 668c89b079..438465bda5 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -35,12 +35,14 @@ struct ExtendedPoint float curvature; }; -template -std::vector estimate_points_properties(const std::vector

&input_points, +template +std::vector estimate_points_properties(const POINTS &input_points, const AABBTreeLines::LinesDistancer &unscaled_prev_layer, float flow_width, float max_line_length = -1.0f) { + using P = typename POINTS::value_type; + using AABBScalar = typename AABBTreeLines::LinesDistancer::Scalar; if (input_points.empty()) return {}; diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 244a103ca8..3bf1edf39e 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -437,7 +437,7 @@ Polygons extract_perimeter_polygons(const Layer *layer, std::vector; - } - namespace Geometry { // Generic result of an orientation predicate. diff --git a/src/libslic3r/JumpPointSearch.cpp b/src/libslic3r/JumpPointSearch.cpp index dbae42151b..513d84bf82 100644 --- a/src/libslic3r/JumpPointSearch.cpp +++ b/src/libslic3r/JumpPointSearch.cpp @@ -19,6 +19,8 @@ #include #include +#include + //#define DEBUG_FILES #ifdef DEBUG_FILES #include "libslic3r/SVG.hpp" @@ -267,7 +269,7 @@ Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1) using QNode = astar::QNode>; std::unordered_map astar_cache{}; - std::vector out_path; + std::vector> out_path; std::vector out_nodes; if (!astar::search_route(tracer, {start, {0, 0}}, std::back_inserter(out_nodes), astar_cache)) { @@ -306,7 +308,7 @@ Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1) svg.draw(scaled_point(start), "green", scale_(0.4)); #endif - std::vector tmp_path; + std::vector> 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()); diff --git a/src/libslic3r/MultiPoint.cpp b/src/libslic3r/MultiPoint.cpp index f18720bd6f..bb4d62cc0b 100644 --- a/src/libslic3r/MultiPoint.cpp +++ b/src/libslic3r/MultiPoint.cpp @@ -103,9 +103,9 @@ bool MultiPoint::remove_duplicate_points() return false; } -std::vector MultiPoint::_douglas_peucker(const std::vector& pts, const double tolerance) +Points MultiPoint::_douglas_peucker(const Points &pts, const double tolerance) { - std::vector result_pts; + Points result_pts; double tolerance_sq = tolerance * tolerance; if (! pts.empty()) { const Point *anchor = &pts.front(); diff --git a/src/libslic3r/MultiPoint.hpp b/src/libslic3r/MultiPoint.hpp index 778b30c57d..4cf4b5e140 100644 --- a/src/libslic3r/MultiPoint.hpp +++ b/src/libslic3r/MultiPoint.hpp @@ -110,7 +110,7 @@ public: }; extern BoundingBox get_extents(const MultiPoint &mp); -extern BoundingBox get_extents_rotated(const std::vector &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) { diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 89add59783..1a487cba86 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -39,11 +39,11 @@ #include #include #include -#include -#include #include #include +#include + // #define ARACHNE_DEBUG #ifdef ARACHNE_DEBUG @@ -569,7 +569,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::P size_t occurrence = 0; bool is_overhang = false; }; - std::unordered_map point_occurrence; + ankerl::unordered_dense::map point_occurrence; for (const ExtrusionPath &path : paths) { ++point_occurrence[path.polyline.first_point()].occurrence; ++point_occurrence[path.polyline.last_point()].occurrence; @@ -681,7 +681,7 @@ Polylines reconnect_polylines(const Polylines &polylines, double limit_distance) if (polylines.empty()) return polylines; - std::unordered_map connected; + ankerl::unordered_dense::map connected; connected.reserve(polylines.size()); for (size_t i = 0; i < polylines.size(); i++) { if (!polylines[i].empty()) { @@ -731,7 +731,7 @@ ExtrusionPaths sort_extra_perimeters(ExtrusionPaths extra_perims, int index_of_f { if (extra_perims.empty()) return {}; - std::vector> dependencies(extra_perims.size()); + std::vector> dependencies(extra_perims.size()); for (size_t path_idx = 0; path_idx < extra_perims.size(); path_idx++) { for (size_t prev_path_idx = 0; prev_path_idx < path_idx; prev_path_idx++) { if (paths_touch(extra_perims[path_idx], extra_perims[prev_path_idx], extrusion_spacing * 1.5f)) { @@ -1153,11 +1153,11 @@ void PerimeterGenerator::process_arachne( // Find topological order with constraints from extrusions_constrains. std::vector blocked(all_extrusions.size(), 0); // Value indicating how many extrusions it is blocking (preceding extrusions) an extrusion. std::vector> blocking(all_extrusions.size()); // Each extrusion contains a vector of extrusions that are blocked by this extrusion. - std::unordered_map map_extrusion_to_idx; + ankerl::unordered_dense::map map_extrusion_to_idx; for (size_t idx = 0; idx < all_extrusions.size(); idx++) map_extrusion_to_idx.emplace(all_extrusions[idx], idx); - auto extrusions_constrains = Arachne::WallToolPaths::getRegionOrder(all_extrusions, params.config.external_perimeters_first); + Arachne::WallToolPaths::ExtrusionLineSet extrusions_constrains = Arachne::WallToolPaths::getRegionOrder(all_extrusions, params.config.external_perimeters_first); for (auto [before, after] : extrusions_constrains) { auto after_it = map_extrusion_to_idx.find(after); ++blocked[after_it->second]; diff --git a/src/libslic3r/Point.cpp b/src/libslic3r/Point.cpp index 09afcc3993..457bb44cef 100644 --- a/src/libslic3r/Point.cpp +++ b/src/libslic3r/Point.cpp @@ -57,7 +57,7 @@ void Point::rotate(double angle, const Point ¢er) (*this)(1) = (coord_t)round( (double)center(1) + c * dy + s * dx ); } -bool has_duplicate_points(std::vector &&pts) +bool has_duplicate_points(Points &&pts) { std::sort(pts.begin(), pts.end()); for (size_t i = 1; i < pts.size(); ++ i) @@ -97,15 +97,15 @@ template BoundingBox get_extents(const Points &pts); // if IncludeBoundary, then a bounding box is defined even for a single point. // otherwise a bounding box is only defined if it has a positive area. template -BoundingBox get_extents(const std::vector &pts) +BoundingBox get_extents(const VecOfPoints &pts) { BoundingBox bbox; for (const Points &p : pts) bbox.merge(get_extents(p)); return bbox; } -template BoundingBox get_extents(const std::vector &pts); -template BoundingBox get_extents(const std::vector &pts); +template BoundingBox get_extents(const VecOfPoints &pts); +template BoundingBox get_extents(const VecOfPoints &pts); BoundingBoxf get_extents(const std::vector &pts) { diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index d53352f28e..c4b821ca6e 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -9,6 +9,9 @@ #include #include +#include + + #include #include "LocalesUtils.hpp" @@ -49,7 +52,10 @@ using Vec2d = Eigen::Matrix; using Vec3d = Eigen::Matrix; using Vec4d = Eigen::Matrix; -using Points = std::vector; +template +using PointsAllocator = tbb::scalable_allocator; +//using PointsAllocator = std::allocator; +using Points = std::vector>; using PointPtrs = std::vector; using PointConstPtrs = std::vector; using Points3 = std::vector; @@ -57,6 +63,8 @@ using Pointfs = std::vector; using Vec2ds = std::vector; using Pointf3s = std::vector; +using VecOfPoints = std::vector>; + using Matrix2f = Eigen::Matrix; using Matrix2d = Eigen::Matrix; using Matrix3f = Eigen::Matrix; @@ -247,9 +255,9 @@ extern template BoundingBox get_extents(const Points &pts); // if IncludeBoundary, then a bounding box is defined even for a single point. // otherwise a bounding box is only defined if it has a positive area. template -BoundingBox get_extents(const std::vector &pts); -extern template BoundingBox get_extents(const std::vector &pts); -extern template BoundingBox get_extents(const std::vector &pts); +BoundingBox get_extents(const VecOfPoints &pts); +extern template BoundingBox get_extents(const VecOfPoints &pts); +extern template BoundingBox get_extents(const VecOfPoints &pts); BoundingBoxf get_extents(const std::vector &pts); @@ -263,16 +271,16 @@ inline std::pair nearest_point(const Points &points, const Point &p // Test for duplicate points in a vector of points. // The points are copied, sorted and checked for duplicates globally. -bool has_duplicate_points(std::vector &&pts); -inline bool has_duplicate_points(const std::vector &pts) +bool has_duplicate_points(Points &&pts); +inline bool has_duplicate_points(const Points &pts) { - std::vector cpy = pts; + Points cpy = pts; return has_duplicate_points(std::move(cpy)); } // Test for duplicate points in a vector of points. // Only successive points are checked for equality. -inline bool has_duplicate_successive_points(const std::vector &pts) +inline bool has_duplicate_successive_points(const Points &pts) { for (size_t i = 1; i < pts.size(); ++ i) if (pts[i - 1] == pts[i]) @@ -282,7 +290,7 @@ inline bool has_duplicate_successive_points(const std::vector &pts) // Test for duplicate points in a vector of points. // Only successive points are checked for equality. Additionally, first and last points are compared for equality. -inline bool has_duplicate_successive_points_closed(const std::vector &pts) +inline bool has_duplicate_successive_points_closed(const Points &pts) { return has_duplicate_successive_points(pts) || (pts.size() >= 2 && pts.front() == pts.back()); } diff --git a/src/libslic3r/Polygon.cpp b/src/libslic3r/Polygon.cpp index 3be36984c5..299e22adcd 100644 --- a/src/libslic3r/Polygon.cpp +++ b/src/libslic3r/Polygon.cpp @@ -404,7 +404,7 @@ bool has_duplicate_points(const Polygons &polys) // Check globally. #if 0 // Detect duplicates by sorting with quicksort. It is quite fast, but ankerl::unordered_dense is around 1/4 faster. - std::vector allpts; + Points allpts; allpts.reserve(count_points(polys)); for (const Polygon &poly : polys) allpts.insert(allpts.end(), poly.points.begin(), poly.points.end()); diff --git a/src/libslic3r/Polygon.hpp b/src/libslic3r/Polygon.hpp index 3c4bb0e2ad..bf4a087b0d 100644 --- a/src/libslic3r/Polygon.hpp +++ b/src/libslic3r/Polygon.hpp @@ -5,15 +5,16 @@ #include #include #include "Line.hpp" +#include "Point.hpp" #include "MultiPoint.hpp" #include "Polyline.hpp" namespace Slic3r { class Polygon; -using Polygons = std::vector; -using PolygonPtrs = std::vector; -using ConstPolygonPtrs = std::vector; +using Polygons = std::vector>; +using PolygonPtrs = std::vector>; +using ConstPolygonPtrs = std::vector>; // Returns true if inside. Returns border_result if on boundary. bool contains(const Polygon& polygon, const Point& p, bool border_result = true); @@ -241,7 +242,7 @@ inline Polylines to_polylines(Polygons &&polys) return polylines; } -inline Polygons to_polygons(const std::vector &paths) +inline Polygons to_polygons(const VecOfPoints &paths) { Polygons out; out.reserve(paths.size()); @@ -250,7 +251,7 @@ inline Polygons to_polygons(const std::vector &paths) return out; } -inline Polygons to_polygons(std::vector &&paths) +inline Polygons to_polygons(VecOfPoints &&paths) { Polygons out; out.reserve(paths.size()); diff --git a/src/libslic3r/PolygonTrimmer.hpp b/src/libslic3r/PolygonTrimmer.hpp index eddffbc7fa..93e94e303f 100644 --- a/src/libslic3r/PolygonTrimmer.hpp +++ b/src/libslic3r/PolygonTrimmer.hpp @@ -17,7 +17,7 @@ namespace EdgeGrid { struct TrimmedLoop { - std::vector points; + Points points; // Number of points per segment. Empty if the loop is std::vector segments; diff --git a/src/libslic3r/Polyline.hpp b/src/libslic3r/Polyline.hpp index 1b23388e18..8766c6d864 100644 --- a/src/libslic3r/Polyline.hpp +++ b/src/libslic3r/Polyline.hpp @@ -158,8 +158,8 @@ inline void polylines_append(Polylines &dst, Polylines &&src) // src_first: the merge point is at src.begin() or src.end()? // The orientation of the resulting polyline is unknown, the output polyline may start // either with src piece or dst piece. -template -inline void polylines_merge(std::vector &dst, bool dst_first, std::vector &&src, bool src_first) +template +inline void polylines_merge(PointsType &dst, bool dst_first, PointsType &&src, bool src_first) { if (dst_first) { if (src_first) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index b68d04b2b9..49d17e5c0b 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1132,9 +1132,9 @@ Polygons Print::first_layer_islands() const return islands; } -std::vector Print::first_layer_wipe_tower_corners() const +Points Print::first_layer_wipe_tower_corners() const { - std::vector pts_scaled; + Points pts_scaled; if (has_wipe_tower() && ! m_wipe_tower_data.tool_changes.empty()) { double width = m_config.wipe_tower_width + 2*m_wipe_tower_data.brim_width; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index d222fbfe29..30f6bb41a7 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -626,7 +626,7 @@ private: // Islands of objects and their supports extruded at the 1st layer. Polygons first_layer_islands() const; // Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim. - std::vector first_layer_wipe_tower_corners() const; + Points first_layer_wipe_tower_corners() const; // Returns true if any of the print_objects has print_object_step valid. // That means data shared by all print objects of the print_objects span may still use the shared data. diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index ed3813139d..c6329f2e4e 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1992,8 +1992,8 @@ void PrintObject::bridge_over_infill() // reconstruct polygon from polygon sections struct TracedPoly { - std::vector lows; - std::vector highs; + Points lows; + Points highs; }; std::vector current_traced_polys; diff --git a/src/libslic3r/SLA/ConcaveHull.cpp b/src/libslic3r/SLA/ConcaveHull.cpp index 08a2ff676a..f657fce746 100644 --- a/src/libslic3r/SLA/ConcaveHull.cpp +++ b/src/libslic3r/SLA/ConcaveHull.cpp @@ -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(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); }); diff --git a/src/libslic3r/SLA/Pad.hpp b/src/libslic3r/SLA/Pad.hpp index 0b61495572..da09343c49 100644 --- a/src/libslic3r/SLA/Pad.hpp +++ b/src/libslic3r/SLA/Pad.hpp @@ -6,6 +6,8 @@ #include #include +#include + struct indexed_triangle_set; namespace Slic3r { @@ -13,7 +15,7 @@ namespace Slic3r { class ExPolygon; class Polygon; using ExPolygons = std::vector; -using Polygons = std::vector; +using Polygons = std::vector>; namespace sla { diff --git a/src/libslic3r/SLA/SupportTree.hpp b/src/libslic3r/SLA/SupportTree.hpp index 53fb16f6e7..83814d8c59 100644 --- a/src/libslic3r/SLA/SupportTree.hpp +++ b/src/libslic3r/SLA/SupportTree.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -14,9 +15,6 @@ namespace Slic3r { -using Polygons = std::vector; -using ExPolygons = std::vector; - namespace sla { struct SupportTreeConfig diff --git a/src/libslic3r/ShortEdgeCollapse.cpp b/src/libslic3r/ShortEdgeCollapse.cpp index 0c940cb475..c8e4eb97e7 100644 --- a/src/libslic3r/ShortEdgeCollapse.cpp +++ b/src/libslic3r/ShortEdgeCollapse.cpp @@ -6,6 +6,8 @@ #include #include +#include + namespace Slic3r { void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_count) { @@ -155,7 +157,7 @@ void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_ } //Extract the result mesh - std::unordered_map final_vertices_mapping; + ankerl::unordered_dense::map final_vertices_mapping; std::vector final_vertices; std::vector final_indices; final_indices.reserve(face_indices.size()); diff --git a/src/libslic3r/ShortestPath.hpp b/src/libslic3r/ShortestPath.hpp index c84349217e..1781c51889 100644 --- a/src/libslic3r/ShortestPath.hpp +++ b/src/libslic3r/ShortestPath.hpp @@ -8,10 +8,13 @@ #include #include -namespace ClipperLib { class PolyNode; } - namespace Slic3r { + namespace ClipperLib { + class PolyNode; + using PolyNodes = std::vector>; + } + class ExPolygon; using ExPolygons = std::vector; @@ -29,7 +32,7 @@ void chain_and_reorder_extrusion_paths(std::vect Polylines chain_polylines(Polylines &&src, const Point *start_near = nullptr); inline Polylines chain_polylines(const Polylines& src, const Point* start_near = nullptr) { Polylines tmp(src); return chain_polylines(std::move(tmp), start_near); } -std::vector chain_clipper_polynodes(const Points &points, const std::vector &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. diff --git a/src/libslic3r/Timer.cpp b/src/libslic3r/Timer.cpp index b361427a65..91f3b0f09e 100644 --- a/src/libslic3r/Timer.cpp +++ b/src/libslic3r/Timer.cpp @@ -10,3 +10,12 @@ Slic3r::Timer::~Timer() BOOST_LOG_TRIVIAL(debug) << "Timer '" << m_name << "' spend " << duration_cast(steady_clock::now() - m_start).count() << "ms"; } + + +namespace Slic3r::Timing { + +void TimeLimitAlarm::report_time_exceeded() const { + BOOST_LOG_TRIVIAL(error) << "Time limit exceeded for " << m_limit_exceeded_message << ": " << m_timer.elapsed_seconds() << "s"; +} + +} diff --git a/src/libslic3r/Timer.hpp b/src/libslic3r/Timer.hpp index b8f9736a17..f2e5dde1a8 100644 --- a/src/libslic3r/Timer.hpp +++ b/src/libslic3r/Timer.hpp @@ -27,5 +27,66 @@ public: ~Timer(); }; +namespace Timing { + + // Timing code from Catch2 unit testing library + static inline uint64_t nanoseconds_since_epoch() { + return std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + } + + // Timing code from Catch2 unit testing library + class Timer { + public: + void start() { + m_nanoseconds = nanoseconds_since_epoch(); + } + uint64_t elapsed_nanoseconds() const { + return nanoseconds_since_epoch() - m_nanoseconds; + } + uint64_t elapsed_microseconds() const { + return elapsed_nanoseconds() / 1000; + } + unsigned int elapsed_milliseconds() const { + return static_cast(elapsed_microseconds()/1000); + } + double elapsed_seconds() const { + return elapsed_microseconds() / 1000000.0; + } + private: + uint64_t m_nanoseconds = 0; + }; + + // Emits a Boost::log error if the life time of this timing object exceeds a limit. + class TimeLimitAlarm { + public: + TimeLimitAlarm(uint64_t time_limit_nanoseconds, std::string_view limit_exceeded_message) : + m_time_limit_nanoseconds(time_limit_nanoseconds), m_limit_exceeded_message(limit_exceeded_message) { + m_timer.start(); + } + ~TimeLimitAlarm() { + auto elapsed = m_timer.elapsed_nanoseconds(); + if (elapsed > m_time_limit_nanoseconds) + this->report_time_exceeded(); + } + static TimeLimitAlarm new_nanos(uint64_t time_limit_nanoseconds, std::string_view limit_exceeded_message) { + return TimeLimitAlarm(time_limit_nanoseconds, limit_exceeded_message); + } + static TimeLimitAlarm new_milis(uint64_t time_limit_milis, std::string_view limit_exceeded_message) { + return TimeLimitAlarm(uint64_t(time_limit_milis) * 1000000l, limit_exceeded_message); + } + static TimeLimitAlarm new_seconds(uint64_t time_limit_seconds, std::string_view limit_exceeded_message) { + return TimeLimitAlarm(uint64_t(time_limit_seconds) * 1000000000l, limit_exceeded_message); + } + private: + void report_time_exceeded() const; + + Timer m_timer; + uint64_t m_time_limit_nanoseconds; + std::string_view m_limit_exceeded_message; + }; + +} // namespace Catch + } // namespace Slic3r -#endif // libslic3r_Timer_hpp_ \ No newline at end of file + +#endif // libslic3r_Timer_hpp_ diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 856208c9d4..83089fefee 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -106,8 +106,8 @@ enum Axis { NUM_AXES_WITH_UNKNOWN, }; -template -inline void append(std::vector& dest, const std::vector& src) +template +inline void append(std::vector &dest, const std::vector &src) { if (dest.empty()) dest = src; // copy @@ -115,8 +115,8 @@ inline void append(std::vector& dest, const std::vector& src) dest.insert(dest.end(), src.begin(), src.end()); } -template -inline void append(std::vector& dest, std::vector&& src) +template +inline void append(std::vector &dest, std::vector &&src) { if (dest.empty()) dest = std::move(src); diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index ef4ab6d474..fbf6ed5334 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -14,7 +14,7 @@ namespace Slic3r { class TriangleMesh; class Polygon; -using Polygons = std::vector; +using Polygons = std::vector>; class BuildVolume; namespace GUI { diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 2828fc8003..d7c01c3686 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -183,7 +183,8 @@ static void update_arrangepoly_slaprint(arrangement::ArrangePolygon &ret, trafo_instance = trafo_instance * po.trafo().cast().inverse(); - auto polys = reserve_vector(3); + Polygons polys; + polys.reserve(3); auto zlvl = -po.get_elevation(); if (omesh) { diff --git a/tests/libnest2d/CMakeLists.txt b/tests/libnest2d/CMakeLists.txt index ea4f4255ed..8dabc688d3 100644 --- a/tests/libnest2d/CMakeLists.txt +++ b/tests/libnest2d/CMakeLists.txt @@ -2,7 +2,7 @@ get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME) add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp printer_parts.cpp printer_parts.hpp) # mold linker for successful linking needs also to link TBB library and link it before libslic3r. -target_link_libraries(${_TEST_NAME}_tests test_common TBB::tbb libnest2d ) +target_link_libraries(${_TEST_NAME}_tests test_common TBB::tbb TBB::tbbmalloc libnest2d ) set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests") # catch_discover_tests(${_TEST_NAME}_tests TEST_PREFIX "${_TEST_NAME}: ") diff --git a/tests/libslic3r/test_clipper_utils.cpp b/tests/libslic3r/test_clipper_utils.cpp index 775796ba7e..1f3bc0fdca 100644 --- a/tests/libslic3r/test_clipper_utils.cpp +++ b/tests/libslic3r/test_clipper_utils.cpp @@ -308,8 +308,8 @@ SCENARIO("Various Clipper operations - t/clipper.t", "[ClipperUtils]") { } } -template -double polytree_area(const Tree &tree, std::vector

*out) +template +double polytree_area(const Tree &tree, std::vector *out) { traverse_pt(tree, out); diff --git a/tests/libslic3r/test_geometry.cpp b/tests/libslic3r/test_geometry.cpp index 239edd4f74..16a27665e8 100644 --- a/tests/libslic3r/test_geometry.cpp +++ b/tests/libslic3r/test_geometry.cpp @@ -83,7 +83,7 @@ TEST_CASE("Line::perpendicular_to", "[Geometry]") { TEST_CASE("Polygon::contains works properly", "[Geometry]"){ // this test was failing on Windows (GH #1950) - Slic3r::Polygon polygon(std::vector({ + Slic3r::Polygon polygon(Points({ Point(207802834,-57084522), Point(196528149,-37556190), Point(173626821,-25420928), @@ -145,7 +145,7 @@ SCENARIO("polygon_is_convex works") { TEST_CASE("Creating a polyline generates the obvious lines", "[Geometry]"){ Slic3r::Polyline polyline; - polyline.points = std::vector({Point(0, 0), Point(10, 0), Point(20, 0)}); + polyline.points = Points({Point(0, 0), Point(10, 0), Point(20, 0)}); REQUIRE(polyline.lines().at(0).a == Point(0,0)); REQUIRE(polyline.lines().at(0).b == Point(10,0)); REQUIRE(polyline.lines().at(1).a == Point(10,0)); @@ -153,7 +153,7 @@ TEST_CASE("Creating a polyline generates the obvious lines", "[Geometry]"){ } TEST_CASE("Splitting a Polygon generates a polyline correctly", "[Geometry]"){ - Slic3r::Polygon polygon(std::vector({Point(0, 0), Point(10, 0), Point(5, 5)})); + Slic3r::Polygon polygon(Points({Point(0, 0), Point(10, 0), Point(5, 5)})); Slic3r::Polyline split = polygon.split_at_index(1); REQUIRE(split.points[0]==Point(10,0)); REQUIRE(split.points[1]==Point(5,5)); @@ -164,7 +164,7 @@ TEST_CASE("Splitting a Polygon generates a polyline correctly", "[Geometry]"){ SCENARIO("BoundingBox", "[Geometry]") { WHEN("Bounding boxes are scaled") { - BoundingBox bb(std::vector({Point(0, 1), Point(10, 2), Point(20, 2)})); + BoundingBox bb(Points({Point(0, 1), Point(10, 2), Point(20, 2)})); bb.scale(2); REQUIRE(bb.min == Point(0,2)); REQUIRE(bb.max == Point(40,4)); @@ -193,7 +193,7 @@ SCENARIO("BoundingBox", "[Geometry]") { TEST_CASE("Offseting a line generates a polygon correctly", "[Geometry]"){ Slic3r::Polyline tmp = { Point(10,10), Point(20,10) }; Slic3r::Polygon area = offset(tmp,5).at(0); - REQUIRE(area.area() == Slic3r::Polygon(std::vector({Point(10,5),Point(20,5),Point(20,15),Point(10,15)})).area()); + REQUIRE(area.area() == Slic3r::Polygon(Points({Point(10,5),Point(20,5),Point(20,15),Point(10,15)})).area()); } SCENARIO("Circle Fit, TaubinFit with Newton's method", "[Geometry]") { @@ -308,7 +308,7 @@ TEST_CASE("smallest_enclosing_circle_welzl", "[Geometry]") { SCENARIO("Path chaining", "[Geometry]") { GIVEN("A path") { - std::vector points = { Point(26,26),Point(52,26),Point(0,26),Point(26,52),Point(26,0),Point(0,52),Point(52,52),Point(52,0) }; + Points points = { Point(26,26),Point(52,26),Point(0,26),Point(26,52),Point(26,0),Point(0,52),Point(52,52),Point(52,0) }; THEN("Chained with no diagonals (thus 26 units long)") { std::vector indices = chain_points(points); for (Points::size_type i = 0; i + 1 < indices.size(); ++ i) { @@ -431,7 +431,7 @@ SCENARIO("Calculating angles", "[Geometry]") SCENARIO("Polygon convex/concave detection", "[Geometry]"){ static constexpr const double angle_threshold = M_PI / 3.; GIVEN(("A Square with dimension 100")){ - auto square = Slic3r::Polygon /*new_scale*/(std::vector({ + auto square = Slic3r::Polygon /*new_scale*/(Points({ Point(100,100), Point(200,100), Point(200,200), @@ -447,7 +447,7 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){ } } GIVEN("A Square with an extra colinearvertex"){ - auto square = Slic3r::Polygon /*new_scale*/(std::vector({ + auto square = Slic3r::Polygon /*new_scale*/(Points({ Point(150,100), Point(200,100), Point(200,200), @@ -459,7 +459,7 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){ } } GIVEN("A Square with an extra collinear vertex in different order"){ - auto square = Slic3r::Polygon /*new_scale*/(std::vector({ + auto square = Slic3r::Polygon /*new_scale*/(Points({ Point(200,200), Point(100,200), Point(100,100), @@ -472,7 +472,7 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){ } GIVEN("A triangle"){ - auto triangle = Slic3r::Polygon(std::vector({ + auto triangle = Slic3r::Polygon(Points({ Point(16000170,26257364), Point(714223,461012), Point(31286371,461008) @@ -484,7 +484,7 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){ } GIVEN("A triangle with an extra collinear point"){ - auto triangle = Slic3r::Polygon(std::vector({ + auto triangle = Slic3r::Polygon(Points({ Point(16000170,26257364), Point(714223,461012), Point(20000000,461012), @@ -498,7 +498,7 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){ GIVEN("A polygon with concave vertices with angles of specifically 4/3pi"){ // Two concave vertices of this polygon have angle = PI*4/3, so this test fails // if epsilon is not used. - auto polygon = Slic3r::Polygon(std::vector({ + auto polygon = Slic3r::Polygon(Points({ Point(60246458,14802768),Point(64477191,12360001), Point(63727343,11060995),Point(64086449,10853608), Point(66393722,14850069),Point(66034704,15057334), @@ -516,7 +516,7 @@ SCENARIO("Polygon convex/concave detection", "[Geometry]"){ } TEST_CASE("Triangle Simplification does not result in less than 3 points", "[Geometry]"){ - auto triangle = Slic3r::Polygon(std::vector({ + auto triangle = Slic3r::Polygon(Points({ Point(16000170,26257364), Point(714223,461012), Point(31286371,461008) })); REQUIRE(triangle.simplify(250000).at(0).points.size() == 3); diff --git a/tests/sla_print/CMakeLists.txt b/tests/sla_print/CMakeLists.txt index 2a800cc50e..3a5d96c7ac 100644 --- a/tests/sla_print/CMakeLists.txt +++ b/tests/sla_print/CMakeLists.txt @@ -8,7 +8,7 @@ add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp sla_archive_readwrite_tests.cpp) # mold linker for successful linking needs also to link TBB library and link it before libslic3r. -target_link_libraries(${_TEST_NAME}_tests test_common TBB::tbb libslic3r) +target_link_libraries(${_TEST_NAME}_tests test_common TBB::tbb TBB::tbbmalloc libslic3r) set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests") if (WIN32) diff --git a/tests/slic3rutils/CMakeLists.txt b/tests/slic3rutils/CMakeLists.txt index 892e7a8a76..7c83fb8d75 100644 --- a/tests/slic3rutils/CMakeLists.txt +++ b/tests/slic3rutils/CMakeLists.txt @@ -6,7 +6,7 @@ add_executable(${_TEST_NAME}_tests ) # mold linker for successful linking needs also to link TBB library and link it before libslic3r. -target_link_libraries(${_TEST_NAME}_tests test_common TBB::tbb libslic3r_gui libslic3r) +target_link_libraries(${_TEST_NAME}_tests test_common TBB::tbb TBB::tbbmalloc libslic3r_gui libslic3r) if (MSVC) target_link_libraries(${_TEST_NAME}_tests Setupapi.lib) endif () diff --git a/xs/src/xsinit.h b/xs/src/xsinit.h index 19e25c54d1..dcf56a6d49 100644 --- a/xs/src/xsinit.h +++ b/xs/src/xsinit.h @@ -77,6 +77,7 @@ #undef accept #undef wait #undef abort + #undef pause // Breaks compilation with Eigen matrices embedded into Slic3r::Point. #undef malloc