owlps/owlps-positioning/src/point3d.cc

187 lines
3.2 KiB
C++

/*
* This file is part of the Owl Positioning System (OwlPS).
* OwlPS is a project of the University of Franche-Comté
* (Université de Franche-Comté), France.
*/
#include "point3d.hh"
#include "posutil.hh"
#include "posexcept.hh"
#include <sstream>
#include <boost/functional/hash.hpp>
using namespace std ;
/* *** Constructors *** */
Point3D::Point3D(const string &source)
{
float pos[3] ;
istringstream iss(source) ;
for (int i = 0 ; i < 2 ; ++i)
{
iss >> pos[i] ;
if (iss.get() != ';')
throw malformed_input_data(
"Point3D(string): cannot extract coordinates!") ;
}
iss >> pos[2] ;
set_coordinates(pos) ;
}
/* *** Distance operations *** */
/**
* The distance is not square rooted after the computation, in order
* to optimise comparisons.
*/
float Point3D::square_distance(const Point3D &source) const
{
return
(x - source.x) * (x - source.x) +
(y - source.y) * (y - source.y) +
(z - source.z) * (z - source.z) ;
}
/**
* The distance is not square rooted after the computation, in order
* to optimise comparisons.
*/
float Point3D::square_distance(const float _x,
const float _y,
const float _z) const
{
return
(x - _x) * (x - _x) +
(y - _y) * (y - _y) +
(z - _z) * (z - _z) ;
}
/**
* A, B and C are three points, A being the current Point3D (*this).
* If the points are aligned, the angle returned is always 0° (and not
* 180°, even in the case where A is on BC).
* @returns The angle BÂC, in the interval [0, 180] degrees.
*/
double Point3D::angle(const Point3D &b, const Point3D &c) const
{
double
sq_ab = square_distance(b),
sq_ac = square_distance(c),
sq_bc = b.square_distance(c) ;
if (sq_ab == 0 || sq_ac == 0 || sq_bc == 0)
return 0 ;
double
ab = sqrt(sq_ab),
ac = sqrt(sq_ac) ;
double cos_bac = (sq_ab + sq_ac - sq_bc) / (2 * ab * ac) ;
double bac = acos(cos_bac) ;
return PosUtil::rad2deg(bac) ;
}
/* *** Operators *** */
Point3D& Point3D::operator=(const Point3D &source)
{
if (this == &source)
return *this ;
x = source.x ;
y = source.y ;
z = source.z ;
return *this ;
}
bool Point3D::operator==(const Point3D &source) const
{
if (this == &source)
return true ;
return
x == source.x &&
y == source.y &&
z == source.z ;
}
bool Point3D::operator<(const Point3D &source) const
{
if (x < source.x)
return true ;
if (x > source.x)
return false ;
if (y < source.y)
return true ;
if (y > source.y)
return false ;
if (z < source.z)
return true ;
return false ;
}
Point3D::operator std::string(void) const
{
ostringstream oss ;
oss << *this ;
return oss.str() ;
}
/**
* @return \em true if either #x, #y or #z is non-zero.
* @return \em false if #x, #y and #z are defined to 0.
*/
Point3D::operator bool(void) const
{
return
x != 0 &&
y != 0 &&
z != 0 ;
}
ostream& operator<<(ostream &os, const Point3D &p)
{
os << "(" << p.x << ";" << p.y << ";" << p.z << ")" ;
return os ;
}
size_t hash_value(const Point3D &source)
{
size_t seed = 0 ;
boost::hash_combine(seed, source.x) ;
boost::hash_combine(seed, source.y) ;
boost::hash_combine(seed, source.z) ;
return seed ;
}