Open flbbronnec opened 4 years ago
pybind11-rdp handles this pretty well:
https://github.com/cubao/pybind11-rdp/blob/master/src/main.cpp#L26-L37
struct LineSegment
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
const Eigen::Vector3d A, B, AB;
const double len2, inv_len2;
LineSegment(const Eigen::Vector3d &a, const Eigen::Vector3d &b)
: A(a), B(b), AB(b - a), //
len2((b - a).squaredNorm()), inv_len2(1.0 / len2)
{
}
double distance2(const Eigen::Vector3d &P) const
{
double dot = (P - A).dot(AB);
if (dot <= 0) {
return (P - A).squaredNorm();
} else if (dot >= len2) {
return (P - B).squaredNorm();
}
// P' = A + dot/length * normed(AB)
// = A + dot * AB / (length^2)
return (A + (dot * inv_len2 * AB) - P).squaredNorm();
}
double distance(const Eigen::Vector3d &P) const
{
return std::sqrt(distance2(P));
}
};
Some tests:
TEST(RdpTest, Distance)
{
auto seg = LineSegment({0.0, 0.0, 0.0}, {10.0, 0.0, 0.0});
ASSERT_EQ(4.0, dbg(seg.distance({5.0, 4.0, 0.0})));
ASSERT_EQ(5.0, dbg(seg.distance({-4.0, 3.0, 0.0})));
ASSERT_EQ(5.0, dbg(seg.distance({14.0, 3.0, 0.0})));
}
TEST(RdpTest, Distance_dup)
{
auto seg = LineSegment({0.0, 0.0, 0.0}, {0.0, 0.0, 0.0});
ASSERT_EQ(5.0, dbg(seg.distance({3.0, 4.0, 0.0})));
ASSERT_EQ(5.0, dbg(seg.distance({-4.0, 3.0, 0.0})));
ASSERT_EQ(13.0, dbg(seg.distance({5.0, 12.0, 0.0})));
}
这是来自QQ邮箱的假期自动回复邮件。你好,我最近正在休假中,无法亲自回复你的邮件。我将在假期结束后,尽快给你回复。
As https://github.com/fhirschmann/rdp/issues/13 points out, pdist in rdp is WRONGLY Point-to-Line distance. We (pybind11_rdp) use Point-to-LineSegment distance.
from rdp import rdp
print(rdp([[0, 0], [10, 0.1], [1, 0]], epsilon=1.0)) # wrong
# [[0.0, 0.0],
# [1.0, 0.0]]
from pybind11_rdp import rdp
print(rdp([[0, 0], [10, 0.1], [1, 0]], epsilon=1.0)) # correct
# [[ 0. 0. ]
# [10. 0.1]
# [ 1. 0. ]]
The current
pldist
function returns the distance between a point and the infinte line generated by two other points (i.e the distance to the orthogonal projection), which is incorrect. It should return the distance between a point and a line-segment.Here is a fix coming from this answer https://stackoverflow.com/a/54442561: