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