Tests for duplicate points in Polygons / ExPolygons were reworked

to use ankerl::unordered_dense hash map. Now the tests are roughly
1/4 faster than before.
This commit is contained in:
Vojtech Bubnik 2023-04-13 16:09:29 +02:00
parent bd301d2a85
commit 78b00bb9cb
2 changed files with 49 additions and 11 deletions

View file

@ -10,6 +10,8 @@
#include <cassert>
#include <list>
#include <ankerl/unordered_dense.h>
namespace Slic3r {
void ExPolygon::scale(double factor)
@ -416,20 +418,36 @@ 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();
}
#if 0
// Detect duplicates by sorting with quicksort. It is quite fast, but ankerl::unordered_dense is around 1/4 faster.
std::vector<Point> allpts;
allpts.reserve(cnt);
allpts.reserve(count_points(expolys));
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
// Detect duplicates by inserting into an ankerl::unordered_dense hash set, which is is around 1/4 faster than qsort.
struct PointHash {
uint64_t operator()(const Point &p) const noexcept {
uint64_t h;
static_assert(sizeof(h) == sizeof(p));
memcpy(&h, &p, sizeof(p));
return ankerl::unordered_dense::detail::wyhash::hash(h);
}
};
ankerl::unordered_dense::set<Point, PointHash> allpts;
allpts.reserve(count_points(expolys));
for (const ExPolygon &expoly : expolys)
for (size_t icontour = 0; icontour < expoly.num_contours(); ++ icontour)
for (const Point &pt : expoly.contour_or_hole(icontour).points)
if (! allpts.insert(pt).second)
// Duplicate point was discovered.
return true;
return false;
#endif
#else
// Check per contour.
for (const ExPolygon &expoly : expolys)

View file

@ -4,6 +4,8 @@
#include "Polygon.hpp"
#include "Polyline.hpp"
#include <ankerl/unordered_dense.h>
namespace Slic3r {
double Polygon::length() const
@ -400,14 +402,32 @@ bool has_duplicate_points(const Polygons &polys)
{
#if 1
// Check globally.
size_t cnt = 0;
for (const Polygon &poly : polys)
cnt += poly.points.size();
#if 0
// Detect duplicates by sorting with quicksort. It is quite fast, but ankerl::unordered_dense is around 1/4 faster.
std::vector<Point> allpts;
allpts.reserve(cnt);
allpts.reserve(count_points(polys));
for (const Polygon &poly : polys)
allpts.insert(allpts.end(), poly.points.begin(), poly.points.end());
return has_duplicate_points(std::move(allpts));
#else
// Detect duplicates by inserting into an ankerl::unordered_dense hash set, which is is around 1/4 faster than qsort.
struct PointHash {
uint64_t operator()(const Point &p) const noexcept {
uint64_t h;
static_assert(sizeof(h) == sizeof(p));
memcpy(&h, &p, sizeof(p));
return ankerl::unordered_dense::detail::wyhash::hash(h);
}
};
ankerl::unordered_dense::set<Point, PointHash> allpts;
allpts.reserve(count_points(polys));
for (const Polygon &poly : polys)
for (const Point &pt : poly.points)
if (! allpts.insert(pt).second)
// Duplicate point was discovered.
return true;
return false;
#endif
#else
// Check per contour.
for (const Polygon &poly : polys)