Added various has_duplicate_points() checks, to be used by asserts.

Removed some "extern" function modifiers, they have no meaning in C++.
This commit is contained in:
Vojtech Bubnik 2021-09-24 14:07:46 +02:00
parent 7eea15fdde
commit fec5d92bc8
7 changed files with 183 additions and 27 deletions

View file

@ -126,6 +126,45 @@ ExPolygons ClipperPaths_to_Slic3rExPolygons(const ClipperLib::Paths &input)
return PolyTreeToExPolygons(std::move(polytree));
}
#if 0
// Global test.
bool has_duplicate_points(const ClipperLib::PolyTree &polytree)
{
struct Helper {
static void collect_points_recursive(const ClipperLib::PolyNode &polynode, ClipperLib::Path &out) {
// For each hole of the current expolygon:
out.insert(out.end(), polynode.Contour.begin(), polynode.Contour.end());
for (int i = 0; i < polynode.ChildCount(); ++ i)
collect_points_recursive(*polynode.Childs[i], out);
}
};
ClipperLib::Path pts;
for (int i = 0; i < polytree.ChildCount(); ++ i)
Helper::collect_points_recursive(*polytree.Childs[i], pts);
return has_duplicate_points(std::move(pts));
}
#else
// Local test inside each of the contours.
bool has_duplicate_points(const ClipperLib::PolyTree &polytree)
{
struct Helper {
static bool has_duplicate_points_recursive(const ClipperLib::PolyNode &polynode) {
if (has_duplicate_points(polynode.Contour))
return true;
for (int i = 0; i < polynode.ChildCount(); ++ i)
if (has_duplicate_points_recursive(*polynode.Childs[i]))
return true;
return false;
}
};
ClipperLib::Path pts;
for (int i = 0; i < polytree.ChildCount(); ++ i)
if (Helper::has_duplicate_points_recursive(*polytree.Childs[i]))
return true;
return false;
}
#endif
// Offset outside by 10um, one by one.
template<typename PathsProvider>
static ClipperLib::Paths safety_offset(PathsProvider &&paths)

View file

@ -114,10 +114,11 @@ bool ExPolygon::contains(const Polylines &polylines) const
bool ExPolygon::contains(const Point &point) const
{
if (!this->contour.contains(point)) return false;
for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) {
if (it->contains(point)) return false;
}
if (! this->contour.contains(point))
return false;
for (const Polygon &hole : this->holes)
if (hole.contains(point))
return false;
return true;
}
@ -367,6 +368,57 @@ extern std::vector<BoundingBox> get_extents_vector(const ExPolygons &polygons)
return out;
}
bool has_duplicate_points(const ExPolygon &expoly)
{
#if 1
// Check globally.
size_t cnt = expoly.contour.points.size();
for (const Polygon &hole : expoly.holes)
cnt += hole.points.size();
std::vector<Point> allpts;
allpts.reserve(cnt);
allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end());
for (const Polygon &hole : expoly.holes)
allpts.insert(allpts.end(), hole.points.begin(), hole.points.end());
return has_duplicate_points(std::move(allpts));
#else
// Check per contour.
if (has_duplicate_points(expoly.contour))
return true;
for (const Polygon &hole : expoly.holes)
if (has_duplicate_points(hole))
return true;
return false;
#endif
}
bool has_duplicate_points(const ExPolygons &expolys)
{
#if 1
// Check globally.
size_t cnt = 0;
for (const ExPolygon &expoly : expolys) {
cnt += expoly.contour.points.size();
for (const Polygon &hole : expoly.holes)
cnt += hole.points.size();
}
std::vector<Point> allpts;
allpts.reserve(cnt);
for (const ExPolygon &expoly : expolys) {
allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end());
for (const Polygon &hole : expoly.holes)
allpts.insert(allpts.end(), hole.points.begin(), hole.points.end());
}
return has_duplicate_points(std::move(allpts));
#else
// Check per contour.
for (const ExPolygon &expoly : expolys)
if (has_duplicate_points(expoly))
return true;
return false;
#endif
}
bool remove_sticks(ExPolygon &poly)
{
return remove_sticks(poly.contour) || remove_sticks(poly.holes);

View file

@ -351,20 +351,24 @@ inline ExPolygons expolygons_simplify(const ExPolygons &expolys, double toleranc
return out;
}
extern BoundingBox get_extents(const ExPolygon &expolygon);
extern BoundingBox get_extents(const ExPolygons &expolygons);
extern BoundingBox get_extents_rotated(const ExPolygon &poly, double angle);
extern BoundingBox get_extents_rotated(const ExPolygons &polygons, double angle);
extern std::vector<BoundingBox> get_extents_vector(const ExPolygons &polygons);
BoundingBox get_extents(const ExPolygon &expolygon);
BoundingBox get_extents(const ExPolygons &expolygons);
BoundingBox get_extents_rotated(const ExPolygon &poly, double angle);
BoundingBox get_extents_rotated(const ExPolygons &polygons, double angle);
std::vector<BoundingBox> get_extents_vector(const ExPolygons &polygons);
extern bool remove_sticks(ExPolygon &poly);
extern void keep_largest_contour_only(ExPolygons &polygons);
// Test for duplicate points. The points are copied, sorted and checked for duplicates globally.
bool has_duplicate_points(const ExPolygon &expoly);
bool has_duplicate_points(const ExPolygons &expolys);
bool remove_sticks(ExPolygon &poly);
void keep_largest_contour_only(ExPolygons &polygons);
inline double area(const ExPolygon &poly) { return poly.area(); }
inline double area(const ExPolygons &polys) { double s = 0.; for (auto &p : polys) s += p.area(); return s; }
// Removes all expolygons smaller than min_area and also removes all holes smaller than min_area
extern bool remove_small_and_small_holes(ExPolygons &expolygons, double min_area);
bool remove_small_and_small_holes(ExPolygons &expolygons, double min_area);
} // namespace Slic3r

