|
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
|