/* * This file is part of the Owl Positioning System (OwlPS) project. * It is subject to the copyright notice and license terms in the * COPYRIGHT.t2t file found in the top-level directory of this * distribution and at * http://code.lm7.fr/p/owlps/source/tree/master/COPYRIGHT.t2t * No part of the OwlPS Project, including this file, may be copied, * modified, propagated, or distributed except according to the terms * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be * distributed along with this file, either separately or by replacing * this notice by the COPYRITGHT.t2t file's contents. */ #include "point3d.hh" #include "posutil.hh" #include "posexcept.hh" #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_2d(const Point3D &source) const { return (x - source.x) * (x - source.x) + (y - source.y) * (y - source.y) ; } /** * 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) ; } /** * A, B and C are three points, A being the current Point3D (*this). * This function computes the angle BÂC, in two dimensions (i.e. the Z * coordinate of the points is ignored). * * 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_2d(const Point3D &b, const Point3D &c) const { double sq_ab = square_distance_2d(b), sq_ac = square_distance_2d(c), sq_bc = b.square_distance_2d(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) ; } /** * #x and #y are updated with the rotated image of the point. * * Note that as this functions does a 2D rotation, the c.z is ignored, * and so is this->x. */ void Point3D::rotate_2d(const Point3D &c, float angle) { angle = PosUtil::deg2rad(angle) ; float new_x = cos(angle) * (x-c.x) - sin(angle) * (y-c.y) + c.x ; float new_y = sin(angle) * (x-c.x) + cos(angle) * (y-c.y) + c.y ; x = new_x ; y = new_y ; } /* *** 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() ; } /** * @returns `true` if either #x, #y or #z is non-zero. * @returns `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 ; }