vcglib/vcg/space/point.h

883 lines
26 KiB
C++

/****************************************************************************
* 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. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
Revision 1.4 2004/04/29 10:47:06 ganovelli
some siyntax error corrected
Revision 1.3 2004/04/05 12:36:43 tarini
unified version: PointBase version, with no guards "(N==3)"
Revision 1.1 2004/03/16 03:07:38 tarini
"dimensionally unified" version: first commit
****************************************************************************/
#ifndef __VCGLIB_POINT
#define __VCGLIB_POINT
#include <assert.h>
#include <vcg/math/base.h>
#include <vcg/space/space.h>
namespace vcg {
template <int N, class S>
class Point;
/** \addtogroup space */
/*@{*/
/**
The templated class for representing a point in R^N space.
The class is templated over the ScalarType class that is used to represent coordinates.
PointBase provides the interface and the common operators for points
of any dimensionality.
*/
template <int N, class S>
class PointBase
{
public:
typedef S ScalarType;
typedef VoidType ParamType;
typedef Point<N,S> PointType;
enum {Dimension=N};
protected:
/// The only data member. Hidden to user.
S _v[N];
public:
//@{
/** @name Standard Constructors and Initializers
No casting operators have been introduced to avoid automatic unattended (and costly) conversion between different PointType types
**/
inline PointBase () { };
// inline PointBase ( const S nv[N] );
/// 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 S Ext( const int i ) const
{
if(i>=0 && i<=N) return _v[i];
else return 0;
}
/// importer for points with different scalar type and-or dimensionality
template <int N2, class S2>
inline void Import( const Point<N2,S2> & b )
{
_v[0] = ScalarType(b[0]);
_v[1] = ScalarType(b[1]);
if (N>2) { if (N2>2) _v[2] = ScalarType(b[2]); else _v[2] = 0;};
if (N>3) { if (N2>3) _v[3] = ScalarType(b[3]); else _v[3] = 0;};
}
/// constructor for points with different scalar type and-or dimensionality
template <int N2, class S2>
static inline PointType Construct( const Point<N2,S2> & b )
{
PointType p; p.Import(b);
return p;
}
/// importer for homogeneous points
template <class S2>
inline void ImportHomo( const Point<N-1,S2> & b )
{
_v[0] = ScalarType(b[0]);
_v[1] = ScalarType(b[1]);
if (N>2) { _v[2] = ScalarType(_v[2]); };
_v[N-1] = 1.0;
}
/// constructor for homogeneus point.
template <int N2, class S2>
static inline PointType Construct( const Point<N-1,S2> & b )
{
PointType p; p.ImportHomo(b);
return p;
}
//@}
//@{
/** @name Data Access.
access to data is done by overloading of [] or explicit naming of coords (x,y,z)**/
inline S & operator [] ( const int i )
{
assert(i>=0 && i<N);
return _v[i];
}
inline const S & operator [] ( const int i ) const
{
assert(i>=0 && i<N);
return _v[i];
}
inline const S &X() const { return _v[0]; }
inline const S &Y() const { return _v[1]; }
inline const S &Z() const { static_assert(N>2); return _v[2]; }
/// W is in any case the last coordinate.
/// (in a 2D point, W() == Y(). In a 3D point, W()==Z()
/// in a 4D point, W() is a separate component)
inline const S &W() const { return _v[N-1]; }
inline S &X() { return _v[0]; }
inline S &Y() { return _v[1]; }
inline S &Z() { static_assert(N>2); return _v[2]; }
inline S &W() { return _v[N-1]; }
inline const S * V() const
{
return _v;
}
inline S & V( const int i )
{
assert(i>=0 && i<N);
return _v[i];
}
inline const S & V( const int i ) const
{
assert(i>=0 && i<N);
return _v[i];
}
//@}
//@{
/** @name Linearity for points
**/
/// sets a PointType to Zero
inline void Zero();
inline PointType operator + ( PointType const & p) const;
inline PointType operator - ( PointType const & p) const;
inline PointType operator * ( const S s ) const;
inline PointType operator / ( const S s ) const;
inline PointType & operator += ( PointType const & p);
inline PointType & operator -= ( PointType const & p);
inline PointType & operator *= ( const S s );
inline PointType & operator /= ( const S s );
inline PointType operator - () const;
//@}
//@{
/** @name Dot products (cross product "%" is defined olny for 3D points)
**/
/// Dot product
inline S operator * ( PointType const & p ) const;
/// slower version, more stable (double precision only)
inline S StableDot ( const PointType & p ) const;
//@}
//@{
/** @name Norms
**/
/// Euclidean norm
inline S Norm() const;
/// Euclidean norm, static version
template <class PT> static S Norm(const PT &p );
/// Squared Euclidean norm
inline S SquaredNorm() const;
/// Squared Euclidean norm, static version
template <class PT> static S SquaredNorm(const PT &p );
/// Normalization (division by norm)
inline PointType & Normalize();
/// Normalization (division by norm), static version
template <class PT> static PointType & Normalize(const PT &p);
/// Homogeneous normalization (division by W)
inline PointType & HomoNormalize();
/// norm infinity: largest absolute value of compoenet
inline S NormInfinity() const;
/// norm 1: sum of absolute values of components
inline S NormOne() const;
//@}
/// Signed area operator
/// a % b returns the signed area of the parallelogram inside a and b
inline S operator % ( PointType const & p ) const;
/// the sum of the components
inline S Sum() const;
/// returns the biggest component
inline S Max() const;
/// returns the smallest component
inline S Min() const;
/// returns the index of the biggest component
inline int MaxI() const;
/// returns the index of the smallest component
inline int MinI() const;
/// Per component scaling
inline PointType & Scale( const PointType & p );
/// Convert to polar coordinates
void ToPolar( S & ro, S & tetha, S & fi ) const
{
ro = Norm();
tetha = (S)atan2( _v[1], _v[0] );
fi = (S)acos( _v[2]/ro );
}
//@{
/** @name Comparison Operators.
Lexicographic order.
**/
inline bool operator == ( PointType const & p ) const;
inline bool operator != ( PointType const & p ) const;
inline bool operator < ( PointType const & p ) const;
inline bool operator > ( PointType const & p ) const;
inline bool operator <= ( PointType const & p ) const;
inline bool operator >= ( PointType const & p ) const;
//@}
//@{
/** @name
Glocal to Local and viceversa
(provided for uniformity with other spatial classes. trivial for points)
**/
inline PointType LocalToGlobal(ParamType p) const{
return *this; }
inline ParamType GlobalToLocal(PointType p) const{
ParamType p(); return p; }
//@}
}; // end class definition
template <class S>
class Point<2, S> : public PointBase<2,S> {
public:
typedef S ScalarType;
typedef Point<2,S> PointType;
//@{
/** @name Special members for 2D points. **/
/// default
inline Point (){}
/// yx constructor
inline Point ( const S a, const S b){
_v[0]=a; _v[1]=b; };
/// unary orthogonal operator (2D equivalent of cross product)
/// returns orthogonal vector (90 deg left)
inline Point operator ~ () const {
return Point ( -_v[2], _v[1] );
}
/// returns the angle with X axis (radiants, in [-PI, +PI] )
inline ScalarType &Angle(){
return math::Atan2(_v[1],_v[0]);}
/// transform the point in cartesian coords into polar coords
inline Point & ToPolar(){
ScalarType t = Angle();
_v[0] = Norm();
_v[1] = t;
return *this;}
/// transform the point in polar coords into cartesian coords
inline Point & ToCartesian() {
ScalarType l = _v[0];
_v[0] = (ScalarType)(l*math::Cos(_v[1]));
_v[1] = (ScalarType)(l*math::Sin(_v[1]));
return *this;}
/// rotates the point of an angle (radiants, counterclockwise)
inline Point & Rotate( const ScalarType rad ){
ScalarType t = _v[0];
ScalarType s = math::Sin(rad);
ScalarType c = math::Cos(rad);
_v[0] = _v[0]*c - _v[1]*s;
_v[1] = t *s + _v[1]*c;
return *this;}
//@}
//@{
/** @name Implementation of standard functions for 3D points **/
inline void Zero(){
_v[0]=0; _v[1]=0; };
inline Point ( const S nv[2] ){
_v[0]=nv[0]; _v[1]=nv[1]; };
inline Point operator + ( Point const & p) const {
return Point( _v[0]+p._v[0], _v[1]+p._v[1]); }
inline Point operator - ( Point const & p) const {
return Point( _v[0]-p._v[0], _v[1]-p._v[1]); }
inline Point operator * ( const S s ) const {
return Point( _v[0]*s, _v[1]*s ); }
inline Point operator / ( const S s ) const {
S t=1.0/s;
return Point( _v[0]*t, _v[1]*t ); }
inline Point operator - () const {
return Point ( -_v[0], -_v[1] ); }
inline Point & operator += ( Point const & p ) {
_v[0] += p._v[0]; _v[1] += p._v[1]; return *this; }
inline Point & operator -= ( Point const & p ) {
_v[0] -= p._v[0]; _v[1] -= p._v[1]; return *this; }
inline Point & operator *= ( const S s ) {
_v[0] *= s; _v[1] *= s; return *this; }
inline Point & operator /= ( const S s ) {
S t=1.0/s; _v[0] *= t; _v[1] *= t; return *this; }
inline S Norm() const {
return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] );}
template <class PT> static S Norm(const PT &p ) {
return math::Sqrt( p.V(0)*p.V(0) + p.V(1)*p.V(1) );}
inline S SquaredNorm() const {
return ( _v[0]*_v[0] + _v[1]*_v[1] );}
template <class PT> static S SquaredNorm(const PT &p ) {
return ( p.V(0)*p.V(0) + p.V(1)*p.V(1) );}
inline S operator * ( Point const & p ) const {
return ( _v[0]*p._v[0] + _v[1]*p._v[1]) ; }
inline bool operator == ( Point const & p ) const {
return _v[0]==p._v[0] && _v[1]==p._v[1] ;}
inline bool operator != ( Point const & p ) const {
return _v[0]!=p._v[0] || _v[1]!=p._v[1] ;}
inline bool operator < ( Point const & p ) const{
return (_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<p._v[0]); }
inline bool operator > ( Point const & p ) const {
return (_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>p._v[0]); }
inline bool operator <= ( Point const & p ) {
return (_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<=p._v[0]); }
inline bool operator >= ( Point const & p ) const {
return (_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>=p._v[0]); }
inline Point & Normalize() {
PointType n = Norm(); if(n!=0.0) { n=1.0/n; _v[0]*=n; _v[1]*=n;} return *this;};
template <class PT> Point & Normalize(const PT &p){
PointType n = Norm(); if(n!=0.0) { n=1.0/n; V(0)*=n; V(1)*=n; }
return *this;};
inline Point & HomoNormalize(){
if (_v[2]!=0.0) { _v[0] /= W(); W()=1.0; } return *this;};
inline S NormInfinity() const {
return math::Max( math::Abs(_v[0]), math::Abs(_v[1]) ); }
inline S NormOne() const {
return math::Abs(_v[0])+ math::Abs(_v[1]);}
inline S operator % ( Point const & p ) const {
return _v[0] * p._v[1] - _v[1] * p._v[0]; }
inline S Sum() const {
return _v[0]+_v[1];}
inline S Max() const {
return math::Max( _v[0], _v[1] ); }
inline S Min() const {
return math::Min( _v[0], _v[1] ); }
inline int MaxI() const {
return (_v[0] < _v[1]) ? 1:0; };
inline int MinI() const {
return (_v[0] > _v[1]) ? 1:0; };
inline PointType & Scale( const PointType & p ) {
_v[0] *= p._v[0]; _v[1] *= p._v[1]; return *this; }
inline S StableDot ( const PointType & p ) const {
return _v[0]*p._v[0] +_v[1]*p._v[1]; }
//@}
};
template <class S>
class Point<3,S> : public PointBase<3,S> {
public:
typedef S ScalarType;
typedef Point<3,S> PointType;
//@{
/** @name Special members for 3D points. **/
/// default
inline Point ():PointBase<3,S>(){}
/// yxz constructor
inline Point ( const S a, const S b, const S c){
_v[0]=a; _v[1]=b; _v[2]=c; };
/// Cross product for 3D points
inline PointType operator ^ ( PointType const & p ) const {
return Point (
_v[1]*p._v[2] - _v[2]*p._v[1],
_v[2]*p._v[0] - _v[0]*p._v[2],
_v[0]*p._v[1] - _v[1]*p._v[0] );
}
//@}
//@{
/** @name Implementation of standard functions for 3D points **/
inline void Zero(){
_v[0]=0; _v[1]=0; _v[2]=0; };
inline Point ( const S nv[3] ){
_v[0]=nv[0]; _v[1]=nv[1]; _v[2]=nv[2]; };
inline Point operator + ( Point const & p) const{
return Point( _v[0]+p._v[0], _v[1]+p._v[1], _v[2]+p._v[2]); }
inline Point operator - ( Point const & p) const {
return Point( _v[0]-p._v[0], _v[1]-p._v[1], _v[2]-p._v[2]); }
inline Point operator * ( const S s ) const {
return Point( _v[0]*s, _v[1]*s , _v[2]*s ); }
inline Point operator / ( const S s ) const {
S t=1.0/s;
return Point( _v[0]*t, _v[1]*t , _v[2]*t ); }
inline Point operator - () const {
return Point ( -_v[0], -_v[1] , -_v[2] ); }
inline Point & operator += ( Point const & p ) {
_v[0] += p._v[0]; _v[1] += p._v[1]; _v[2] += p._v[2]; return *this; }
inline Point & operator -= ( Point const & p ) {
_v[0] -= p._v[0]; _v[1] -= p._v[1]; _v[2] -= p._v[2]; return *this; }
inline Point & operator *= ( const S s ) {
_v[0] *= s; _v[1] *= s; _v[2] *= s; return *this; }
inline Point & operator /= ( const S s ) {
S t=1.0/s; _v[0] *= t; _v[1] *= t; _v[2] *= t; return *this; }
inline S Norm() const {
return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] );}
template <class PT> static S Norm(const PT &p ) {
return math::Sqrt( p.V(0)*p.V(0) + p.V(1)*p.V(1) + p.V(2)*p.V(2) );}
inline S SquaredNorm() const {
return ( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] );}
template <class PT> static S SquaredNorm(const PT &p ) {
return ( p.V(0)*p.V(0) + p.V(1)*p.V(1) + p.V(2)*p.V(2) );}
inline S operator * ( PointType const & p ) const {
return ( _v[0]*p._v[0] + _v[1]*p._v[1] + _v[2]*p._v[2]) ; }
inline bool operator == ( PointType const & p ) const {
return _v[0]==p._v[0] && _v[1]==p._v[1] && _v[2]==p._v[2] ;}
inline bool operator != ( PointType const & p ) const {
return _v[0]!=p._v[0] || _v[1]!=p._v[1] || _v[2]!=p._v[2] ;}
inline bool operator < ( PointType const & p ) const{
return (_v[2]!=p._v[2])?(_v[2]< p._v[2]):
(_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<p._v[0]); }
inline bool operator > ( PointType const & p ) const {
return (_v[2]!=p._v[2])?(_v[2]> p._v[2]):
(_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>p._v[0]); }
inline bool operator <= ( PointType const & p ) {
return (_v[2]!=p._v[2])?(_v[2]< p._v[2]):
(_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<=p._v[0]); }
inline bool operator >= ( PointType const & p ) const {
return (_v[2]!=p._v[2])?(_v[2]> p._v[2]):
(_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>=p._v[0]); }
inline PointType & Normalize() {
S n = Norm();
if(n!=0.0) {
n=S(1.0)/n;
_v[0]*=n; _v[1]*=n; _v[2]*=n; }
return *this;};
template <class PT> PointType & Normalize(const PT &p){
S n = Norm(); if(n!=0.0) { n=1.0/n; V(0)*=n; V(1)*=n; V(2)*=n; }
return *this;};
inline PointType & HomoNormalize(){
if (_v[2]!=0.0) { _v[0] /= W(); _v[1] /= W(); W()=1.0; }
return *this;};
inline S NormInfinity() const {
return math::Max( math::Max( math::Abs(_v[0]), math::Abs(_v[1]) ),
math::Abs(_v[3]) ); }
inline S NormOne() const {
return math::Abs(_v[0])+ math::Abs(_v[1])+math::Max(math::Abs(_v[2]));}
inline S operator % ( PointType const & p ) const {
S t = (*this)*p; /* Area, general formula */
return math::Sqrt( SquaredNorm() * p.SquaredNorm() - (t*t) );};
inline S Sum() const {
return _v[0]+_v[1]+_v[2];}
inline S Max() const {
return math::Max( math::Max( _v[0], _v[1] ), _v[2] ); }
inline S Min() const {
return math::Min( math::Min( _v[0], _v[1] ), _v[2] ); }
inline int MaxI() const {
int i= (_v[0] < _v[1]) ? 1:0; if (_v[i] < _v[2]) i=2; return i;};
inline int MinI() const {
int i= (_v[0] > _v[1]) ? 1:0; if (_v[i] > _v[2]) i=2; return i;};
inline PointType & Scale( const PointType & p ) {
_v[0] *= p._v[0]; _v[1] *= p._v[1]; _v[2] *= p._v[2]; return *this; }
inline S StableDot ( const PointType & p ) const {
PointType k0(_v[0]*p._v[0], k1=_v[1]*p._v[1], k2=_v[2]*p._v[2]);
int exp0,exp1,exp2;
frexp( double(k0), &exp0 );
frexp( double(k1), &exp1 );
frexp( double(k2), &exp2 );
if( exp0<exp1 )
if(exp0<exp2) return (k1+k2)+k0; else return (k0+k1)+k2;
else
if(exp1<exp2) return (k0+k2)+k1; else return (k0+k1)+k2;
}
//@}
};
template <class S>
class Point<4, S> : public PointBase<4,S> {
public:
typedef S ScalarType;
typedef Point<4,S> PointType;
//@{
/** @name Special members for 4D points. **/
/// default
inline Point (){}
/// xyzw constructor
//@}
inline Point ( const S a, const S b, const S c, const S d){
_v[0]=a; _v[1]=b; _v[2]=c; _v[3]=d; };
//@{
/** @name Implementation of standard functions for 3D points **/
inline void Zero(){
_v[0]=0; _v[1]=0; _v[2]=0; _v[3]=0; };
inline Point ( const S nv[4] ){
_v[0]=nv[0]; _v[1]=nv[1]; _v[2]=nv[2]; _v[3]=nv[3]; };
inline Point operator + ( Point const & p) const {
return Point( _v[0]+p._v[0], _v[1]+p._v[1], _v[2]+p._v[2], _v[3]+p._v[3] ); }
inline Point operator - ( Point const & p) const {
return Point( _v[0]-p._v[0], _v[1]-p._v[1], _v[2]-p._v[2], _v[3]-p._v[3] ); }
inline Point operator * ( const S s ) const {
return Point( _v[0]*s, _v[1]*s , _v[2]*s , _v[3]*s ); }
inline PointType operator ^ ( PointType const & p ) const {
assert(0);
return *this;
}
inline Point operator / ( const S s ) const {
S t=1.0/s;
return Point( _v[0]*t, _v[1]*t , _v[2]*t , _v[3]*t ); }
inline Point operator - () const {
return Point ( -_v[0], -_v[1] , -_v[2] , -_v[3] ); }
inline Point & operator += ( Point const & p ) {
_v[0] += p._v[0]; _v[1] += p._v[1]; _v[2] += p._v[2]; _v[3] += p._v[3]; return *this; }
inline Point & operator -= ( Point const & p ) {
_v[0] -= p._v[0]; _v[1] -= p._v[1]; _v[2] -= p._v[2]; _v[3] -= p._v[3]; return *this; }
inline Point & operator *= ( const S s ) {
_v[0] *= s; _v[1] *= s; _v[2] *= s; _v[3] *= s; return *this; }
inline Point & operator /= ( const S s ) {
S t=1.0/s; _v[0] *= t; _v[1] *= t; _v[2] *= t; _v[3] *= t; return *this; }
inline S Norm() const {
return math::Sqrt( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3] );}
template <class PT> static S Norm(const PT &p ) {
return math::Sqrt( p.V(0)*p.V(0) + p.V(1)*p.V(1) + p.V(2)*p.V(2) + p.V(3)*p.V(3) );}
inline S SquaredNorm() const {
return ( _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3] );}
template <class PT> static S SquaredNorm(const PT &p ) {
return ( p.V(0)*p.V(0) + p.V(1)*p.V(1) + p.V(2)*p.V(2) + p.V(3)*p.V(3) );}
inline S operator * ( PointType const & p ) const {
return ( _v[0]*p._v[0] + _v[1]*p._v[1] + _v[2]*p._v[2] + _v[3]*p._v[3] ); }
inline bool operator == ( PointType const & p ) const {
return _v[0]==p._v[0] && _v[1]==p._v[1] && _v[2]==p._v[2] && _v[3]==p._v[3];}
inline bool operator != ( PointType const & p ) const {
return _v[0]!=p._v[0] || _v[1]!=p._v[1] || _v[2]!=p._v[2] || _v[3]!=p._v[3];}
inline bool operator < ( PointType const & p ) const{
return (_v[3]!=p._v[3])?(_v[3]< p._v[3]) : (_v[2]!=p._v[2])?(_v[2]< p._v[2]):
(_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<p._v[0]); }
inline bool operator > ( PointType const & p ) const {
return (_v[3]!=p._v[3])?(_v[3]> p._v[3]) : (_v[2]!=p._v[2])?(_v[2]> p._v[2]):
(_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>p._v[0]); }
inline bool operator <= ( PointType const & p ) {
return (_v[3]!=p._v[3])?(_v[3]< p._v[3]) : (_v[2]!=p._v[2])?(_v[2]< p._v[2]):
(_v[1]!=p._v[1])?(_v[1]< p._v[1]) : (_v[0]<=p._v[0]); }
inline bool operator >= ( PointType const & p ) const {
return (_v[3]!=p._v[3])?(_v[3]> p._v[3]) : (_v[2]!=p._v[2])?(_v[2]> p._v[2]):
(_v[1]!=p._v[1])?(_v[1]> p._v[1]) : (_v[0]>=p._v[0]); }
inline PointType & Normalize() {
PointType n = Norm(); if(n!=0.0) { n=1.0/n; _v[0]*=n; _v[1]*=n; _v[2]*=n; _v[3]*=n; }
return *this;};
template <class PT> PointType & Normalize(const PT &p){
PointType n = Norm(); if(n!=0.0) { n=1.0/n; V(0)*=n; V(1)*=n; V(2)*=n; V(3)*=n; }
return *this;};
inline PointType & HomoNormalize(){
if (_v[3]!=0.0) { _v[0] /= W(); _v[1] /= W(); _v[2] /= W(); W()=1.0; }
return *this;};
inline S NormInfinity() const {
return math::Max( math::Max( math::Abs(_v[0]), math::Abs(_v[1]) ),
math::Max( math::Abs(_v[2]), math::Abs(_v[3]) ) ); }
inline S NormOne() const {
return math::Abs(_v[0])+ math::Abs(_v[1])+math::Max(math::Abs(_v[2]),math::Abs(_v[3]));}
inline S operator % ( PointType const & p ) const {
S t = (*this)*p; /* Area, general formula */
return math::Sqrt( SquaredNorm() * p.SquaredNorm() - (t*t) );};
inline S Sum() const {
return _v[0]+_v[1]+_v[2]+_v[3];}
inline S Max() const {
return math::Max( math::Max( _v[0], _v[1] ), math::Max( _v[2], _v[3] )); }
inline S Min() const {
return math::Min( math::Min( _v[0], _v[1] ), math::Min( _v[2], _v[3] )); }
inline int MaxI() const {
int i= (_v[0] < _v[1]) ? 1:0; if (_v[i] < _v[2]) i=2; if (_v[i] < _v[3]) i=3;
return i;};
inline int MinI() const {
int i= (_v[0] > _v[1]) ? 1:0; if (_v[i] > _v[2]) i=2; if (_v[i] > _v[3]) i=3;
return i;};
inline PointType & Scale( const PointType & p ) {
_v[0] *= p._v[0]; _v[1] *= p._v[1]; _v[2] *= p._v[2]; _v[3] *= p._v[3]; return *this; }
inline S StableDot ( const PointType & p ) const {
S k0=_v[0]*p._v[0], k1=_v[1]*p._v[1], k2=_v[2]*p._v[2], k3=_v[3]*p._v[3];
int exp0,exp1,exp2,exp3;
frexp( double(k0), &exp0 );frexp( double(k1), &exp1 );
frexp( double(k2), &exp2 );frexp( double(k3), &exp3 );
if (exp0>exp1) { math::Swap(k0,k1); math::Swap(exp0,exp1); }
if (exp2>exp3) { math::Swap(k2,k3); math::Swap(exp2,exp3); }
if (exp0>exp2) { math::Swap(k0,k2); math::Swap(exp0,exp2); }
if (exp1>exp3) { math::Swap(k1,k3); math::Swap(exp1,exp3); }
if (exp2>exp3) { math::Swap(k2,k3); math::Swap(exp2,exp3); }
return ( (k0 + k1) + k2 ) +k3; }
//@}
};
template <class S>
inline S Angle( Point<3,S> const & p1, Point<3,S> const & p2 )
{
S w = p1.Norm()*p2.Norm();
if(w==0) return -1;
S t = (p1*p2)/w;
if(t>1) t = 1;
else if(t<-1) t = -1;
return (S) acos(t);
}
// versione uguale alla precedente ma che assume che i due vettori siano unitari
template <class S>
inline S AngleN( Point<3,S> const & p1, Point<3,S> const & p2 )
{
S w = p1*p2;
if(w>1)
w = 1;
else if(w<-1)
w=-1;
return (S) acos(w);
}
template <int N,class S>
inline S Norm( Point<N,S> const & p )
{
return p.Norm();
}
template <int N,class S>
inline S SquaredNorm( Point<N,S> const & p )
{
return p.SquaredNorm();
}
template <int N,class S>
inline Point<N,S> & Normalize( Point<N,S> & p )
{
p.Normalize();
return p;
}
template <int N, class S>
inline S Distance( Point<N,S> const & p1,Point<N,S> const & p2 )
{
return (p1-p2).Norm();
}
template <int N, class S>
inline S SquaredDistance( Point<N,S> const & p1,Point<N,S> const & p2 )
{
return (p1-p2).SquaredNorm();
}
template <typename S>
struct Point2:public Point<2,S>{
inline Point2(){};
inline Point2(Point<2,S> const & p):Point<2,S>(p){} ;
inline Point2( const S a, const S b):Point<2,S>(a,b){};
};
template <typename S>
struct Point3:public Point<3,S> {
inline Point3(){};
inline Point3(Point<3,S> const & p):Point<3,S> (p){}
inline Point3( const S a, const S b, const S c):Point<3,S> (a,b,c){};
};
template <typename S>
struct Point4:public Point<4,S>{
inline Point4(){};
inline Point4(Point<4,S> const & p):Point<4,S>(p){}
inline Point4( const S a, const S b, const S c, const S d):Point<4,S>(a,b,c,d){};
};
typedef Point2<short> Point2s;
typedef Point2<int> Point2i;
typedef Point2<float> Point2f;
typedef Point2<double> Point2d;
typedef Point2<short> Vector2s;
typedef Point2<int> Vector2i;
typedef Point2<float> Vector2f;
typedef Point2<double> Vector2d;
typedef Point3<short> Point3s;
typedef Point3<int> Point3i;
typedef Point3<float> Point3f;
typedef Point3<double> Point3d;
typedef Point3<short> Vector3s;
typedef Point3<int> Vector3i;
typedef Point3<float> Vector3f;
typedef Point3<double> Vector3d;
typedef Point4<short> Point4s;
typedef Point4<int> Point4i;
typedef Point4<float> Point4f;
typedef Point4<double> Point4d;
typedef Point4<short> Vector4s;
typedef Point4<int> Vector4i;
typedef Point4<float> Vector4f;
typedef Point4<double> Vector4d;
/*@}*/
} // end namespace
#endif