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); auto c1 = dot (w, v);
if (c1 <= 0) if (c1 <= 0)
return m_points[0].distance (target); return util::distance (target, m_points[0]);
auto c2 = dot (v, v); auto c2 = dot (v, v);
if (c2 <= c1) if (c2 <= c1)
return m_points[1].distance (target); return util::distance (target, m_points[1]);
auto b = c1 / c2; auto b = c1 / c2;
auto p = m_points[0] + b * v; auto p = m_points[0] + b * v;
return p.distance (target); return util::distance (target, p);
} }
} }
@ -271,12 +271,12 @@ namespace util {
continue; continue;
if (t <= 0) if (t <= 0)
dist = min (dist, p0.distance (target)); dist = min (dist, util::distance (target, p0));
else if (t > 1) else if (t > 1)
dist = min (p2.distance (target)); dist = min (util::distance (target, p2));
else { else {
auto p = eval (t); 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_l = b.eval (t_l);
util::point2f p_r = b.eval (t_r); util::point2f p_r = b.eval (t_r);
float d_l = p_l.distance (target); float d_l = util::distance (target, p_l);
float d_r = p_r.distance (target); float d_r = util::distance (target, p_r);
if (d_l < d) { return refine_cubic (b, target, t_l, d_l, p); } 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); } 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)); lookup[i] = eval (i / float (SUBDIV - 1));
size_t best = 0; size_t best = 0;
for (size_t i = 1; i < lookup.size (); ++i) for (size_t i = 1; i < lookup.size (); ++i) {
if (lookup[i].distance2 (target) < lookup[best].distance2 (target)) auto d_i = util::distance2 (target, lookup[i]);
auto d_b = util::distance2 (target, lookup[best]);
if (d_i < d_b)
best = i; best = i;
}
return refine_cubic (*this, return refine_cubic (*this,
target, target,
best / float (SUBDIV - 1), best / float (SUBDIV - 1),
lookup[best].distance (target), util::distance (target, lookup[best]),
1.f / SUBDIV); 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); CHECK (off.y >= 0 && off.y <= 1);
pos += off; 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)); std::sort (std::begin (distances), std::end (distances));
CHECK_GE (distances[0], 0); CHECK_GE (distances[0], 0);

View File

@ -33,11 +33,6 @@ namespace util {
{ {
using coord::base<S,T,util::point,coord::xyzw>::base; 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> to (point) const;
vector<S,T> from (point) const; vector<S,T> from (point) const;
@ -48,6 +43,19 @@ namespace util {
void sanity (void) const; 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 // iostream operators
template <size_t S, typename T> template <size_t S, typename T>
std::ostream& operator<< (std::ostream&, point<S,T>); std::ostream& operator<< (std::ostream&, point<S,T>);

View File

@ -19,50 +19,6 @@
#include <algorithm> #include <algorithm>
namespace util { 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. /// expand point to use homogenous coordinates of a higher dimension.
/// ie, fill with (0,..,0,1) /// ie, fill with (0,..,0,1)
@ -88,4 +44,50 @@ namespace util {
return out; 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); CHECK_EQ (pf.template cast<point2u::value_type> (), pu);
} }
// redim to 4-dimension homogenous coords
{ {
const point2f p (3, 4); const point2f p (3, 4);
const point4f q = p.homog<4> (); const point4f q = p.homog<4> ();
@ -57,6 +58,17 @@ main (int, char**) {
CHECK_EQ (q.w, 1); 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; util::TAP::logger tap;
tap.todo ("convert to TAP"); tap.skip ("convert to TAP");
} }