mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-07-26 10:14:28 +08:00
Fix clipper::union adding extremely small holes even with safety_offset
It check that all polygons are all thicker than scaled_epsilon
This commit is contained in:
parent
b6a98377ae
commit
42a0c31cb2
@ -162,6 +162,25 @@ double Area(const Path &poly)
|
|||||||
return -a * 0.5;
|
return -a * 0.5;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
IntPoint Centroid(const Path& poly, double area)
|
||||||
|
{
|
||||||
|
double x_temp = 0;
|
||||||
|
double y_temp = 0;
|
||||||
|
|
||||||
|
const int max = poly.size() - 1;
|
||||||
|
size_t i = 0;
|
||||||
|
for (; i < max; ++i)
|
||||||
|
{
|
||||||
|
size_t j = i + 1;
|
||||||
|
x_temp += (double)(poly[i].X + poly[j].X) * ((double)poly[i].X * poly[j].Y - (double)poly[j].X * poly[i].Y);
|
||||||
|
y_temp += (double)(poly[i].Y + poly[j].Y) * ((double)poly[i].X * poly[j].Y - (double)poly[j].X * poly[i].Y);
|
||||||
|
}
|
||||||
|
x_temp += (double)(poly[i].X + poly[0].X) * ((double)poly[i].X * poly[0].Y - (double)poly[0].X * poly[i].Y);
|
||||||
|
y_temp += (double)(poly[i].Y + poly[0].Y) * ((double)poly[i].X * poly[0].Y - (double)poly[0].X * poly[i].Y);
|
||||||
|
|
||||||
|
return IntPoint(x_temp / (6 * area), y_temp / (6 * area));
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
double Area(const OutRec &outRec)
|
double Area(const OutRec &outRec)
|
||||||
{
|
{
|
||||||
@ -3895,10 +3914,10 @@ double DistanceFromLineSqrd(
|
|||||||
const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2)
|
const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2)
|
||||||
{
|
{
|
||||||
//The equation of a line in general form (Ax + By + C = 0)
|
//The equation of a line in general form (Ax + By + C = 0)
|
||||||
//given 2 points (x¹,y¹) & (x²,y²) is ...
|
//given 2 points (x<EFBFBD>,y<>) & (x<>,y<>) is ...
|
||||||
//(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0
|
//(y<EFBFBD> - y<>)x + (x<> - x<>)y + (y<> - y<>)x<> - (x<> - x<>)y<> = 0
|
||||||
//A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹
|
//A = (y<EFBFBD> - y<>); B = (x<> - x<>); C = (y<> - y<>)x<> - (x<> - x<>)y<>
|
||||||
//perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
|
//perpendicular distance of point (x<EFBFBD>,y<>) = (Ax<41> + By<42> + C)/Sqrt(A<> + B<>)
|
||||||
//see http://en.wikipedia.org/wiki/Perpendicular_distance
|
//see http://en.wikipedia.org/wiki/Perpendicular_distance
|
||||||
double A = double(ln1.Y - ln2.Y);
|
double A = double(ln1.Y - ln2.Y);
|
||||||
double B = double(ln2.X - ln1.X);
|
double B = double(ln2.X - ln1.X);
|
||||||
|
@ -184,6 +184,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
double Area(const Path &poly);
|
double Area(const Path &poly);
|
||||||
|
IntPoint Centroid(const Path& poly, double area);
|
||||||
inline bool Orientation(const Path &poly) { return Area(poly) >= 0; }
|
inline bool Orientation(const Path &poly) { return Area(poly) >= 0; }
|
||||||
int PointInPolygon(const IntPoint &pt, const Path &path);
|
int PointInPolygon(const IntPoint &pt, const Path &path);
|
||||||
|
|
||||||
|
@ -524,6 +524,22 @@ T _clipper_do(const ClipperLib::ClipType clipType,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool test_path(const ClipperLib::Path &path) {
|
||||||
|
|
||||||
|
double area = std::abs(ClipperLib::Area(path));
|
||||||
|
// get highest dist, but as it's n² in complexity, i use 2*dist to center wich is 2n in complexity
|
||||||
|
ClipperLib::cInt max_dist_sqrd = 0;
|
||||||
|
ClipperLib::IntPoint centroid = ClipperLib::Centroid(path, area);
|
||||||
|
for (const ClipperLib::IntPoint& pt : path) {
|
||||||
|
// &0x3FFFFFFF to let (dx * dx + dy * dy) be storable into a int64
|
||||||
|
ClipperLib::cInt dx = (pt.X - centroid.X) & 0x3FFFFFFF;
|
||||||
|
ClipperLib::cInt dy = (pt.Y - centroid.Y) & 0x3FFFFFFF;
|
||||||
|
ClipperLib::cInt dist_sqrd = (dx * dx + dy * dy);
|
||||||
|
max_dist_sqrd = std::max(max_dist_sqrd, dist_sqrd);
|
||||||
|
}
|
||||||
|
return (area < (SCALED_EPSILON + SCALED_EPSILON) * std::sqrt(max_dist_sqrd));
|
||||||
|
}
|
||||||
|
|
||||||
// Fix of #117: A large fractal pyramid takes ages to slice
|
// Fix of #117: A large fractal pyramid takes ages to slice
|
||||||
// The Clipper library has difficulties processing overlapping polygons.
|
// The Clipper library has difficulties processing overlapping polygons.
|
||||||
// Namely, the function ClipperLib::JoinCommonEdges() has potentially a terrible time complexity if the output
|
// Namely, the function ClipperLib::JoinCommonEdges() has potentially a terrible time complexity if the output
|
||||||
@ -554,6 +570,24 @@ inline ClipperLib::PolyTree _clipper_do_polytree2(const ClipperLib::ClipType cli
|
|||||||
clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
|
clipper.AddPaths(input_subject, ClipperLib::ptSubject, true);
|
||||||
ClipperLib::PolyTree retval;
|
ClipperLib::PolyTree retval;
|
||||||
clipper.Execute(ClipperLib::ctUnion, retval, fillType, fillType);
|
clipper.Execute(ClipperLib::ctUnion, retval, fillType, fillType);
|
||||||
|
|
||||||
|
// if safety_offset_, remove too small polygons & holes
|
||||||
|
if (safety_offset_)
|
||||||
|
for (int idx_poly = 0; idx_poly < retval.ChildCount(); ++idx_poly) {
|
||||||
|
ClipperLib::PolyNode* ex_polygon = retval.Childs[idx_poly];
|
||||||
|
if (test_path(ex_polygon->Contour)) {
|
||||||
|
retval.Childs.erase(retval.Childs.begin() + idx_poly);
|
||||||
|
--idx_poly;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < ex_polygon->ChildCount(); ++i)
|
||||||
|
{
|
||||||
|
if (test_path(ex_polygon->Childs[i]->Contour)) {
|
||||||
|
ex_polygon->Childs.erase(ex_polygon->Childs.begin() + i);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user