View file

@ -179,6 +179,15 @@ Point Point::projection_onto(const Line &line) const
return ((line.a - *this).cast<double>().squaredNorm() < (line.b - *this).cast<double>().squaredNorm()) ? line.a : line.b;
}
bool has_duplicate_points(std::vector<Point> &&pts)
{
std::sort(pts.begin(), pts.end());
for (size_t i = 1; i < pts.size(); ++ i)
if (pts[i - 1] == pts[i])
return true;
return false;
}
BoundingBox get_extents(const Points &pts)
{
return BoundingBox(pts);

View file

@ -211,8 +211,34 @@ inline Point lerp(const Point &a, const Point &b, double t)
return ((1. - t) * a.cast<double>() + t * b.cast<double>()).cast<coord_t>();
}
extern BoundingBox get_extents(const Points &pts);
extern BoundingBox get_extents(const std::vector<Points> &pts);
BoundingBox get_extents(const Points &pts);
BoundingBox get_extents(const std::vector<Points> &pts);
// Test for duplicate points in a vector of points.
// The points are copied, sorted and checked for duplicates globally.
bool has_duplicate_points(std::vector<Point> &&pts);
inline bool has_duplicate_points(const std::vector<Point> &pts)
{
std::vector<Point> cpy = pts;
return has_duplicate_points(std::move(cpy));
}
// Test for duplicate points in a vector of points.
// Only successive points are checked for equality.
inline bool has_duplicate_successive_points(const std::vector<Point> &pts)
{
for (size_t i = 1; i < pts.size(); ++ i)
if (pts[i - 1] == pts[i])
return true;
return false;
}
// Test for duplicate points in a vector of points.
// Only successive points are checked for equality. Additionally, first and last points are compared for equality.
inline bool has_duplicate_successive_points_closed(const std::vector<Point> &pts)
{
return has_duplicate_successive_points(pts) || (pts.size() >= 2 && pts.front() == pts.back());
}
namespace int128 {
// Exact orientation predicate,

View file

@ -334,6 +334,27 @@ extern std::vector<BoundingBox> get_extents_vector(const Polygons &polygons)
return out;
}
bool has_duplicate_points(const Polygons &polys)
{
#if 1
// Check globally.
size_t cnt = 0;
for (const Polygon &poly : polys)
cnt += poly.points.size();
std::vector<Point> allpts;
allpts.reserve(cnt);
for (const Polygon &poly : polys)
allpts.insert(allpts.end(), poly.points.begin(), poly.points.end());
return has_duplicate_points(std::move(allpts));
#else
// Check per contour.
for (const Polygon &poly : polys)
if (has_duplicate_points(poly))
return true;
return false;
#endif
}
static inline bool is_stick(const Point &p1, const Point &p2, const Point &p3)
{
Point v1 = p2 - p1;

View file

@ -78,11 +78,16 @@ public:
inline bool operator==(const Polygon &lhs, const Polygon &rhs) { return lhs.points == rhs.points; }
inline bool operator!=(const Polygon &lhs, const Polygon &rhs) { return lhs.points != rhs.points; }
extern BoundingBox get_extents(const Polygon &poly);
extern BoundingBox get_extents(const Polygons &polygons);
extern BoundingBox get_extents_rotated(const Polygon &poly, double angle);
extern BoundingBox get_extents_rotated(const Polygons &polygons, double angle);
extern std::vector<BoundingBox> get_extents_vector(const Polygons &polygons);
BoundingBox get_extents(const Polygon &poly);
BoundingBox get_extents(const Polygons &polygons);
BoundingBox get_extents_rotated(const Polygon &poly, double angle);
BoundingBox get_extents_rotated(const Polygons &polygons, double angle);
std::vector<BoundingBox> get_extents_vector(const Polygons &polygons);
// Test for duplicate points. The points are copied, sorted and checked for duplicates globally.
inline bool has_duplicate_points(Polygon &&poly) { return has_duplicate_points(std::move(poly.points)); }
inline bool has_duplicate_points(const Polygon &poly) { return has_duplicate_points(poly.points); }
bool has_duplicate_points(const Polygons &polys);
inline double total_length(const Polygons &polylines) {
double total = 0;
@ -102,19 +107,19 @@ inline double area(const Polygons &polys)
}
// Remove sticks (tentacles with zero area) from the polygon.
extern bool remove_sticks(Polygon &poly);
extern bool remove_sticks(Polygons &polys);
bool remove_sticks(Polygon &poly);
bool remove_sticks(Polygons &polys);
// Remove polygons with less than 3 edges.
extern bool remove_degenerate(Polygons &polys);
extern bool remove_small(Polygons &polys, double min_area);
extern void remove_collinear(Polygon &poly);
extern void remove_collinear(Polygons &polys);
bool remove_degenerate(Polygons &polys);
bool remove_small(Polygons &polys, double min_area);
void remove_collinear(Polygon &poly);
void remove_collinear(Polygons &polys);
// Append a vector of polygons at the end of another vector of polygons.
inline void polygons_append(Polygons &dst, const Polygons &src) { dst.insert(dst.end(), src.begin(), src.end()); }
inline void polygons_append(Polygons &dst, const Polygons &src) { dst.insert(dst.end(), src.begin(), src.end()); }
inline void polygons_append(Polygons &dst, Polygons &&src)
inline void polygons_append(Polygons &dst, Polygons &&src)
{
if (dst.empty()) {
dst = std::move(src);