Clipper / ClipperUtils:
1) Let Clipper use int32_t for representing its coordinates. This reduces memory and allows to skip conversion between Slic3r Polygon and Clipper polygon. 2) Disable additional offset before executing the Clipper Offset algorithm. We don't see any reason for that and it required 64bit Clipper coordinates, which were disabled with 1).
This commit is contained in:
parent
dbd1c09523
commit
e8643125d8
5 changed files with 155 additions and 41 deletions
|
@ -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);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in a new issue