diff --git a/src/clipper/clipper.cpp b/src/clipper/clipper.cpp index 3c0057b22..cbe54a064 100644 --- a/src/clipper/clipper.cpp +++ b/src/clipper/clipper.cpp @@ -287,6 +287,11 @@ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) } //---------------------------------------------------------------------- +#ifdef CLIPPERLIB_INT32 +inline bool SlopesEqual(const cInt dx1, const cInt dy1, const cInt dx2, const cInt dy2, bool /* UseFullInt64Range */) { + return int64_t(dy1) * int64_t(dx2) == int64_t(dx1) * int64_t(dy2); +} +#else inline bool SlopesEqual(const cInt dx1, const cInt dy1, const cInt dx2, const cInt dy2, bool UseFullInt64Range) { return (UseFullInt64Range) ? // |dx1| < 2^63, |dx2| < 2^63 etc, @@ -296,6 +301,8 @@ inline bool SlopesEqual(const cInt dx1, const cInt dy1, const cInt dx2, const cI // therefore the following computation could be done with 64bit arithmetics. dy1 * dx2 == dx1 * dy2; } +#endif + inline bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range) { return SlopesEqual(e1.Delta.X, e1.Delta.Y, e2.Delta.X, e2.Delta.Y, UseFullInt64Range); } inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2, const IntPoint &pt3, bool UseFullInt64Range) @@ -363,8 +370,8 @@ void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip) } else { - b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; - b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; + b1 = double(Edge1.Bot.X) - double(Edge1.Bot.Y) * Edge1.Dx; + b2 = double(Edge2.Bot.X) - double(Edge2.Bot.Y) * Edge2.Dx; double q = (b2-b1) / (Edge1.Dx - Edge2.Dx); ip.Y = Round(q); ip.X = (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) ? @@ -569,6 +576,7 @@ bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b) // ClipperBase class methods ... //------------------------------------------------------------------------------ +#ifndef CLIPPERLIB_INT32 // Called from ClipperBase::AddPath() to verify the scale of the input polygon coordinates. inline void RangeTest(const IntPoint& Pt, bool& useFullRange) { @@ -583,6 +591,7 @@ inline void RangeTest(const IntPoint& Pt, bool& useFullRange) RangeTest(Pt, useFullRange); } } +#endif // CLIPPERLIB_INT32 //------------------------------------------------------------------------------ // Called from ClipperBase::AddPath() to construct the Local Minima List. @@ -805,13 +814,17 @@ bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, b try { edges[1].Curr = pg[1]; +#ifndef CLIPPERLIB_INT32 RangeTest(pg[0], m_UseFullRange); RangeTest(pg[highI], m_UseFullRange); +#endif // CLIPPERLIB_INT32 InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]); for (int i = highI - 1; i >= 1; --i) { +#ifndef CLIPPERLIB_INT32 RangeTest(pg[i], m_UseFullRange); +#endif // CLIPPERLIB_INT32 InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]); } } @@ -967,7 +980,9 @@ void ClipperBase::Clear() CLIPPERLIB_PROFILE_FUNC(); m_MinimaList.clear(); m_edges.clear(); +#ifndef CLIPPERLIB_INT32 m_UseFullRange = false; +#endif // CLIPPERLIB_INT32 m_HasOpenPaths = false; } //------------------------------------------------------------------------------ @@ -3322,9 +3337,9 @@ DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) if(pt2.X == pt1.X && pt2.Y == pt1.Y) return DoublePoint(0, 0); - double Dx = (double)(pt2.X - pt1.X); - double dy = (double)(pt2.Y - pt1.Y); - double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy ); + double Dx = double(pt2.X - pt1.X); + double dy = double(pt2.Y - pt1.Y); + double f = 1.0 / std::sqrt( Dx*Dx + dy*dy ); Dx *= f; dy *= f; return DoublePoint(dy, -Dx); @@ -3530,8 +3545,9 @@ void ClipperOffset::DoOffset(double delta) } //see offset_triginometry3.svg in the documentation folder ... - if (MiterLimit > 2) m_miterLim = 2/(MiterLimit * MiterLimit); - else m_miterLim = 0.5; + m_miterLim = (MiterLimit > 2) ? + 2. / (MiterLimit * MiterLimit) : + 0.5; double y; if (ArcTolerance <= 0.0) y = def_arc_tolerance; @@ -3633,11 +3649,9 @@ void ClipperOffset::DoOffset(double delta) if (node.m_endtype == etOpenButt) { int j = len - 1; - pt1 = IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * - delta), Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); + pt1 = IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * delta), Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); m_destPoly.push_back(pt1); - pt1 = IntPoint(Round(m_srcPoly[j].X - m_normals[j].X * - delta), Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); + pt1 = IntPoint(Round(m_srcPoly[j].X - m_normals[j].X * delta), Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); m_destPoly.push_back(pt1); } else @@ -3662,11 +3676,9 @@ void ClipperOffset::DoOffset(double delta) if (node.m_endtype == etOpenButt) { - pt1 = IntPoint(Round(m_srcPoly[0].X - m_normals[0].X * delta), - Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); + pt1 = IntPoint(Round(m_srcPoly[0].X - m_normals[0].X * delta), Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); m_destPoly.push_back(pt1); - pt1 = IntPoint(Round(m_srcPoly[0].X + m_normals[0].X * delta), - Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); + pt1 = IntPoint(Round(m_srcPoly[0].X + m_normals[0].X * delta), Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); m_destPoly.push_back(pt1); } else @@ -3753,7 +3765,7 @@ void ClipperOffset::DoRound(int j, int k) { double a = std::atan2(m_sinA, m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); - int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1); + auto steps = std::max<int>(Round(m_StepsPerRad * std::fabs(a)), 1); double X = m_normals[k].X, Y = m_normals[k].Y, X2; for (int i = 0; i < steps; ++i) @@ -3885,8 +3897,8 @@ void SimplifyPolygons(Paths &polys, PolyFillType fillType) inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2) { - double Dx = ((double)pt1.X - pt2.X); - double dy = ((double)pt1.Y - pt2.Y); + auto Dx = double(pt1.X - pt2.X); + auto dy = double(pt1.Y - pt2.Y); return (Dx*Dx + dy*dy); } //------------------------------------------------------------------------------ @@ -3937,8 +3949,8 @@ bool SlopesNearCollinear(const IntPoint& pt1, bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) { - double Dx = (double)pt1.X - pt2.X; - double dy = (double)pt1.Y - pt2.Y; + auto Dx = double(pt1.X - pt2.X); + auto dy = double(pt1.Y - pt2.Y); return ((Dx * Dx) + (dy * dy) <= distSqrd); } //------------------------------------------------------------------------------ diff --git a/src/clipper/clipper.hpp b/src/clipper/clipper.hpp index 8b34779e3..48e83d046 100644 --- a/src/clipper/clipper.hpp +++ b/src/clipper/clipper.hpp @@ -71,12 +71,22 @@ enum PolyType { ptSubject, ptClip }; //see http://glprogramming.com/red/chapter11.html enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; +// If defined, Clipper will work with 32bit signed int coordinates to reduce memory +// consumption and to speed up exact orientation predicate calculation. +// In that case, coordinates and their differences (vectors of the coordinates) have to fit int32_t. +#define CLIPPERLIB_INT32 + // Point coordinate type -typedef int64_t cInt; -// Maximum cInt value to allow a cross product calculation using 32bit expressions. -static cInt const loRange = 0x3FFFFFFF; -// Maximum allowed cInt value. -static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; +#ifdef CLIPPERLIB_INT32 + // Coordinates and their differences (vectors of the coordinates) have to fit int32_t. + typedef int32_t cInt; +#else + typedef int64_t cInt; + // Maximum cInt value to allow a cross product calculation using 32bit expressions. + static constexpr cInt const loRange = 0x3FFFFFFF; // 0x3FFFFFFF = 1 073 741 823 + // Maximum allowed cInt value. + static constexpr cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; +#endif // CLIPPERLIB_INT32 struct IntPoint { cInt X; @@ -289,7 +299,11 @@ enum EdgeSide { esLeft = 1, esRight = 2}; class ClipperBase { public: - ClipperBase() : m_UseFullRange(false), m_HasOpenPaths(false) {} + ClipperBase() : +#ifndef CLIPPERLIB_INT32 + m_UseFullRange(false), +#endif // CLIPPERLIB_INT32 + m_HasOpenPaths(false) {} ~ClipperBase() { Clear(); } bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); @@ -310,9 +324,14 @@ protected: // Local minima (Y, left edge, right edge) sorted by ascending Y. std::vector<LocalMinimum> m_MinimaList; +#ifdef CLIPPERLIB_INT32 + static constexpr const bool m_UseFullRange = false; +#else // CLIPPERLIB_INT32 // True if the input polygons have abs values higher than loRange, but lower than hiRange. // False if the input polygons have abs values lower or equal to loRange. bool m_UseFullRange; +#endif // CLIPPERLIB_INT32 + // A vector of edges per each input path. std::vector<std::vector<TEdge>> m_edges; // Don't remove intermediate vertices of a collinear sequence of points. diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp index 305ea134f..cd243dfb1 100644 --- a/src/libslic3r/ClipperUtils.cpp +++ b/src/libslic3r/ClipperUtils.cpp @@ -57,6 +57,7 @@ err: } #endif /* CLIPPER_UTILS_DEBUG */ +#ifdef CLIPPERUTILS_OFFSET_SCALE void scaleClipperPolygon(ClipperLib::Path &polygon) { CLIPPERUTILS_PROFILE_FUNC(); @@ -98,6 +99,7 @@ void unscaleClipperPolygons(ClipperLib::Paths &polygons) pit->Y >>= CLIPPER_OFFSET_POWER_OF_2; } } +#endif // CLIPPERUTILS_OFFSET_SCALE //----------------------------------------------------------- // legacy code from Clipper documentation @@ -222,8 +224,10 @@ ClipperLib::Paths Slic3rMultiPoints_to_ClipperPaths(const Polylines &input) ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType, const float delta, ClipperLib::JoinType joinType, double miterLimit) { +#ifdef CLIPPERUTILS_OFFSET_SCALE // scale input scaleClipperPolygons(input); +#endif // CLIPPERUTILS_OFFSET_SCALE // perform offset ClipperLib::ClipperOffset co; @@ -231,14 +235,20 @@ ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType co.ArcTolerance = miterLimit; else co.MiterLimit = miterLimit; +#ifdef CLIPPERUTILS_OFFSET_SCALE float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE); +#else // CLIPPERUTILS_OFFSET_SCALE + float delta_scaled = delta; +#endif // CLIPPERUTILS_OFFSET_SCALE co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR)); co.AddPaths(input, joinType, endType); ClipperLib::Paths retval; co.Execute(retval, delta_scaled); +#ifdef CLIPPERUTILS_OFFSET_SCALE // unscale output unscaleClipperPolygons(retval); +#endif // CLIPPERUTILS_OFFSET_SCALE return retval; } @@ -257,14 +267,24 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, { // printf("new ExPolygon offset\n"); // 1) Offset the outer contour. - const float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE); +#ifdef CLIPPERUTILS_OFFSET_SCALE + float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE); +#else // CLIPPERUTILS_OFFSET_SCALE + float delta_scaled = delta; +#endif // CLIPPERUTILS_OFFSET_SCALE ClipperLib::Paths contours; { ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(expolygon.contour); +#ifdef CLIPPERUTILS_OFFSET_SCALE scaleClipperPolygon(input); +#endif // CLIPPERUTILS_OFFSET_SCALE ClipperLib::ClipperOffset co; if (joinType == jtRound) +#ifdef CLIPPERUTILS_OFFSET_SCALE co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE); +#else // CLIPPERUTILS_OFFSET_SCALE + co.ArcTolerance = miterLimit; +#endif // CLIPPERUTILS_OFFSET_SCALE else co.MiterLimit = miterLimit; co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR)); @@ -278,17 +298,23 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, holes.reserve(expolygon.holes.size()); for (Polygons::const_iterator it_hole = expolygon.holes.begin(); it_hole != expolygon.holes.end(); ++ it_hole) { ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole); +#ifdef CLIPPERUTILS_OFFSET_SCALE scaleClipperPolygon(input); +#endif // CLIPPERUTILS_OFFSET_SCALE ClipperLib::ClipperOffset co; if (joinType == jtRound) +#ifdef CLIPPERUTILS_OFFSET_SCALE co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE); +#else // CLIPPERUTILS_OFFSET_SCALE + co.ArcTolerance = miterLimit; +#endif // CLIPPERUTILS_OFFSET_SCALE else co.MiterLimit = miterLimit; co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR)); co.AddPath(input, joinType, ClipperLib::etClosedPolygon); ClipperLib::Paths out; co.Execute(out, - delta_scaled); - holes.insert(holes.end(), out.begin(), out.end()); + append(holes, std::move(out)); } } @@ -305,7 +331,9 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, } // 4) Unscale the output. +#ifdef CLIPPERUTILS_OFFSET_SCALE unscaleClipperPolygons(output); +#endif // CLIPPERUTILS_OFFSET_SCALE return output; } @@ -315,7 +343,11 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta, ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delta, ClipperLib::JoinType joinType, double miterLimit) { - const float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE); +#ifdef CLIPPERUTILS_OFFSET_SCALE + float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE); +#else // CLIPPERUTILS_OFFSET_SCALE + float delta_scaled = delta; +#endif // CLIPPERUTILS_OFFSET_SCALE // Offsetted ExPolygons before they are united. ClipperLib::Paths contours_cummulative; contours_cummulative.reserve(expolygons.size()); @@ -327,10 +359,16 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt ClipperLib::Paths contours; { ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath(it_expoly->contour); +#ifdef CLIPPERUTILS_OFFSET_SCALE scaleClipperPolygon(input); +#endif // CLIPPERUTILS_OFFSET_SCALE ClipperLib::ClipperOffset co; if (joinType == jtRound) +#ifdef CLIPPERUTILS_OFFSET_SCALE co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE); +#else // CLIPPERUTILS_OFFSET_SCALE + co.ArcTolerance = miterLimit; +#endif // CLIPPERUTILS_OFFSET_SCALE else co.MiterLimit = miterLimit; co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR)); @@ -351,10 +389,16 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt { for (Polygons::const_iterator it_hole = it_expoly->holes.begin(); it_hole != it_expoly->holes.end(); ++ it_hole) { ClipperLib::Path input = Slic3rMultiPoint_to_ClipperPath_reversed(*it_hole); +#ifdef CLIPPERUTILS_OFFSET_SCALE scaleClipperPolygon(input); +#endif // CLIPPERUTILS_OFFSET_SCALE ClipperLib::ClipperOffset co; if (joinType == jtRound) +#ifdef CLIPPERUTILS_OFFSET_SCALE co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE); +#else // CLIPPERUTILS_OFFSET_SCALE + co.ArcTolerance = miterLimit; +#endif // CLIPPERUTILS_OFFSET_SCALE else co.MiterLimit = miterLimit; co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR)); @@ -413,8 +457,10 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt output = std::move(contours_cummulative); } +#ifdef CLIPPERUTILS_OFFSET_SCALE // 4) Unscale the output. unscaleClipperPolygons(output); +#endif // CLIPPERUTILS_OFFSET_SCALE return output; } @@ -425,8 +471,10 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2, // read input ClipperLib::Paths input = Slic3rMultiPoints_to_ClipperPaths(polygons); +#ifdef CLIPPERUTILS_OFFSET_SCALE // scale input scaleClipperPolygons(input); +#endif // CLIPPERUTILS_OFFSET_SCALE // prepare ClipperOffset object ClipperLib::ClipperOffset co; @@ -435,8 +483,13 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2, } else { co.MiterLimit = miterLimit; } +#ifdef CLIPPERUTILS_OFFSET_SCALE float delta_scaled1 = delta1 * float(CLIPPER_OFFSET_SCALE); float delta_scaled2 = delta2 * float(CLIPPER_OFFSET_SCALE); +#else // CLIPPERUTILS_OFFSET_SCALE + float delta_scaled1 = delta1; + float delta_scaled2 = delta2; +#endif // CLIPPERUTILS_OFFSET_SCALE co.ShortestEdgeLength = double(std::max(std::abs(delta_scaled1), std::abs(delta_scaled2)) * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR); // perform first offset @@ -450,8 +503,10 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2, ClipperLib::Paths retval; co.Execute(retval, delta_scaled2); +#ifdef CLIPPERUTILS_OFFSET_SCALE // unscale output unscaleClipperPolygons(retval); +#endif // CLIPPERUTILS_OFFSET_SCALE return retval; } @@ -789,8 +844,10 @@ void safety_offset(ClipperLib::Paths* paths) { CLIPPERUTILS_PROFILE_FUNC(); +#ifdef CLIPPERUTILS_OFFSET_SCALE // scale input scaleClipperPolygons(*paths); +#endif // CLIPPERUTILS_OFFSET_SCALE // perform offset (delta = scale 1e-05) ClipperLib::ClipperOffset co; @@ -816,7 +873,11 @@ void safety_offset(ClipperLib::Paths* paths) CLIPPERUTILS_PROFILE_BLOCK(safety_offset_Execute); // offset outside by 10um ClipperLib::Paths out_this; +#ifdef CLIPPERUTILS_OFFSET_SCALE co.Execute(out_this, ccw ? 10.f * float(CLIPPER_OFFSET_SCALE) : -10.f * float(CLIPPER_OFFSET_SCALE)); +#else // CLIPPERUTILS_OFFSET_SCALE + co.Execute(out_this, ccw ? 10.f : -10.f); +#endif // CLIPPERUTILS_OFFSET_SCALE if (! ccw) { // Reverse the resulting contours once again. for (ClipperLib::Paths::iterator it = out_this.begin(); it != out_this.end(); ++ it) @@ -830,8 +891,10 @@ void safety_offset(ClipperLib::Paths* paths) } *paths = std::move(out); +#ifdef CLIPPERUTILS_OFFSET_SCALE // unscale output unscaleClipperPolygons(*paths); +#endif // CLIPPERUTILS_OFFSET_SCALE } Polygons top_level_islands(const Slic3r::Polygons &polygons) @@ -925,8 +988,10 @@ ClipperLib::Path mittered_offset_path_scaled(const Points &contour, const std::v // Add a new point to the output, scale by CLIPPER_OFFSET_SCALE and round to ClipperLib::cInt. auto add_offset_point = [&out](Vec2d pt) { +#ifdef CLIPPERUTILS_OFFSET_SCALE pt *= double(CLIPPER_OFFSET_SCALE); - pt += Vec2d(0.5 - (pt.x() < 0), 0.5 - (pt.y() < 0)); +#endif // CLIPPERUTILS_OFFSET_SCALE + pt += Vec2d(0.5 - (pt.x() < 0), 0.5 - (pt.y() < 0)); out.emplace_back(ClipperLib::cInt(pt.x()), ClipperLib::cInt(pt.y())); }; @@ -1075,8 +1140,10 @@ Polygons variable_offset_inner(const ExPolygon &expoly, const std::vector<std::v clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero); } +#ifdef CLIPPERUTILS_OFFSET_SCALE // 4) Unscale the output. unscaleClipperPolygons(output); +#endif // CLIPPERUTILS_OFFSET_SCALE return ClipperPaths_to_Slic3rPolygons(output); } @@ -1119,8 +1186,10 @@ for (const std::vector<float>& ds : deltas) clipper.Execute(ClipperLib::ctDifference, output, ClipperLib::pftNonZero, ClipperLib::pftNonZero); } +#ifdef CLIPPERUTILS_OFFSET_SCALE // 4) Unscale the output. unscaleClipperPolygons(output); +#endif // CLIPPERUTILS_OFFSET_SCALE return ClipperPaths_to_Slic3rPolygons(output); } @@ -1152,7 +1221,9 @@ for (const std::vector<float>& ds : deltas) #endif /* NDEBUG */ // 3) Subtract holes from the contours. +#ifdef CLIPPERUTILS_OFFSET_SCALE unscaleClipperPolygons(contours); +#endif // CLIPPERUTILS_OFFSET_SCALE ExPolygons output; if (holes.empty()) { output.reserve(contours.size()); @@ -1160,7 +1231,9 @@ for (const std::vector<float>& ds : deltas) output.emplace_back(ClipperPath_to_Slic3rPolygon(path)); } else { ClipperLib::Clipper clipper; +#ifdef CLIPPERUTILS_OFFSET_SCALE unscaleClipperPolygons(holes); +#endif // CLIPPERUTILS_OFFSET_SCALE clipper.AddPaths(contours, ClipperLib::ptSubject, true); clipper.AddPaths(holes, ClipperLib::ptClip, true); ClipperLib::PolyTree polytree; @@ -1200,7 +1273,9 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s #endif /* NDEBUG */ // 3) Subtract holes from the contours. +#ifdef CLIPPERUTILS_OFFSET_SCALE unscaleClipperPolygons(contours); +#endif // CLIPPERUTILS_OFFSET_SCALE ExPolygons output; if (holes.empty()) { output.reserve(contours.size()); @@ -1208,7 +1283,9 @@ ExPolygons variable_offset_inner_ex(const ExPolygon &expoly, const std::vector<s output.emplace_back(ClipperPath_to_Slic3rPolygon(path)); } else { ClipperLib::Clipper clipper; +#ifdef CLIPPERUTILS_OFFSET_SCALE unscaleClipperPolygons(holes); +#endif // CLIPPERUTILS_OFFSET_SCALE clipper.AddPaths(contours, ClipperLib::ptSubject, true); clipper.AddPaths(holes, ClipperLib::ptClip, true); ClipperLib::PolyTree polytree; diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp index cd966435b..c1b887583 100644 --- a/src/libslic3r/ClipperUtils.hpp +++ b/src/libslic3r/ClipperUtils.hpp @@ -12,17 +12,21 @@ using ClipperLib::jtMiter; using ClipperLib::jtRound; using ClipperLib::jtSquare; -// Factor to convert from coord_t (which is int32) to an int64 type used by the Clipper library -// for general offsetting (the offset(), offset2(), offset_ex() functions) and for the safety offset, -// which is optionally executed by other functions (union, intersection, diff). -// This scaling (cca 130t) is applied over the usual SCALING_FACTOR. -// By the way, is the scalling for offset needed at all? -// The reason to apply this scaling may be to match the resolution of the double mantissa. -#define CLIPPER_OFFSET_POWER_OF_2 17 -// 2^17=131072 -#define CLIPPER_OFFSET_SCALE (1 << CLIPPER_OFFSET_POWER_OF_2) -#define CLIPPER_OFFSET_SCALE_ROUNDING_DELTA ((1 << (CLIPPER_OFFSET_POWER_OF_2 - 1)) - 1) -#define CLIPPER_MAX_COORD_UNSCALED (ClipperLib::hiRange / CLIPPER_OFFSET_SCALE) +// #define CLIPPERUTILS_OFFSET_SCALE + +#ifdef CLIPPERUTILS_OFFSET_SCALE + // Factor to convert from coord_t (which is int32) to an int64 type used by the Clipper library + // for general offsetting (the offset(), offset2(), offset_ex() functions) and for the safety offset, + // which is optionally executed by other functions (union, intersection, diff). + // This scaling (cca 130t) is applied over the usual SCALING_FACTOR. + // By the way, is the scalling for offset needed at all? + // The reason to apply this scaling may be to match the resolution of the double mantissa. + #define CLIPPER_OFFSET_POWER_OF_2 17 + // 2^17=131072 + #define CLIPPER_OFFSET_SCALE (1 << CLIPPER_OFFSET_POWER_OF_2) + #define CLIPPER_OFFSET_SCALE_ROUNDING_DELTA ((1 << (CLIPPER_OFFSET_POWER_OF_2 - 1)) - 1) + #define CLIPPER_MAX_COORD_UNSCALED (ClipperLib::hiRange / CLIPPER_OFFSET_SCALE) +#endif // CLIPPERUTILS_OFFSET_SCALE namespace Slic3r { diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index aac7c7752..d5ef41125 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1087,11 +1087,13 @@ bool MedialAxis::validate_edge(const VD::edge_type* edge) { // prevent overflows and detect almost-infinite edges +#ifndef CLIPPERLIB_INT32 if (std::abs(edge->vertex0()->x()) > double(CLIPPER_MAX_COORD_UNSCALED) || std::abs(edge->vertex0()->y()) > double(CLIPPER_MAX_COORD_UNSCALED) || std::abs(edge->vertex1()->x()) > double(CLIPPER_MAX_COORD_UNSCALED) || std::abs(edge->vertex1()->y()) > double(CLIPPER_MAX_COORD_UNSCALED)) return false; +#endif // CLIPPERLIB_INT32 // construct the line representing this edge of the Voronoi diagram const Line line(