Shinya Kitaoka 810553
#pragma once
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TCG_POINT_OPS_H
Toshihiro Shimizu 890ddd
#define TCG_POINT_OPS_H
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "point.h"
Toshihiro Shimizu 890ddd
#include "numeric_ops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  \file     tcg_point_ops.h
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \brief    This file contains useful functions to deal with \a planar objects
Toshihiro Shimizu 890ddd
            (\a two dimensions) up to points and lines.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************************
Toshihiro Shimizu 890ddd
//    (Planar) Point  Operations
Toshihiro Shimizu 890ddd
//*****************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace tcg {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Contains useful functions to deal with \a planar objects
Toshihiro Shimizu 890ddd
  (\a two dimensions) up to points and lines.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace point_ops {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point NaP() {
Shinya Kitaoka 120a6e
  return Point(numeric_ops::NaN<typename point_traits<point="">::value_type>(),</typename>
Shinya Kitaoka 120a6e
               numeric_ops::NaN<typename point_traits<point="">::value_type>());</typename>
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point operator+(const Point &a, const Point &b) {
Shinya Kitaoka 120a6e
  return Point(a.x + b.x, a.y + b.y);
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point operator-(const Point &a, const Point &b) {
Shinya Kitaoka 120a6e
  return Point(a.x - b.x, a.y - b.y);
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point,="" scalar="" typename=""></typename>
Shinya Kitaoka 120a6e
inline Point operator*(Scalar a, const Point &b) {
Shinya Kitaoka 120a6e
  return Point(a * b.x, a * b.y);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point,="" scalar="" typename=""></typename>
Shinya Kitaoka 120a6e
inline Point operator/(const Point &a, Scalar b) {
Shinya Kitaoka 120a6e
  return Point(a.x / b, a.y / b);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type operator*(const Point &a,</point>
Shinya Kitaoka 120a6e
                                                          const Point &b) {
Shinya Kitaoka 120a6e
  return a.x * b.x + a.y * b.y;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type cross(const Point &a,</point>
Shinya Kitaoka 120a6e
                                                      const Point &b) {
Shinya Kitaoka 120a6e
  return a.x * b.y - a.y * b.x;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type norm2(const Point &a) {</point>
Shinya Kitaoka 120a6e
  return a * a;
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::float_type norm(const Point &a) {</point>
Shinya Kitaoka 120a6e
  return sqrt(typename point_traits<point>::float_type(a * a));</point>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type dist2(const Point &a,</point>
Shinya Kitaoka 120a6e
                                                      const Point &b) {
Shinya Kitaoka 120a6e
  return norm2(b - a);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type dist(const Point &a,</point>
Shinya Kitaoka 120a6e
                                                     const Point &b) {
Shinya Kitaoka 120a6e
  return norm(b - a);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type absDist(const Point &a,</point>
Shinya Kitaoka 120a6e
                                                        const Point &b) {
Shinya Kitaoka 120a6e
  typename point_traits<point>::value_type xDist = std::abs(b.x - a.x),</point>
Shinya Kitaoka 120a6e
                                           yDist = std::abs(b.y - a.y);
Shinya Kitaoka 120a6e
  return (xDist < yDist) ? yDist : xDist;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point normalized(const Point &v) {
Shinya Kitaoka 120a6e
  return v / norm(v);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point normalized(const Point &v,
Shinya Kitaoka 120a6e
                        typename point_traits<point>::value_type tol) {</point>
Shinya Kitaoka 120a6e
  typename point_traits<point>::value_type vNorm = norm(v);</point>
Shinya Kitaoka 120a6e
  return (vNorm >= tol) ? v / vNorm : NaP<point>();</point>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline void normalize(Point &v) {
Shinya Kitaoka 120a6e
  v = normalized(v);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline bool normalize(Point &v, typename point_traits<point>::value_type tol) {</point>
Shinya Kitaoka 120a6e
  typename point_traits<point>::value_type vNorm = norm(v);</point>
Shinya Kitaoka 120a6e
  return (vNorm >= tol) ? (v = v / vNorm, true) : (v = NaP<point>(), false);</point>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point direction(const Point &a, const Point &b) {
Shinya Kitaoka 120a6e
  return normalized(b - a);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point direction(const Point &a, const Point &b,
Shinya Kitaoka 120a6e
                       typename point_traits<point>::value_type tol) {</point>
Shinya Kitaoka 120a6e
  return normalized<point>(b - a, tol);</point>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns the left orthogonal of passed point
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point ortLeft(const Point &p) {
Shinya Kitaoka 120a6e
  return Point(-p.y, p.x);
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns the right orthogonal of passed point
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point ortRight(const Point &p) {
Shinya Kitaoka 120a6e
  return Point(p.y, -p.x);
Shinya Kitaoka 120a6e
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Shinya Kitaoka 120a6e
  Returns the bisecting direction \p bd between \p d0 and \p d1, in the plane
Shinya Kitaoka 120a6e
  region
Toshihiro Shimizu 890ddd
  where <tt>d x d1 > 0</tt>
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point bisecant(const Point &d0, const Point &d1) {
Shinya Kitaoka 120a6e
  Point sum   = d0 + d1;
Shinya Kitaoka 120a6e
  double norm = sum * sum;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (norm < 1)
Shinya Kitaoka 120a6e
    sum = ortLeft(d0 - d1), norm = sum * sum;
Shinya Kitaoka 120a6e
  else if (cross(d0, d1) < 0)
Shinya Kitaoka 120a6e
    sum.x = -sum.x, sum.y = -sum.y;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  norm = sqrt(norm);
Shinya Kitaoka 120a6e
  sum.x /= norm, sum.y /= norm;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return sum;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns the projection of point \p p on line <tt>a -> d</tt>
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline Point projection(const Point &p, const Point &a, const Point &d) {
Shinya Kitaoka 120a6e
  return a + ((p.x - a.x) * d.x + (p.y - a.y) * d.y) * d;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns res: <tt>p = p0 + res.x * (p1 - p0) + res.y * (p1 - p0)_orth</tt>
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
Point ortCoords(const Point &p, const Point &p0, const Point &p1) {
Shinya Kitaoka 120a6e
  Point v01(p1.x - p0.x, p1.y - p0.y);
Shinya Kitaoka 120a6e
  Point v02(p.x - p0.x, p.y - p0.y);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  typename point_traits<point>::value_type den = v01.x * v01.x + v01.y * v01.y;</point>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return Point((v01.x * v02.x + v01.y * v02.y) / den,
Shinya Kitaoka 120a6e
               (v01.y * v02.x - v01.x * v02.y) / den);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns res: <tt>p = p0 + res.x * (p1 - p0) + res.y * (p2 - p0)</tt>
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
Point triCoords(const Point &p, const Point &p0, const Point &p1,
Shinya Kitaoka 120a6e
                const Point &p2) {
Shinya Kitaoka 120a6e
  Point v01(p1.x - p0.x, p1.y - p0.y);
Shinya Kitaoka 120a6e
  Point v02(p2.x - p0.x, p2.y - p0.y);
Shinya Kitaoka 120a6e
  Point p_p0(p.x - p0.x, p.y - p0.y);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  typename point_traits<point>::value_type det = v01.x * v02.y - v02.x * v01.y;</point>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return Point((v02.y * p_p0.x - v02.x * p_p0.y) / det,
Shinya Kitaoka 120a6e
               (v01.x * p_p0.y - v01.y * p_p0.x) / det);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns the signed distance of point \p p from line <tt>a->d</tt>, where
Shinya Kitaoka 120a6e
//! positive means at its left.
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type lineSignedDist(const Point &p,</point>
Shinya Kitaoka 120a6e
                                                               const Point &a,
Shinya Kitaoka 120a6e
                                                               const Point &d) {
Shinya Kitaoka 120a6e
  return (p.y - a.y) * d.x - (p.x - a.x) * d.y;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns the distance of point \p p from line <tt>a->d</tt>
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type lineDist(const Point &p,</point>
Shinya Kitaoka 120a6e
                                                         const Point &a,
Shinya Kitaoka 120a6e
                                                         const Point &d) {
Shinya Kitaoka 120a6e
  return std::abs(lineSignedDist(p, a, d));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Shinya Kitaoka 120a6e
  \brief Returns the side of line <tt>a->d</tt> where point \p p lies, where \p
Shinya Kitaoka 120a6e
  1 means left,
Toshihiro Shimizu 890ddd
  \p -1 right, and \p 0 below tolerance (ie on the line).
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Toshihiro Shimizu 890ddd
inline int lineSide(const Point &p, const Point &a, const Point &d,
Shinya Kitaoka 120a6e
                    typename point_traits<point>::value_type tol = 0) {</point>
Shinya Kitaoka 120a6e
  typename point_traits<point>::value_type dist = lineSignedDist(p, a, d);</point>
Shinya Kitaoka 120a6e
  return (dist > tol) ? 1 : (dist < -tol) ? -1 : 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
typename point_traits<point>::value_type segDist(const Point &a, const Point &b,</point>
Shinya Kitaoka 120a6e
                                                 const Point &p) {
Shinya Kitaoka 120a6e
  Point v(b - a), w;
Shinya Kitaoka 120a6e
  v = v / norm(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if ((w = p - a) * v < 0) return norm(w);
Shinya Kitaoka 120a6e
  if ((w = p - b) * (-v) < 0) return norm(w);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  v = Point(-v.y, v.x);
Shinya Kitaoka 120a6e
  return std::abs((p - a) * v);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type rad(const Point &p) {</point>
Shinya Kitaoka 120a6e
  return atan2(p.y, p.x);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Shinya Kitaoka 120a6e
  Computes the angle, in radians, between \a unnormalized directions \p v1 and
Shinya Kitaoka 120a6e
  \p v2.
Shinya Kitaoka 120a6e
  \return The angle between the specified directions, in the range
Shinya Kitaoka 120a6e
  <tt>[-consts::pi, consts::pi]</tt>.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type angle(const Point &v1,</point>
Shinya Kitaoka 120a6e
                                                      const Point &v2) {
Shinya Kitaoka 120a6e
  return numeric_ops::mod<typename point_traits<point="">::value_type>(</typename>
Shinya Kitaoka 120a6e
      rad(v2) - rad(v1), -M_PI, M_PI);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline typename point_traits<point>::value_type segCoord(const Point &p,</point>
Shinya Kitaoka 120a6e
                                                         const Point &p0,
Shinya Kitaoka 120a6e
                                                         const Point &p1) {
Shinya Kitaoka 120a6e
  Point p1_p0 = p1 - p0;
Shinya Kitaoka 120a6e
  return ((p - p0) * p1_p0) / (p1_p0 * p1_p0);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Calculates scalars \p s and \p t:  <tt>a + s * v == c + t * w</tt>
Shinya Kitaoka 120a6e
  \return Whether the calculation succeeded with the specified tolerance
Shinya Kitaoka 120a6e
  parameter.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  \note In case the absolute value of the system's determinant is less or equal
Shinya Kitaoka 120a6e
  to the
Shinya Kitaoka 120a6e
        passed tolerance, the values numeric_ops::NaN() are returned for \p s
Shinya Kitaoka 120a6e
  and \p t.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
bool intersectionCoords(const Point &a, const Point &v, const Point &c,
Shinya Kitaoka 120a6e
                        const Point &w,
Shinya Kitaoka 120a6e
                        typename point_traits<point>::value_type &s,</point>
Shinya Kitaoka 120a6e
                        typename point_traits<point>::value_type &t,</point>
Shinya Kitaoka 120a6e
                        typename point_traits<point>::value_type detTol = 0) {</point>
Shinya Kitaoka 120a6e
  typedef typename point_traits<point>::value_type value_type;</point>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  value_type det = v.y * w.x - v.x * w.y;
Shinya Kitaoka 120a6e
  if (std::abs(det) < detTol) {
Shinya Kitaoka 120a6e
    s = t = numeric_ops::NaN<value_type>();</value_type>
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  value_type c_aX = c.x - a.x, c_aY = c.y - a.y;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  s = (w.x * c_aY - w.y * c_aX) / det;
Shinya Kitaoka 120a6e
  t = (v.x * c_aY - v.y * c_aX) / det;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Calculates scalars \p s and \p t:  <tt>a + s * (b-a) == c + t * (d-c)</tt>
Shinya Kitaoka 120a6e
  \return Whether the calculation succeeded with the specified tolerance
Shinya Kitaoka 120a6e
  parameter.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  \note In case the absolute value of the system's determinant is less or equal
Shinya Kitaoka 120a6e
  to the
Shinya Kitaoka 120a6e
        passed tolerance, the values numeric_ops::NaN() are returned for \p s
Shinya Kitaoka 120a6e
  and \p t.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Shinya Kitaoka 120a6e
inline bool intersectionSegCoords(
Shinya Kitaoka 120a6e
    const Point &a, const Point &b, const Point &c, const Point &d,
Shinya Kitaoka 120a6e
    typename point_traits<point>::value_type &s,</point>
Shinya Kitaoka 120a6e
    typename point_traits<point>::value_type &t,</point>
Shinya Kitaoka 120a6e
    typename point_traits<point>::value_type detTol = 0) {</point>
Shinya Kitaoka 120a6e
  return intersectionCoords(a, b - a, c, d - c, s, t, detTol);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  \brief  Stores the 6 values of the bidimensional affine transform mapping
Toshihiro Shimizu 890ddd
          \p p0, \p p1, \p p2 into \p q0, \p q1, \p q1.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Returned values are in row-major order, with the translational
Shinya Kitaoka 120a6e
  component
Toshihiro Shimizu 890ddd
  at multiple of 3 indexes.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Returns numeric_ops::NaN() on each entry if the system could not be solved
Shinya Kitaoka 120a6e
  under
Toshihiro Shimizu 890ddd
  the specified determinant threshold.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  \return  Whether the affine could be solved under the specified constraints
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Toshihiro Shimizu 890ddd
bool affineMap(const Point &p0, const Point &p1, const Point &p2,
Shinya Kitaoka 120a6e
               const Point &q0, const Point &q1, const Point &q2,
Shinya Kitaoka 120a6e
               typename point_traits<point>::value_type affValues[],</point>
Shinya Kitaoka 120a6e
               typename point_traits<point>::value_type detTol = 0) {</point>
Shinya Kitaoka 120a6e
  typedef typename point_traits<point>::value_type value_type;</point>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build the linear transform mapping (p1-p0) and (p2-p0) into (q1-q0) and
Shinya Kitaoka 120a6e
  // (q2-q0)
Shinya Kitaoka 120a6e
  value_type p1_p0_x = p1.x - p0.x, p1_p0_y = p1.y - p0.y;
Shinya Kitaoka 120a6e
  value_type p2_p0_x = p2.x - p0.x, p2_p0_y = p2.y - p0.y;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  value_type det = p1_p0_x * p2_p0_y - p1_p0_y * p2_p0_x;
Shinya Kitaoka 120a6e
  if (std::abs(det) < detTol) {
Shinya Kitaoka 120a6e
    affValues[0] = affValues[1] = affValues[2] = affValues[3] = affValues[4] =
Shinya Kitaoka 120a6e
        affValues[5] = numeric_ops::NaN<value_type>();</value_type>
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  value_type q1_q0_x = q1.x - q0.x, q1_q0_y = q1.y - q0.y;
Shinya Kitaoka 120a6e
  value_type q2_q0_x = q2.x - q0.x, q2_q0_y = q2.y - q0.y;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  affValues[2] = p2_p0_y / det;
Shinya Kitaoka 120a6e
  affValues[5] = -p2_p0_x / det;  // 2 and 5 used as temps here
Shinya Kitaoka 120a6e
  affValues[3] = -p1_p0_y / det;
Shinya Kitaoka 120a6e
  affValues[4] = p1_p0_x / det;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  affValues[0] = q1_q0_x * affValues[2] + q2_q0_x * affValues[3];
Shinya Kitaoka 120a6e
  affValues[1] = q1_q0_x * affValues[5] + q2_q0_x * affValues[4];
Shinya Kitaoka 120a6e
  affValues[3] = q1_q0_y * affValues[2] + q2_q0_y * affValues[3];
Shinya Kitaoka 120a6e
  affValues[4] = q1_q0_y * affValues[5] + q2_q0_y * affValues[4];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Finally, add the translational component
Shinya Kitaoka 120a6e
  affValues[2] = q0.x - affValues[0] * p0.x - affValues[1] * p0.y;
Shinya Kitaoka 120a6e
  affValues[5] = q0.y - affValues[3] * p0.x - affValues[4] * p0.y;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Shinya Kitaoka 120a6e
  \brief  Calculates the best fit line passing through \p p whose \p n samples
Shinya Kitaoka 120a6e
  have the specified
Toshihiro Shimizu 890ddd
          coordinate sums
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  \note   Returned unnormalized direction \p v may be NaP() in case no
Shinya Kitaoka 120a6e
  preferential direction could
Toshihiro Shimizu 890ddd
          be chosen
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Toshihiro Shimizu 890ddd
bool bestFit(const Point &p, Point &v,
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums_x,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums_y,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums2_x,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums2_y,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums_xy,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type n) {</point>
Shinya Kitaoka 120a6e
  typedef typename point_traits<point>::value_type value_type;</point>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  sums_x /= n;
Shinya Kitaoka 120a6e
  sums_y /= n;
Shinya Kitaoka 120a6e
  sums2_x /= n;
Shinya Kitaoka 120a6e
  sums2_y /= n;
Shinya Kitaoka 120a6e
  sums_xy /= n;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  value_type a = sums2_x - 2.0 * p.x * sums_x + sq(p.x);  // Always >= 0
Shinya Kitaoka 120a6e
  value_type b = sums_xy - p.x * sums_y - p.y * sums_x + p.x * p.y;
Shinya Kitaoka 120a6e
  value_type c = sums2_y - 2.0 * p.y * sums_y + sq(p.y);  // Always >= 0
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // The best-fit direction is an eigenvector of matrix [a, b; b, c]'s highest
Shinya Kitaoka 120a6e
  // eigenvalue.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double trace = 0.5 * (a + c);
Shinya Kitaoka 120a6e
  double det   = a * c - b * b;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double traceSq = trace * trace;
Shinya Kitaoka 120a6e
  if (traceSq < det) {
Shinya Kitaoka 120a6e
    v = NaP<point>();</point>
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double eigen = trace + sqrt(traceSq - det);  // plus takes the greater eigen
Shinya Kitaoka 120a6e
  a -= eigen, c -= eigen;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Take the most 'normed' obvious eigenvector
Shinya Kitaoka 120a6e
  if (std::abs(a) > std::abs(c))
Shinya Kitaoka 120a6e
    v.x = b, v.y = -a;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    v.x = -c, v.y = b;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Shinya Kitaoka 120a6e
  Calculates the best fit line whose n samples have the specified coordinate
Shinya Kitaoka 120a6e
  sums.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  \note  Returned point \p p is the samples mean, while (not normalized)
Shinya Kitaoka 120a6e
  direction \p v
Toshihiro Shimizu 890ddd
         may be NaP in case no preferential direction could be chosen.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point=""></typename>
Toshihiro Shimizu 890ddd
bool bestFit(Point &p, Point &v,
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums_x,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums_y,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums2_x,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums2_y,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type sums_xy,</point>
Shinya Kitaoka 120a6e
             typename point_traits<point>::value_type n) {</point>
Shinya Kitaoka 120a6e
  p.x = sums_x / n, p.y = sums_y / n;
Shinya Kitaoka 120a6e
  return bestFit((const Point &)p, v, sums_x, sums_y, sums2_x, sums2_y, sums_xy,
Shinya Kitaoka 120a6e
                 n);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Calculates the best fit line of the specified points.
Toshihiro Shimizu 890ddd
  This is a mostly overloaded version of bestFit without explicit sums.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
template <typename point,="" point_iterator="" point_ref,="" typename=""></typename>
Shinya Kitaoka 120a6e
bool bestFit(Point_ref p, Point &d, point_iterator begin, point_iterator end) {
Shinya Kitaoka 120a6e
  typedef typename point_traits<point>::value_type value_type;</point>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  value_type sums_x, sums_y, sums2_x, sums2_y, sums_xy;
Shinya Kitaoka 120a6e
  sums_x = sums_y = sums2_x = sums2_y = sums_xy = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  size_t n = 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  point_iterator it;
Shinya Kitaoka 120a6e
  for (it = begin; it != end; ++it, ++n) {
Shinya Kitaoka 120a6e
    const Point &p = *it;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    sums_x += p.x, sums_y += p.y;
Shinya Kitaoka 120a6e
    sums2_x += p.x * p.x, sums2_y += p.y * p.y;
Shinya Kitaoka 120a6e
    sums_xy += p.x * p.y;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return bestFit(p, d, sums_x, sums_y, sums2_x, sums2_y, sums_xy, n);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
}  // namespace tcg::point_ops
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
#endif  // TCG_POINT_OPS_H