point: convert distance member functions to functions

This commit is contained in:
Danny Robson 2015-06-01 15:29:24 +10:00
parent 2e9698f53b
commit 9b548e56d9
5 changed files with 90 additions and 62 deletions

View File

@ -105,16 +105,16 @@ namespace util {
auto c1 = dot (w, v);
if (c1 <= 0)
return m_points[0].distance (target);
return util::distance (target, m_points[0]);
auto c2 = dot (v, v);
if (c2 <= c1)
return m_points[1].distance (target);
return util::distance (target, m_points[1]);
auto b = c1 / c2;
auto p = m_points[0] + b * v;
return p.distance (target);
return util::distance (target, p);
}
}
@ -271,12 +271,12 @@ namespace util {
continue;
if (t <= 0)
dist = min (dist, p0.distance (target));
dist = min (dist, util::distance (target, p0));
else if (t > 1)
dist = min (p2.distance (target));
dist = min (util::distance (target, p2));
else {
auto p = eval (t);
dist = min (dist, p.distance (target));
dist = min (dist, util::distance (target, p));
}
}
@ -303,8 +303,8 @@ float refine_cubic (util::bezier<3> b,
util::point2f p_l = b.eval (t_l);
util::point2f p_r = b.eval (t_r);
float d_l = p_l.distance (target);
float d_r = p_r.distance (target);
float d_l = util::distance (target, p_l);
float d_r = util::distance (target, p_r);
if (d_l < d) { return refine_cubic (b, target, t_l, d_l, p); }
if (d_r < d) { return refine_cubic (b, target, t_r, d_r, p); }
@ -327,14 +327,18 @@ namespace util {
lookup[i] = eval (i / float (SUBDIV - 1));
size_t best = 0;
for (size_t i = 1; i < lookup.size (); ++i)
if (lookup[i].distance2 (target) < lookup[best].distance2 (target))
for (size_t i = 1; i < lookup.size (); ++i) {
auto d_i = util::distance2 (target, lookup[i]);
auto d_b = util::distance2 (target, lookup[best]);
if (d_i < d_b)
best = i;
}
return refine_cubic (*this,
target,
best / float (SUBDIV - 1),
lookup[best].distance (target),
util::distance (target, lookup[best]),
1.f / SUBDIV);
}
}

View File

@ -100,8 +100,10 @@ worley<T>::operator() (util::point<2,T> p) const
CHECK (off.y >= 0 && off.y <= 1);
pos += off;
*cursor++ = pos.difference2 (p_rem.template as<util::vector> ());
*cursor = distance2 (pos + off, p_rem);
cursor++;
}
}
std::sort (std::begin (distances), std::end (distances));
CHECK_GE (distances[0], 0);

View File

@ -33,11 +33,6 @@ namespace util {
{
using coord::base<S,T,util::point,coord::xyzw>::base;
// point operators
template <typename U> typename std::common_type<T,U>::type distance (point<S,U>) const;
template <typename U> typename std::common_type<T,U>::type distance2 (point<S,U>) const;
template <typename U> typename std::common_type<T,U>::type manhattan (point<S,U>) const;
vector<S,T> to (point) const;
vector<S,T> from (point) const;
@ -48,6 +43,19 @@ namespace util {
void sanity (void) const;
};
// distance operators
template <size_t S, typename T, typename U>
typename std::common_type<T,U>::type distance (point<S,T>, point<S,U>);
template <size_t S, typename T, typename U>
typename std::common_type<T,U>::type distance2 (point<S,T>, point<S,U>);
template <size_t S, typename T, typename U>
typename std::common_type<T,U>::type manhattan (point<S,T>, point<S,U>);
template <size_t S, typename T, typename U>
typename std::common_type<T,U>::type chebyshev (point<S,T>, point<S,U>);
// iostream operators
template <size_t S, typename T>
std::ostream& operator<< (std::ostream&, point<S,T>);

View File

@ -19,50 +19,6 @@
#include <algorithm>
namespace util {
//-------------------------------------------------------------------------
template <size_t S, typename T>
template <typename U>
typename std::common_type<T,U>::type
util::point<S,T>::distance (point<S,U> rhs) const
{
return std::sqrt (distance2 (rhs));
}
//-------------------------------------------------------------------------
template <size_t S, typename T>
template <typename U>
typename std::common_type<T,U>::type
util::point<S,T>::distance2 (point<S,U> rhs) const
{
typedef typename std::common_type<T,U>::type result_t;
result_t sum { 0 };
for (size_t i = 0; i < S; ++i)
sum += pow2 (this->data[i] - rhs.data[i]);
return sum;
}
//-------------------------------------------------------------------------
template <size_t S, typename T>
template <typename U>
typename std::common_type<T,U>::type
util::point<S,T>::manhattan (point<S,U> rhs) const
{
typedef typename std::common_type<T,U>::type result_t;
result_t sum { 0 };
for (size_t i = 0; i < S; ++i)
sum += std::abs (this->data[i] - rhs.data[i]);
return sum;
}
///------------------------------------------------------------------------
/// expand point to use homogenous coordinates of a higher dimension.
/// ie, fill with (0,..,0,1)
@ -88,4 +44,50 @@ namespace util {
return out;
}
//-------------------------------------------------------------------------
template <size_t S, typename T, typename U>
typename std::common_type<T,U>::type
distance (point<S,T> a, point<S,U> b)
{
return std::sqrt (distance2 (a, b));
}
//-------------------------------------------------------------------------
template <size_t S, typename T, typename U>
typename std::common_type<T,U>::type
distance2 (point<S,T> a, point<S,U> b)
{
typename std::common_type<T,U>::type sum {0};
for (size_t i = 0; i < S; ++i)
sum += pow2 (a.data[i] - b.data[i]);
return sum;
}
//-------------------------------------------------------------------------
template <size_t S, typename T, typename U>
typename std::common_type<T,U>::type
manhattan (point<S,T> a, point<S,U> b)
{
typename std::common_type<T,U>::type sum {0};
for (size_t i = 0; i < S; ++i)
sum += std::abs (a.data[i] - b.data[i]);
return sum;
}
//-------------------------------------------------------------------------
template <size_t S, typename T, typename U>
typename std::common_type<T,U>::type
chebyshev(point<S,T> a, point<S,U> b)
{
return util::max (abs (a - b));
}
}

View File

@ -47,6 +47,7 @@ main (int, char**) {
CHECK_EQ (pf.template cast<point2u::value_type> (), pu);
}
// redim to 4-dimension homogenous coords
{
const point2f p (3, 4);
const point4f q = p.homog<4> ();
@ -57,6 +58,17 @@ main (int, char**) {
CHECK_EQ (q.w, 1);
}
// trivial checks for distance metrics
{
const point2f a (1, 2);
const point2f b (9, 5);
CHECK_EQ (distance2 (a, b), 73.f);
CHECK_EQ (distance (a, b), std::sqrt (73.f));
CHECK_EQ (manhattan (a, b), 11.f);
CHECK_EQ (chebyshev (a, b), 8.f);
}
util::TAP::logger tap;
tap.todo ("convert to TAP");
tap.skip ("convert to TAP");
}