Slight optimization of distance_to_squared()

This commit is contained in:
Vojtech Bubnik 2023-05-02 16:32:03 +02:00
parent 04f557693b
commit a077f669ee

View File

@ -40,11 +40,12 @@ template<class L> auto get_b(L &&l) { return Traits<remove_cvref_t<L>>::get_b(l)
// Distance to the closest point of line. // Distance to the closest point of line.
template<class L> template<class L>
double distance_to_squared(const L &line, const Vec<Dim<L>, Scalar<L>> &point, Vec<Dim<L>, Scalar<L>> *nearest_point) inline double distance_to_squared(const L &line, const Vec<Dim<L>, Scalar<L>> &point, Vec<Dim<L>, Scalar<L>> *nearest_point)
{ {
const Vec<Dim<L>, double> v = (get_b(line) - get_a(line)).template cast<double>(); using VecType = Vec<Dim<L>, double>;
const Vec<Dim<L>, double> va = (point - get_a(line)).template cast<double>(); const VecType v = (get_b(line) - get_a(line)).template cast<double>();
const double l2 = v.squaredNorm(); // avoid a sqrt const VecType va = (point - get_a(line)).template cast<double>();
const double l2 = v.squaredNorm();
if (l2 == 0.0) { if (l2 == 0.0) {
// a == b case // a == b case
*nearest_point = get_a(line); *nearest_point = get_a(line);
@ -53,19 +54,20 @@ double distance_to_squared(const L &line, const Vec<Dim<L>, Scalar<L>> &point, V
// Consider the line extending the segment, parameterized as a + t (b - a). // Consider the line extending the segment, parameterized as a + t (b - a).
// We find projection of this point onto the line. // We find projection of this point onto the line.
// It falls where t = [(this-a) . (b-a)] / |b-a|^2 // It falls where t = [(this-a) . (b-a)] / |b-a|^2
const double t = va.dot(v) / l2; const double t = va.dot(v);
if (t <= 0.0) { if (t <= 0.0) {
// beyond the 'a' end of the segment // beyond the 'a' end of the segment
*nearest_point = get_a(line); *nearest_point = get_a(line);
return va.squaredNorm(); return va.squaredNorm();
} else if (t >= 1.0) { } else if (t >= l2) {
// beyond the 'b' end of the segment // beyond the 'b' end of the segment
*nearest_point = get_b(line); *nearest_point = get_b(line);
return (point - get_b(line)).template cast<double>().squaredNorm(); return (point - get_b(line)).template cast<double>().squaredNorm();
} }
*nearest_point = (get_a(line).template cast<double>() + t * v).template cast<Scalar<L>>(); const VecType w = ((t / l2) * v).eval();
return (t * v - va).squaredNorm(); *nearest_point = (get_a(line).template cast<double>() + w).template cast<Scalar<L>>();
return (w - va).squaredNorm();
} }
// Distance to the closest point of line. // Distance to the closest point of line.