Factored out convex hull calculation from ModelObject::convex_hull_2d()

to Geometry::convex_hull().
Update Geometry::convex_hull() to handle duplicate points.
This commit is contained in:
Vojtech Bubnik 2021-05-19 13:23:19 +02:00
parent 8db2d96c75
commit 5644b98d3b
2 changed files with 13 additions and 41 deletions

View file

@ -212,36 +212,32 @@ static bool sort_pointfs(const Vec3d& a, const Vec3d& b)
}
// This implementation is based on Andrew's monotone chain 2D convex hull algorithm
Polygon convex_hull(Points points)
Polygon convex_hull(Points pts)
{
assert(points.size() >= 3);
// sort input points
std::sort(points.begin(), points.end(), sort_points);
std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); });
pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end());
int n = points.size(), k = 0;
Polygon hull;
int n = (int)pts.size();
if (n >= 3) {
int k = 0;
hull.points.resize(2 * n);
// Build lower hull
for (int i = 0; i < n; i++) {
while (k >= 2 && points[i].ccw(hull[k-2], hull[k-1]) <= 0) k--;
hull[k++] = points[i];
for (int i = 0; i < n; ++ i) {
while (k >= 2 && pts[i].ccw(hull[k-2], hull[k-1]) <= 0)
-- k;
hull[k ++] = pts[i];
}
// Build upper hull
for (int i = n-2, t = k+1; i >= 0; i--) {
while (k >= t && points[i].ccw(hull[k-2], hull[k-1]) <= 0) k--;
hull[k++] = points[i];
while (k >= t && pts[i].ccw(hull[k-2], hull[k-1]) <= 0)
-- k;
hull[k ++] = pts[i];
}
hull.points.resize(k);
assert(hull.points.front() == hull.points.back());
hull.points.pop_back();
}
return hull;
}

View file

@ -937,31 +937,7 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const
}
#endif // ENABLE_ALLOW_NEGATIVE_Z
}
std::sort(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) < b(0) || (a(0) == b(0) && a(1) < b(1)); });
pts.erase(std::unique(pts.begin(), pts.end(), [](const Point& a, const Point& b) { return a(0) == b(0) && a(1) == b(1); }), pts.end());
Polygon hull;
int n = (int)pts.size();
if (n >= 3) {
int k = 0;
hull.points.resize(2 * n);
// Build lower hull
for (int i = 0; i < n; ++ i) {
while (k >= 2 && pts[i].ccw(hull[k-2], hull[k-1]) <= 0)
-- k;
hull[k ++] = pts[i];
}
// Build upper hull
for (int i = n-2, t = k+1; i >= 0; i--) {
while (k >= t && pts[i].ccw(hull[k-2], hull[k-1]) <= 0)
-- k;
hull[k ++] = pts[i];
}
hull.points.resize(k);
assert(hull.points.front() == hull.points.back());
hull.points.pop_back();
}
return hull;
return Geometry::convex_hull(std::move(pts));
}
void ModelObject::center_around_origin(bool include_modifiers)