/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef VCG_USE_EIGEN #include "deprecated_point3.h" #else #ifndef __VCGLIB_POINT3 #define __VCGLIB_POINT3 #include "../math/eigen.h" #include namespace vcg{ template class Point3; } namespace Eigen{ template struct ei_traits > : ei_traits > {}; template struct NumTraits > : NumTraits { enum { ReadCost = 3, AddCost = 3, MulCost = 3 }; }; } namespace vcg { /** \addtogroup space */ /*@{*/ /** The templated class for representing a point in 3D space. The class is templated over the ScalarType class that is used to represent coordinates. All the usual operator overloading (* + - ...) is present. */ template class Box3; template class Point3 : public Eigen::Matrix<_Scalar,3,1> { typedef Eigen::Matrix<_Scalar,3,1> _Base; using _Base::coeff; using _Base::coeffRef; using _Base::setZero; using _Base::data; using _Base::V; public: _EIGEN_GENERIC_PUBLIC_INTERFACE(Point3,_Base); typedef Scalar ScalarType; VCG_EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Point3) enum {Dimension = 3}; //@{ /** @name Standard Constructors and Initializers No casting operators have been introduced to avoid automatic unattended (and costly) conversion between different point types **/ inline Point3 () {} inline Point3 ( const Scalar nx, const Scalar ny, const Scalar nz ) : Base(nx,ny,nz) {} inline Point3 ( Point3 const & p ) : Base(p) {} inline Point3 ( const Scalar nv[3] ) : Base(nv) {} template inline Point3(const Eigen::MatrixBase& other) : Base(other) {} /// Padding function: give a default 0 value to all the elements that are not in the [0..2] range. /// Useful for managing in a consistent way object that could have point2 / point3 / point4 inline Scalar Ext( const int i ) const { if(i>=0 && i<=2) return data()[i]; else return 0; } template inline void Import( const Eigen::MatrixBase& b ) { EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3); data()[0] = Scalar(b[0]); data()[1] = Scalar(b[1]); data()[2] = Scalar(b[2]); } template static inline Point3 Construct( const Point3 & b ) { return Point3(Scalar(b[0]),Scalar(b[1]),Scalar(b[2])); } template static inline Point3 Construct( const Q & P0, const Q & P1, const Q & P2) { return Point3(Scalar(P0),Scalar(P1),Scalar(P2)); } static inline Point3 Construct( const Point3 & b ) { return b; } //@} //@{ /** @name Data Access. access to data is done by overloading of [] or explicit naming of coords (x,y,z)**/ inline const Scalar &X() const { return data()[0]; } inline const Scalar &Y() const { return data()[1]; } inline const Scalar &Z() const { return data()[2]; } inline Scalar &X() { return data()[0]; } inline Scalar &Y() { return data()[1]; } inline Scalar &Z() { return data()[2]; } inline Scalar & V( const int i ) { assert(i>=0 && i<3); return data()[i]; } inline const Scalar & V( const int i ) const { assert(i>=0 && i<3); return data()[i]; } //@} //@{ /** @name Classical overloading of operators Note **/ // Scalatura differenziata inline Point3 & Scale( const Scalar sx, const Scalar sy, const Scalar sz ) { data()[0] *= sx; data()[1] *= sy; data()[2] *= sz; return *this; } inline Point3 & Scale( const Point3 & p ) { data()[0] *= p.data()[0]; data()[1] *= p.data()[1]; data()[2] *= p.data()[2]; return *this; } /** * Convert to polar coordinates from cartesian coordinates. * * Theta is the azimuth angle and ranges between [0, 360) degrees. * Phi is the elevation angle (not the polar angle) and ranges between [-90, 90] degrees. * * /note Note that instead of the classical polar angle, which ranges between * 0 and 180 degrees we opt for the elevation angle to obtain a more * intuitive spherical coordinate system. */ void ToPolar(Scalar &ro, Scalar &theta, Scalar &phi) const { ro = this->norm(); theta = (Scalar)atan2(data()[2], data()[0]); phi = (Scalar)asin(data()[1]/ro); } /** * Convert from polar coordinates to cartesian coordinates. * * Theta is the azimuth angle and ranges between [0, 360) degrees. * Phi is the elevation angle (not the polar angle) and ranges between [-90, 90] degrees. * * \note Note that instead of the classical polar angle, which ranges between * 0 and 180 degrees, we opt for the elevation angle to obtain a more * intuitive spherical coordinate system. */ void FromPolar(const Scalar &ro, const Scalar &theta, const Scalar &phi) { data()[0]= ro*cos(theta)*cos(phi); data()[1]= ro*sin(phi); data()[2]= ro*sin(theta)*cos(phi); } Box3<_Scalar> GetBBox(Box3<_Scalar> &bb) const; //@} //@{ /** @name Comparison Operators. Note that the reverse z prioritized ordering, useful in many situations. **/ inline bool operator < ( Point3 const & p ) const { return (data()[2]!=p.data()[2])?(data()[2] ( Point3 const & p ) const { return (data()[2]!=p.data()[2])?(data()[2]>p.data()[2]): (data()[1]!=p.data()[1])?(data()[1]>p.data()[1]): (data()[0]>p.data()[0]); } inline bool operator <= ( Point3 const & p ) const { return (data()[2]!=p.data()[2])?(data()[2]< p.data()[2]): (data()[1]!=p.data()[1])?(data()[1]< p.data()[1]): (data()[0]<=p.data()[0]); } inline bool operator >= ( Point3 const & p ) const { return (data()[2]!=p.data()[2])?(data()[2]> p.data()[2]): (data()[1]!=p.data()[1])?(data()[1]> p.data()[1]): (data()[0]>=p.data()[0]); } //@} }; // end class definition // versione uguale alla precedente ma che assume che i due vettori sono unitari template inline Scalar AngleN( Point3 const & p1, Point3 const & p2 ) { Scalar w = p1*p2; if(w>1) w = 1; else if(w<-1) w=-1; return (Scalar) acos(w); } template inline Point3 & Normalize( Point3 & p ) { p.Normalize(); return p; } // Dot product preciso numericamente (solo double!!) // Implementazione: si sommano i prodotti per ordine di esponente // (prima le piu' grandi) template double stable_dot ( Point3 const & p0, Point3 const & p1 ) { Scalar k0 = p0.data()[0]*p1.data()[0]; Scalar k1 = p0.data()[1]*p1.data()[1]; Scalar k2 = p0.data()[2]*p1.data()[2]; int exp0,exp1,exp2; frexp( double(k0), &exp0 ); frexp( double(k1), &exp1 ); frexp( double(k2), &exp2 ); if( exp0 Scalar PSDist( const Point3 & p, const Point3 & v1, const Point3 & v2, Point3 & q ) { Point3 e = v2-v1; Scalar t = ((p-v1).dot(e))/e.SquaredNorm(); if(t<0) t = 0; else if(t>1) t = 1; q = v1+e*t; return Distance(p,q); } template void GetUV( Point3 &n,Point3 &u, Point3 &v, Point3 up=(Point3(0,1,0)) ) { n.Normalize(); const double LocEps=double(1e-7); u=n^up; double len = u.Norm(); if(len < LocEps) { if(fabs(n[0])(1,0,0); // x is the min else up=Point3(0,0,1); // z is the min }else { if(fabs(n[1])(0,1,0); // y is the min else up=Point3(0,0,1); // z is the min } u=n^up; } u.Normalize(); v=n^u; v.Normalize(); Point3 uv=u^v; } template inline Point3 Abs(const Point3 & p) { return (Point3(math::Abs(p[0]), math::Abs(p[1]), math::Abs(p[2]))); } // probably a more uniform naming should be defined... template inline Point3 LowClampToZero(const Point3 & p) { return (Point3(math::Max(p[0], (SCALARTYPE)0), math::Max(p[1], (SCALARTYPE)0), math::Max(p[2], (SCALARTYPE)0))); } typedef Point3 Point3s; typedef Point3 Point3i; typedef Point3 Point3f; typedef Point3 Point3d; /*@}*/ } // end namespace #endif #endif