ClipperLib: Optimized PointInPolygon() to calculate cross products
with int64s instead of doubles. Polygon / ExPolygon: contains() reworked to use ClipperLib::PointInPolygon(). The Slic3r own implementation was not robust. Fixed test_perimeters after recent refactoring (sorting of extrusions into LayerIslands)
This commit is contained in:
parent
5eaec515ba
commit
9dca8403fe
8 changed files with 37 additions and 38 deletions
|
@ -100,10 +100,12 @@ bool ExPolygon::contains(const Polylines &polylines) const
|
|||
|
||||
bool ExPolygon::contains(const Point &point) const
|
||||
{
|
||||
if (! this->contour.contains(point))
|
||||
if (! Slic3r::contains(contour, point, true))
|
||||
// Outside the outer contour, not on the contour boundary.
|
||||
return false;
|
||||
for (const Polygon &hole : this->holes)
|
||||
if (hole.contains(point))
|
||||
if (Slic3r::contains(hole, point, false))
|
||||
// Inside a hole, not on the hole boundary.
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -114,13 +116,13 @@ bool ExPolygon::contains_b(const Point &point) const
|
|||
return this->contains(point) || this->has_boundary_point(point);
|
||||
}
|
||||
|
||||
bool
|
||||
ExPolygon::has_boundary_point(const Point &point) const
|
||||
bool ExPolygon::has_boundary_point(const Point &point) const
|
||||
{
|
||||
if (this->contour.has_boundary_point(point)) return true;
|
||||
for (Polygons::const_iterator h = this->holes.begin(); h != this->holes.end(); ++h) {
|
||||
if (h->has_boundary_point(point)) return true;
|
||||
}
|
||||
if (this->contour.has_boundary_point(point))
|
||||
return true;
|
||||
for (const Polygon &hole : this->holes)
|
||||
if (hole.has_boundary_point(point))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -373,14 +373,14 @@ inline void expolygons_append(ExPolygons &dst, ExPolygons &&src)
|
|||
|
||||
inline void expolygons_rotate(ExPolygons &expolys, double angle)
|
||||
{
|
||||
for (ExPolygons::iterator p = expolys.begin(); p != expolys.end(); ++p)
|
||||
p->rotate(angle);
|
||||
for (ExPolygon &expoly : expolys)
|
||||
expoly.rotate(angle);
|
||||
}
|
||||
|
||||
inline bool expolygons_contain(ExPolygons &expolys, const Point &pt)
|
||||
{
|
||||
for (ExPolygons::iterator p = expolys.begin(); p != expolys.end(); ++p)
|
||||
if (p->contains(pt))
|
||||
for (const ExPolygon &expoly : expolys)
|
||||
if (expoly.contains(pt))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -691,7 +691,7 @@ void Layer::sort_perimeters_into_islands(
|
|||
for (auto it_source_slice = perimeter_slices_queue.begin(); it_source_slice != perimeter_slices_queue.end(); ++ it_source_slice) {
|
||||
double d2min = std::numeric_limits<double>::max();
|
||||
int lslice_idx_min = -1;
|
||||
for (int lslice_idx = int(lslices_ex.size()) - 1; lslice_idx >= 0 && ! perimeter_slices_queue.empty(); -- lslice_idx)
|
||||
for (int lslice_idx = int(lslices_ex.size()) - 1; lslice_idx >= 0; -- lslice_idx)
|
||||
if (double d2 = point_inside_surface_dist2(lslice_idx, it_source_slice->second); d2 < d2min) {
|
||||
d2min = d2;
|
||||
lslice_idx_min = lslice_idx;
|
||||
|
|
|
@ -89,26 +89,9 @@ void Polygon::douglas_peucker(double tolerance)
|
|||
}
|
||||
|
||||
// Does an unoriented polygon contain a point?
|
||||
// Tested by counting intersections along a horizontal line.
|
||||
bool Polygon::contains(const Point &p) const
|
||||
{
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
||||
bool result = false;
|
||||
Points::const_iterator i = this->points.begin();
|
||||
Points::const_iterator j = this->points.end() - 1;
|
||||
for (; i != this->points.end(); j = i ++)
|
||||
if (i->y() > p.y() != j->y() > p.y())
|
||||
#if 1
|
||||
if (Vec2d v = (*j - *i).cast<double>();
|
||||
// p.x() is below the line
|
||||
p.x() - i->x() < double(p.y() - i->y()) * v.x() / v.y())
|
||||
#else
|
||||
// Orientation predicated relative to i-th point.
|
||||
if (double orient = (double)(p.x() - i->x()) * (double)(j->y() - i->y()) - (double)(p.y() - i->y()) * (double)(j->x() - i->x());
|
||||
(i->y() > j->y()) ? (orient > 0.) : (orient < 0.))
|
||||
#endif
|
||||
result = !result;
|
||||
return result;
|
||||
return Slic3r::contains(*this, p, true);
|
||||
}
|
||||
|
||||
// this only works on CCW polygons as CW will be ripped out by Clipper's simplify_polygons()
|
||||
|
@ -536,6 +519,15 @@ bool polygons_match(const Polygon &l, const Polygon &r)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool contains(const Polygon &polygon, const Point &p, bool border_result)
|
||||
{
|
||||
if (const int poly_count_inside = ClipperLib::PointInPolygon(p, polygon.points);
|
||||
poly_count_inside == -1)
|
||||
return border_result;
|
||||
else
|
||||
return (poly_count_inside % 2) == 1;
|
||||
}
|
||||
|
||||
bool contains(const Polygons &polygons, const Point &p, bool border_result)
|
||||
{
|
||||
int poly_count_inside = 0;
|
||||
|
|
|
@ -255,6 +255,7 @@ inline Polygons to_polygons(std::vector<Points> &&paths)
|
|||
bool polygons_match(const Polygon &l, const Polygon &r);
|
||||
|
||||
// Returns true if inside. Returns border_result if on boundary.
|
||||
bool contains(const Polygon& polygon, const Point& p, bool border_result = true);
|
||||
bool contains(const Polygons& polygons, const Point& p, bool border_result = true);
|
||||
|
||||
Polygon make_circle(double radius, double error);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue