mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-22 16:21:24 -06:00
Bugfix: Douglas-Peucker used perpendicular distance instead of shortest distance, thus clipping more than it should. #2474
This commit is contained in:
parent
69da8b0999
commit
d8be67c28b
7 changed files with 64 additions and 5 deletions
|
@ -328,8 +328,8 @@ MedialAxis::is_valid_edge(const VD::edge_type& edge) const
|
|||
// our skeleton
|
||||
Point v0( edge.vertex0()->x(), edge.vertex0()->y() );
|
||||
Point v1( edge.vertex1()->x(), edge.vertex1()->y() );
|
||||
double dist0 = v0.distance_to(segment1);
|
||||
double dist1 = v1.distance_to(segment1);
|
||||
double dist0 = v0.perp_distance_to(segment1);
|
||||
double dist1 = v1.perp_distance_to(segment1);
|
||||
|
||||
/*
|
||||
double diff = fabs(dist1 - dist0);
|
||||
|
|
|
@ -90,6 +90,7 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
|
|||
size_t index = 0;
|
||||
Line full(points.front(), points.back());
|
||||
for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) {
|
||||
// we use shortest distance, not perpendicular distance
|
||||
double d = it->distance_to(full);
|
||||
if (d > dmax) {
|
||||
index = it - points.begin();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "Point.hpp"
|
||||
#include "Line.hpp"
|
||||
#include "MultiPoint.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -130,8 +131,31 @@ Point::distance_to(const Point &point) const
|
|||
return sqrt(dx*dx + dy*dy);
|
||||
}
|
||||
|
||||
/* distance to the closest point of line */
|
||||
double
|
||||
Point::distance_to(const Line &line) const
|
||||
{
|
||||
const double dx = line.b.x - line.a.x;
|
||||
const double dy = line.b.y - line.a.y;
|
||||
|
||||
const double l2 = dx*dx + dy*dy; // avoid a sqrt
|
||||
if (l2 == 0.0) return this->distance_to(line.a); // line.a == line.b case
|
||||
|
||||
// Consider the line extending the segment, parameterized as line.a + t (line.b - line.a).
|
||||
// We find projection of this point onto the line.
|
||||
// It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2
|
||||
const double t = ((this->x - line.a.x) * dx + (this->y - line.a.y) * dy) / l2;
|
||||
if (t < 0.0) return this->distance_to(line.a); // beyond the 'a' end of the segment
|
||||
else if (t > 1.0) return this->distance_to(line.b); // beyond the 'b' end of the segment
|
||||
Point projection(
|
||||
line.a.x + t * dx,
|
||||
line.a.y + t * dy
|
||||
);
|
||||
return this->distance_to(projection);
|
||||
}
|
||||
|
||||
double
|
||||
Point::perp_distance_to(const Line &line) const
|
||||
{
|
||||
if (line.a.coincides_with(line.b)) return this->distance_to(line.a);
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ class Point
|
|||
bool nearest_point(const Points &points, Point* point) const;
|
||||
double distance_to(const Point &point) const;
|
||||
double distance_to(const Line &line) const;
|
||||
double perp_distance_to(const Line &line) const;
|
||||
double ccw(const Point &p1, const Point &p2) const;
|
||||
double ccw(const Line &line) const;
|
||||
double ccw_angle(const Point &p1, const Point &p2) const;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue