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:
parent
bd301d2a85
commit
78b00bb9cb
2 changed files with 49 additions and 11 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue