mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-16 18:15:59 +08:00
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
@ -10,6 +10,8 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
void ExPolygon::scale(double factor)
|
void ExPolygon::scale(double factor)
|
||||||
@ -416,20 +418,36 @@ bool has_duplicate_points(const ExPolygons &expolys)
|
|||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
// Check globally.
|
// Check globally.
|
||||||
size_t cnt = 0;
|
#if 0
|
||||||
for (const ExPolygon &expoly : expolys) {
|
// Detect duplicates by sorting with quicksort. It is quite fast, but ankerl::unordered_dense is around 1/4 faster.
|
||||||
cnt += expoly.contour.points.size();
|
|
||||||
for (const Polygon &hole : expoly.holes)
|
|
||||||
cnt += hole.points.size();
|
|
||||||
}
|
|
||||||
std::vector<Point> allpts;
|
std::vector<Point> allpts;
|
||||||
allpts.reserve(cnt);
|
allpts.reserve(count_points(expolys));
|
||||||
for (const ExPolygon &expoly : expolys) {
|
for (const ExPolygon &expoly : expolys) {
|
||||||
allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end());
|
allpts.insert(allpts.begin(), expoly.contour.points.begin(), expoly.contour.points.end());
|
||||||
for (const Polygon &hole : expoly.holes)
|
for (const Polygon &hole : expoly.holes)
|
||||||
allpts.insert(allpts.end(), hole.points.begin(), hole.points.end());
|
allpts.insert(allpts.end(), hole.points.begin(), hole.points.end());
|
||||||
}
|
}
|
||||||
return has_duplicate_points(std::move(allpts));
|
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
|
#else
|
||||||
// Check per contour.
|
// Check per contour.
|
||||||
for (const ExPolygon &expoly : expolys)
|
for (const ExPolygon &expoly : expolys)
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "Polygon.hpp"
|
#include "Polygon.hpp"
|
||||||
#include "Polyline.hpp"
|
#include "Polyline.hpp"
|
||||||
|
|
||||||
|
#include <ankerl/unordered_dense.h>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
double Polygon::length() const
|
double Polygon::length() const
|
||||||
@ -400,14 +402,32 @@ bool has_duplicate_points(const Polygons &polys)
|
|||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
// Check globally.
|
// Check globally.
|
||||||
size_t cnt = 0;
|
#if 0
|
||||||
for (const Polygon &poly : polys)
|
// Detect duplicates by sorting with quicksort. It is quite fast, but ankerl::unordered_dense is around 1/4 faster.
|
||||||
cnt += poly.points.size();
|
|
||||||
std::vector<Point> allpts;
|
std::vector<Point> allpts;
|
||||||
allpts.reserve(cnt);
|
allpts.reserve(count_points(polys));
|
||||||
for (const Polygon &poly : polys)
|
for (const Polygon &poly : polys)
|
||||||
allpts.insert(allpts.end(), poly.points.begin(), poly.points.end());
|
allpts.insert(allpts.end(), poly.points.begin(), poly.points.end());
|
||||||
return has_duplicate_points(std::move(allpts));
|
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
|
#else
|
||||||
// Check per contour.
|
// Check per contour.
|
||||||
for (const Polygon &poly : polys)
|
for (const Polygon &poly : polys)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user