Slight optimization of distance_to_squared()
This commit is contained in:
parent
04f557693b
commit
a077f669ee
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user