/* * 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 #include 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 ; }