mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-15 07:25:53 +08:00
douglas_peucker(): Optimized for 32bit Point types.
This commit is contained in:
parent
2e150795b1
commit
63ca221394
@ -106,7 +106,7 @@ bool MultiPoint::remove_duplicate_points()
|
|||||||
Points MultiPoint::douglas_peucker(const Points &pts, const double tolerance)
|
Points MultiPoint::douglas_peucker(const Points &pts, const double tolerance)
|
||||||
{
|
{
|
||||||
Points result_pts;
|
Points result_pts;
|
||||||
double tolerance_sq = tolerance * tolerance;
|
auto tolerance_sq = int64_t(sqr(tolerance));
|
||||||
if (! pts.empty()) {
|
if (! pts.empty()) {
|
||||||
const Point *anchor = &pts.front();
|
const Point *anchor = &pts.front();
|
||||||
size_t anchor_idx = 0;
|
size_t anchor_idx = 0;
|
||||||
@ -120,16 +120,44 @@ Points MultiPoint::douglas_peucker(const Points &pts, const double tolerance)
|
|||||||
dpStack.reserve(pts.size());
|
dpStack.reserve(pts.size());
|
||||||
dpStack.emplace_back(floater_idx);
|
dpStack.emplace_back(floater_idx);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
double max_dist_sq = 0.0;
|
int64_t max_dist_sq = 0;
|
||||||
size_t furthest_idx = anchor_idx;
|
size_t furthest_idx = anchor_idx;
|
||||||
// find point furthest from line seg created by (anchor, floater) and note it
|
// find point furthest from line seg created by (anchor, floater) and note it
|
||||||
|
{
|
||||||
|
const Point a = *anchor;
|
||||||
|
const Point f = *floater;
|
||||||
|
const Vec2i64 v = (f - a).cast<int64_t>();
|
||||||
|
const int64_t l2 = v.squaredNorm();
|
||||||
|
// Make up for rounding when converting from int64_t to double. Double mantissa is just 52 bits.
|
||||||
|
if (l2 < (1 << 14)) {
|
||||||
|
for (size_t i = anchor_idx + 1; i < floater_idx; ++ i)
|
||||||
|
if (int64_t dist_sq = (pts[i] - a).cast<int64_t>().squaredNorm(); dist_sq > max_dist_sq) {
|
||||||
|
max_dist_sq = dist_sq;
|
||||||
|
furthest_idx = i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const double dl2 = double(l2);
|
||||||
|
const Vec2d dv = v.cast<double>();
|
||||||
for (size_t i = anchor_idx + 1; i < floater_idx; ++ i) {
|
for (size_t i = anchor_idx + 1; i < floater_idx; ++ i) {
|
||||||
double dist_sq = Line::distance_to_squared(pts[i], *anchor, *floater);
|
const Point p = pts[i];
|
||||||
|
const Vec2i64 va = (p - a).template cast<int64_t>();
|
||||||
|
const int64_t t = va.dot(v);
|
||||||
|
int64_t dist_sq;
|
||||||
|
if (t <= 0) {
|
||||||
|
dist_sq = va.squaredNorm();
|
||||||
|
} else if (t >= l2) {
|
||||||
|
dist_sq = (p - f).cast<int64_t>().squaredNorm();
|
||||||
|
} else {
|
||||||
|
const Vec2i64 w = ((double(t) / dl2) * dv).cast<int64_t>();
|
||||||
|
dist_sq = (w - va).squaredNorm();
|
||||||
|
}
|
||||||
if (dist_sq > max_dist_sq) {
|
if (dist_sq > max_dist_sq) {
|
||||||
max_dist_sq = dist_sq;
|
max_dist_sq = dist_sq;
|
||||||
furthest_idx = i;
|
furthest_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// remove point if less than tolerance
|
// remove point if less than tolerance
|
||||||
if (max_dist_sq <= tolerance_sq) {
|
if (max_dist_sq <= tolerance_sq) {
|
||||||
result_pts.emplace_back(*floater);
|
result_pts.emplace_back(*floater);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user