include/dpoint.hpp

Go to the documentation of this file.
00001 
00002 
00020 #ifndef REVIVER_POINT_HPP
00021 #define REVIVER_POINT_HPP
00022 
00023 
00024 #include "assert.hpp"
00025 #include <iostream>
00026 #include <valarray>
00027 #include <stdio.h>
00028 #include <limits>
00029 
00030 
00031 
00033 namespace reviver {
00034 
00035 
00036 // Forward Declaration of the main Point Class
00037 // Eucledian d-dimensional point. The distance
00038 // is L_2
00039 
00040 template<typename NumType, unsigned D>
00041 class dpoint;
00042 
00043 
00045 // Internal number type traits for dpoint
00047 
00048 template<typename T> 
00049 class InternalNumberType;
00050 
00051 template<>
00052 class InternalNumberType<float>{
00053 public: 
00054   typedef double __INT;
00055 };
00056 
00057 
00058 template<>
00059 class InternalNumberType<int>{
00060 public: 
00061   typedef long long __INT;
00062 };
00063 
00064 
00065 template<>
00066 class InternalNumberType<double>{
00067 public: 
00068   typedef double __INT;
00069 };
00070 
00071 template<>
00072 class InternalNumberType<long>{
00073 public: 
00074   typedef long long __INT;
00075 };
00076 
00077 
00078 
00079 
00081 // Origin of d-dimensional point
00083 template< typename NumType, unsigned D, unsigned I > struct origin
00084 {
00085    static inline void eval( dpoint<NumType,D>& p )
00086    {
00087           p[I] = 0.0;
00088       origin< NumType, D, I-1 >::eval( p );
00089    }
00090 };
00091 
00092 
00093 // Partial Template Specialization
00094 template <typename NumType, unsigned D> struct origin<NumType, D, 0>
00095 {
00096    static inline void eval( dpoint<NumType,D>& p )
00097    {
00098           p[0] = 0.0;
00099    }
00100 };
00101 
00102 
00104 
00107 
00108 // Squared Distance of d-dimensional point
00110 template< typename NumType, unsigned D, unsigned I > struct Distance
00111 {
00112    static inline double eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00113    {
00114      double sum = ((double)p[I] -  (double)q[I] ) *( (double)p[I] - (double)q[I] );
00115           return sum + Distance< NumType, D, I-1 >::eval( p,q );
00116    }
00117 };
00118 
00119 
00121 template <typename NumType, unsigned D> struct Distance<NumType, D, 0>
00122 {
00123    static inline double eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00124    {
00125      return ((double) p[0] - (double)q[0] )*( (double)p[0] - (double)q[0] );
00126    }
00127 };
00128 
00129 
00131 
00134 
00135 // Dot Product of two d-dimensional points
00137 template< typename __INT, typename NumType, unsigned D, unsigned I > struct DotProd
00138 {
00139    static inline __INT eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00140    {
00141           __INT sum = ( ((__INT)p[I]) * ((__INT)q[I]) );
00142           return sum + DotProd< __INT, NumType, D, I-1 >::eval( p,q );
00143    }
00144 };
00145 
00146 
00148 template < typename __INT, typename NumType, unsigned D> struct DotProd<__INT,NumType, D, 0>
00149 {
00150    static inline __INT eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00151    {
00152           return ( ((__INT)p[0]) * ((__INT)q[0]) );
00153    }
00154 };
00155 
00156 
00158 // Equality of two d-dimensional points
00160 template< typename NumType, unsigned D, unsigned I > struct IsEqual
00161 {
00162    static inline bool eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00163    {
00164           if( p[I]  != q[I] ) return false;
00165           else return IsEqual< NumType, D, I-1 >::eval( p,q );
00166    }
00167 };
00168 
00169 
00170 // Partial Template Specialization
00171 template <typename NumType, unsigned D> struct IsEqual<NumType, D, 0>
00172 {
00173    static inline NumType eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00174    {
00175            return (p[0] == q[0])?1:0;
00176    }
00177 };
00178 
00179 
00180 
00182 
00188 template< 
00189   typename NumType1, 
00190   typename NumType2, 
00191   unsigned D, 
00192   unsigned I 
00193   > struct Equate
00194 {
00195    static inline void eval( dpoint<NumType1,D>& p,const dpoint<NumType2,D>& q )
00196    {
00197           p[I]  = q[I];
00198           Equate< NumType1, NumType2, D, I-1 >::eval( p,q );
00199    }
00200 };
00201 
00202 
00204 template <
00205   typename NumType1, 
00206   typename NumType2,
00207   unsigned D
00208   > struct Equate<NumType1,NumType2, D, 0>
00209 {
00210    static inline void  eval( dpoint<NumType1,D>& p,const dpoint<NumType2,D>& q )
00211    {
00212            p[0] = q[0];
00213    }
00214 };
00215 
00216 
00218 
00221 
00222 // Add two d-dimensional points
00224 template< typename NumType, unsigned D, unsigned I > struct Add
00225 {
00226    static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00227    {
00228           result[I] = p[I]  + q[I];
00229           Add< NumType, D, I-1 >::eval( result,p,q );
00230    }
00231 };
00232 
00233 
00235 template <typename NumType, unsigned D> struct Add<NumType, D, 0>
00236 {
00237    static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00238    {
00239            result[0] = p[0] + q[0];
00240    }
00241 };
00242 
00243 
00245 // Subtract two d-dimensional points
00247 // Could actually be done using scalar multiplication
00248 // and addition
00249 
00250 
00251 // What about unsigned types?
00252 template< typename NumType > 
00253 inline NumType Subtract_nums(const NumType& x, const NumType& y) {
00254   if(!std::numeric_limits<NumType>::is_signed) {std::cerr << "Exception: Can't subtract unsigned types."; exit(1);}
00255   return x - y;
00256 }
00257 
00258 
00260 
00263 template< typename NumType, unsigned D, unsigned I > struct Subtract
00264 {
00265    static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00266    {
00267      
00268           result[I] = Subtract_nums(p[I] , q[I]);
00269           Subtract< NumType, D, I-1 >::eval( result,p,q );
00270    }
00271 };
00272 
00273 
00275 template <typename NumType, unsigned D> struct Subtract<NumType, D, 0>
00276 {
00277    static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
00278    {
00279            result[0] = Subtract_nums(p[0] , q[0]);
00280    }
00281 };
00282 
00283 
00284 
00285 
00286 
00288 
00292 template< typename NumType, unsigned D, unsigned I > struct Multiply
00293 {
00294    static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, NumType k)
00295    {
00296           result[I] = p[I] * k;
00297           Multiply< NumType, D, I-1 >::eval( result,p,k );
00298    }
00299 };
00300 
00301 
00303 template <typename NumType, unsigned D> struct Multiply<NumType, D, 0>
00304 {
00305    static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, NumType k )
00306    {
00307            result[0] = p[0] * k;
00308    }
00309 };
00310 
00311 
00312 
00314 
00318 template<typename NumType = double, unsigned D = 3>
00319 class dpoint {
00320 
00321                 // Makes Swap operation fast
00322                 NumType  x[D];
00323 
00324 public:
00325 
00326 
00327         typedef NumType NT;
00328         typedef typename InternalNumberType<NumType>::__INT __INT;
00329 
00330         // To be defined in a cpp file
00331         //  const MgcVector2 MgcVector2::ZERO(0,0);
00332         //  static const dpoint<NumType,D> Zero;
00333 
00334         inline void move2origin(){ origin<NumType, D, D-1>::eval(*this); };
00335 
00336         dpoint(){ 
00337                 Assert( (D >= 1), "Dimension < 1 not allowed" ); 
00338                 // move2origin(); 
00339         };
00340 
00342         dpoint(NumType x0){ x[0] = x0; };
00344         dpoint(NumType x0,NumType x1){ x[0] = x0;  x[1] = x1; };
00346         dpoint(NumType x0,NumType x1,NumType x2){  x[0] = x0;  x[1] = x1; x[2] = x2; };
00348         dpoint(NumType ax[]){ for(int i =0; i < D; ++i) x[i] = ax[i]; };
00350         dpoint(const dpoint<NumType,D>& p){  Equate<NumType,NumType,D,D-1>::eval((*this),p);    };
00351 
00352          
00355         template<class OtherNumType>
00356         explicit dpoint(const dpoint<OtherNumType,D>& p){ Equate<NumType,OtherNumType,D,D-1>::eval((*this),p); };
00357 
00358         // Destructor
00359         ~dpoint(){};
00360 
00361         inline int      dim() const { return D; };
00362         inline double   sqr_dist(const dpoint<NumType,D> q) const ;
00363         inline double   distance(const dpoint<NumType,D> q) const ;
00364         inline __INT    dotprod (const dpoint<NumType,D> q) const ;
00365         inline __INT    sqr_length(void)  const;
00366         inline void     normalize (void);
00367         inline NumType& operator[](int i);
00368         inline NumType  operator[](int i) const;
00369 
00370         inline dpoint&  operator= (const dpoint<NumType,D>& q);
00371 
00372         template<typename NT, unsigned __DIM>
00373         friend dpoint<NT,__DIM>   operator- (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q);
00374 
00375         template<typename NT, unsigned __DIM>
00376         friend dpoint<NT,__DIM>   operator+ (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q);
00377 
00378         template<typename NT, unsigned __DIM>
00379         friend bool   operator== (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q);
00380 
00381         template<typename NT, unsigned __DIM>
00382         friend bool   operator!= (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q);
00383 
00384 
00385 //      inline dpoint&  operator= (const valarray<NumType>& v);
00386 //      inline operator valarray<NumType>() const;
00387 
00388         template<typename __NT,unsigned __DIM>
00389         friend void iswap(dpoint<__NT,__DIM>& p,dpoint<__NT,__DIM>& q);
00390 };
00391 
00392 template<typename NumType, unsigned D>
00393 void dpoint<NumType,D>::normalize (void){
00394         double len = sqrt(sqr_length());
00395         if (len > 0.00001)
00396         for(int i = 0; i < D; ++i){
00397                 x[i] /= len;
00398         }
00399 }
00400 
00401 /*
00402 template<typename NumType, unsigned D>
00403 dpoint<NumType,D>::operator valarray<NumType>() const{
00404         valarray<NumType> result((*this).x , D);
00405         return result;
00406 }
00407 
00408 //Warning : Valarray should be of size D
00409 //TODO: Unwind this for loop into a template system
00410 template<typename NumType, unsigned D>
00411 dpoint<NumType,D>&
00412 dpoint<NumType,D>::operator= (const valarray<NumType>& v){
00413         dpoint<NumType,D> result;
00414         for(int i = 0; i < D; i++) (*this).x[i] = v[i];
00415         return (*this);
00416 }
00417 */
00418 
00419 template<typename NT, unsigned __DIM>
00420 dpoint<NT,__DIM>
00421 operator+ (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q){
00422         dpoint<NT,__DIM> result;
00423         Add<NT,__DIM,__DIM-1>::eval(result,p,q);        
00424         return result;
00425 }
00426 
00427 template<typename NT, unsigned __DIM>
00428 dpoint<NT,__DIM>
00429 operator- (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q){
00430         dpoint<NT,__DIM> result;
00431         // cout << "Subtracting..." << p << " from " << q << " = ";
00432         Subtract<NT,__DIM,__DIM-1>::eval(result,p,q);   
00433         // cout << result << endl;      
00434         return result;
00435 }
00436 
00437 template<typename NT, unsigned __DIM>
00438 bool
00439 operator== (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q){
00440         return IsEqual<NT,__DIM,__DIM-1>::eval(p,q);    
00441 }
00442 
00443 template<typename NT, unsigned __DIM>
00444 bool
00445 operator!= (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q){
00446         return !(IsEqual<NT,__DIM,__DIM-1>::eval(p,q)); 
00447 }
00448 
00449 template<typename NT, unsigned __DIM>
00450 dpoint<NT,__DIM>
00451 operator* (const dpoint<NT,__DIM>& p, const NT k){
00452         dpoint<NT,__DIM> result;
00453         Multiply<NT,__DIM,__DIM-1>::eval(result,p,k);   
00454         return result;
00455 }
00456 
00457 template<typename NT, unsigned __DIM>
00458 dpoint<NT,__DIM>
00459 operator/ (const dpoint<NT,__DIM>& p, const NT k){
00460         Assert( (k != 0), "Hell division by zero man...\n");
00461         dpoint<NT,__DIM> result;
00462         Multiply<NT,__DIM,__DIM-1>::eval(result,p,((double)1.0)/k);     
00463         return result;
00464 }
00465 
00466 template < typename NumType, unsigned D >
00467 dpoint<NumType,D>&
00468 dpoint<NumType,D>::operator=(const dpoint<NumType,D> &q)
00469 {
00470   Assert((this != &q), "Error p = p");
00471   Equate<NumType,NumType,D,D-1>::eval(*this,q); 
00472   return *this;
00473 }
00474 
00475 template < typename NumType, unsigned D >
00476 NumType
00477 dpoint<NumType,D>::operator[](int i) const
00478 { return x[i]; }
00479 
00480 template < typename NumType, unsigned D >
00481 NumType&
00482 dpoint<NumType,D>::operator[](int i)
00483 {
00484  return x[i]; }
00485 
00486 
00487 template<typename NumType, unsigned D>
00488 double
00489 dpoint<NumType,D>::sqr_dist (const dpoint<NumType,D> q) const {
00490         return Distance<NumType,D,D-1>::eval(*this,q);  
00491 }
00492 
00493 template<typename NumType, unsigned D>
00494 double 
00495 dpoint<NumType,D>::distance (const dpoint<NumType,D> q) const {
00496         return sqrt(static_cast<double>(Distance<NumType,D,D-1>::eval(*this,q)));       
00497 }
00498 
00499 
00500 template<typename NumType, unsigned D>
00501 typename dpoint<NumType,D>::__INT
00502 dpoint<NumType,D>::dotprod (const dpoint<NumType,D> q) const {
00503         return DotProd<__INT,NumType,D,D-1>::eval(*this,q);     
00504 }
00505 
00506 template<typename NumType, unsigned D>
00507 typename dpoint<NumType,D>::__INT
00508 dpoint<NumType,D>::sqr_length (void) const {
00509 #ifdef _DEBUG   
00510     if( DotProd<__INT,NumType,D,D-1>::eval(*this,*this) < 0) {
00511           std::cerr << "Point that caused error: ";
00512           std::cerr << *this << std::endl;
00513           std::cerr << DotProd<__INT,NumType,D,D-1>::eval(*this,*this) << std::endl;
00514           std::cerr << "Fatal: Hell!\n"; exit(1);
00515         }
00516 #endif
00517         return DotProd<__INT,NumType,D,D-1>::eval(*this,*this); 
00518         
00519 }
00520 
00521 template < class NumType, unsigned D >
00522 std::ostream&
00523 operator<<(std::ostream& os,const dpoint<NumType,D> &p)
00524 {
00525      os << "Point (d=";
00526          os << D << ", (";
00527          for (unsigned int i=0; i<D-1; ++i)
00528                 os << p[i] << ", ";
00529         return os << p[D-1] << "))";
00530     
00531 };
00532 
00533 template < class NumType, unsigned D >
00534 std::istream&
00535 operator>>(std::istream& is,dpoint<NumType,D> &p)
00536 {
00537          for (int i=0; i<D; ++i)
00538                  if(!(is >> p[i])){
00539                          if(!is.eof()){
00540                                 std::cerr << "Error Reading Point:" 
00541                                           << is << std::endl;
00542                                 exit(1);
00543                          }
00544                  }
00545                  
00546         return is;
00547     
00548 };
00549 
00550 /*
00551 template<typename __NT,unsigned __DIM>
00552 static inline void iswap(dpoint<__NT,__DIM>& p,dpoint<__NT,__DIM>& q){
00553         __NT *y;
00554         y = p.x;
00555         p.x = q.x;
00556         q.x = y;
00557 }
00558 */
00559 
00560 
00561 
00562 template < typename NumType, unsigned D >
00563 dpoint<NumType, D> CrossProd(const dpoint<NumType, D>& vector1, 
00564                              const dpoint<NumType, D>& vector2) {
00565    Assert(D == 3, "Cross product only defined for 3d vectors");
00566    dpoint<NumType, D> vector;
00567    vector[0] = (vector1[1] * vector2[2]) - (vector2[1] * vector1[2]);
00568    vector[1] = (vector2[0] * vector1[2]) - (vector1[0] * vector2[2]);
00569    vector[2] = (vector1[0] * vector2[1]) - (vector2[0] * vector1[1]); 
00570    return vector;
00571 }
00572 
00573 
00574 
00575 
00576 template < typename __NT, unsigned __DIM >
00577 int
00578 orientation(const dpoint<__NT,__DIM> p[__DIM+1])
00579 {
00580         int _sign = + 1;
00581         // To be implemented
00582         std::cerr << "Not yet implemented\n";
00583         exit(1);
00584         return _sign;
00585     
00586 }
00587 
00588 
00589 template < typename __NT >
00590 inline __NT
00591 orientation(
00592             const dpoint<__NT,2>& p,
00593             const dpoint<__NT,2>& q,
00594             const dpoint<__NT,2>& r
00595             )
00596 {
00597    // 2D speaciliazation for orientation
00598         std::cout << "FATAL";
00599   exit(1);
00600   return ((p[0]-r[0])*(q[1]-r[1]))-((q[0]-r[0])*(p[1]-r[1]));
00601 }
00602 
00603 
00604 extern "C" double orient2d(double *p, double *q, double *r);
00605 
00606 template < >
00607 inline double
00608 orientation<double>(
00609             const dpoint<double,2>& p,
00610             const dpoint<double,2>& q,
00611             const dpoint<double,2>& r
00612             )
00613 {
00614    // 2D speaciliazation for orientation
00615   double pp[2] = { p[0], p[1] };
00616   double qq[2] = { q[0], q[1] };
00617   double rr[2] = { r[0], r[1] };
00618   return orient2d(pp,qq,rr);
00619 }
00620 
00621 
00622 template < >
00623 inline float
00624 orientation<float>(
00625             const dpoint<float,2>& p,
00626             const dpoint<float,2>& q,
00627             const dpoint<float,2>& r
00628             )
00629 {
00630    // 2D speaciliazation for orientation
00631   double pp[2] = { p[0], p[1] };
00632   double qq[2] = { q[0], q[1] };
00633   double rr[2] = { r[0], r[1] };
00634   return orient2d(pp,qq,rr);
00635 }
00636 
00637 
00638 
00639 };      // Namespace Ends here
00640 
00641 
00642 
00643 
00644 #endif
00645 
00646 

Generated on Fri Nov 3 21:59:02 2006 for Triangle++ by  doxygen 1.4.6