Point.h

00001 //===========================================================================
00002 // GoTools - SINTEF Geometry Tools version 1.1
00003 //
00004 // GoTools module: CORE
00005 //
00006 // Copyright (C) 2000-2007 SINTEF ICT, Applied Mathematics, Norway.
00007 //
00008 // This program is free software; you can redistribute it and/or          
00009 // modify it under the terms of the GNU General Public License            
00010 // as published by the Free Software Foundation version 2 of the License. 
00011 //
00012 // This program is distributed in the hope that it will be useful,        
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of         
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
00015 // GNU General Public License for more details.                           
00016 //
00017 // You should have received a copy of the GNU General Public License      
00018 // along with this program; if not, write to the Free Software            
00019 // Foundation, Inc.,                                                      
00020 // 59 Temple Place - Suite 330,                                           
00021 // Boston, MA  02111-1307, USA.                                           
00022 //
00023 // Contact information: E-mail: tor.dokken@sintef.no                      
00024 // SINTEF ICT, Department of Applied Mathematics,                         
00025 // P.O. Box 124 Blindern,                                                 
00026 // 0314 Oslo, Norway.                                                     
00027 //
00028 // Other licenses are also available for this software, notably licenses
00029 // for:
00030 // - Building commercial software.                                        
00031 // - Building software whose source code you wish to keep private.        
00032 //===========================================================================
00033 #ifndef _GOPOINT_H
00034 #define _GOPOINT_H
00035 
00036 
00037 #include "Array.h"
00038 #include "errormacros.h"
00039 #include <algorithm>
00040 #include <math.h>
00041 
00042 namespace Go {
00045 
00046 
00047 
00056 class Point
00057 {
00058 private:
00059     double* pstart_;
00060     int n_;
00061     bool owns_;
00062 
00063 public:
00068     Point()
00069         : pstart_(0), n_(0), owns_(true)
00070     {}
00074     explicit Point(int dim)
00075         : pstart_(new double[dim]), n_(dim), owns_(true)
00076     {}
00079     Point(double x, double y)
00080         : pstart_(new double[2]), n_(2), owns_(true)
00081     {
00082         pstart_[0] = x;
00083         pstart_[1] = y;
00084     }
00087     Point(double x, double y, double z)
00088         : pstart_(new double[3]), n_(3), owns_(true)
00089     {
00090         pstart_[0] = x;
00091         pstart_[1] = y;
00092         pstart_[2] = z;
00093     }
00094 
00097     // @@@ 'typename T' must be present in order to compile on MS
00098     // v6.0. (Using just 'int Dim' and 'Array<double, Dim>' will cause
00099     // "internal compiler error" !) @jbt
00100     template <typename T, int Dim>
00101     explicit Point(const Array<T, Dim>& v)
00102         : pstart_(0), n_(Dim), owns_(true)
00103     {
00104         pstart_ = new double[n_];
00105         std::copy(v.begin(), v.end(), pstart_);
00106     }
00107 
00108 // #ifndef _MSC_VER
00110     template <typename RandomAccessIterator>
00111     Point(RandomAccessIterator first, RandomAccessIterator last)
00112         : pstart_(0), n_(last - first), owns_(true)
00113     {
00114         pstart_ = new double[n_];
00115         std::copy(first, last, pstart_);
00116     }
00117 // #endif
00118 // #ifdef _MSC_VER
00119 // #if _MSC_VER > 1200
00120 //     template <typename ForwardIterator>
00121 //     Point(ForwardIterator first, ForwardIterator last)
00122 //      : pstart_(0), n_(last - first), owns_(true)
00123 //     {
00124 //      pstart_ = new double[n_];
00125 //      std::copy(first, last, pstart_);
00126 //     }
00127 // #else // Old version
00128 //     Point(const double* first, const double* last)
00129 //      : pstart_(0), n_(last - first), owns_(true)
00130 //     {
00131 //      pstart_ = new double[n_];
00132 //      std::copy(first, last, pstart_);
00133 //     }
00134 //     Point(const float* first, const float* last)
00135 //      : pstart_(0), n_(last - first), owns_(true)
00136 //     {
00137 //      pstart_ = new double[n_];
00138 //      std::copy(first, last, pstart_);
00139 //     }
00140 // #endif // _MSC_VER > 1200
00141 // #endif
00142 
00147     Point(double* begin, double* end, bool own)
00148         : pstart_(0), n_(end-begin), owns_(own)
00149     {
00150         if (owns_) {
00151             pstart_ = new double[n_];
00152             std::copy(begin, end, pstart_);
00153         } else {
00154             pstart_ = begin;
00155         }
00156     }
00157 
00159     Point(const Point& v)
00160         : pstart_(0), n_(v.n_), owns_(true)
00161     {
00162         pstart_ = new double[n_];
00163         std::copy(v.pstart_, v.pstart_ + n_, pstart_);
00164     }
00165 
00167     Point& operator = (const Point &v)
00168     {
00169         Point temp(v);
00170         swap(temp);
00171         return *this;
00172     }
00173 
00175     ~Point()
00176     {
00177         if (owns_) delete [] pstart_;
00178     }
00179 
00181     void swap(Point& other)
00182     {
00183         std::swap(pstart_, other.pstart_);
00184         std::swap(n_, other.n_);
00185         std::swap(owns_, other.owns_);
00186     }
00187 
00191     void read(std::istream& is);
00192 
00197     void write(std::ostream& os) const;
00198 
00199 
00201     const double& operator [] (int i) const  { return pstart_[i]; }
00203     double& operator [] (int i)        { return pstart_[i]; }
00205     const double* begin() const { return pstart_; }
00207     double* begin()       { return pstart_; }
00209     const double* end() const { return pstart_ + n_; }
00211     double* end()       { return pstart_ + n_; }
00213     int size() const { return n_; }
00215     int dimension() const { return n_; }
00216 
00218     void resize(int d)
00219     {
00220         if (n_ < d) {
00221             Point temp(d);
00222             swap(temp);
00223         } else {
00224             n_ = d;
00225         }
00226     }
00227 
00229     void  setValue(double x, double y)
00230     {
00231         resize(2);
00232         pstart_[0] = x;
00233         pstart_[1] = y;
00234     }
00236     void  setValue(double x, double y, double z)
00237     {
00238         resize(3);
00239         pstart_[0] = x;
00240         pstart_[1] = y;
00241         pstart_[2] = z;
00242     }
00246     void  setValue(const double* array)
00247     {
00248         for (int i = 0; i < n_; ++i) {
00249             pstart_[i] = array[i];
00250         }
00251     }
00255     void  setValue(double val)
00256     {
00257         for (int i = 0; i < n_; ++i) {
00258             pstart_[i] = val;
00259         }
00260     }
00261 
00262     void resetValue(int idx, double val)
00263         {
00264             DEBUG_ERROR_IF(idx < 0 || idx >= n_,
00265                  "Dimension mismatch.");
00266             pstart_[idx] = val;
00267         }
00268 
00271     double length2() const
00272     {
00273         double l2 = 0;
00274         for (int i = 0; i < n_; ++i)
00275             l2 += pstart_[i]*pstart_[i];
00276         return l2;
00277     }
00280     double length()  const
00281     {
00282         return sqrt(length2());
00283     }
00286     double lengthInf() const
00287     {
00288         double linf = 0;
00289         for (int i = 0; i < n_; ++i) {
00290             linf = std::max(linf, fabs(pstart_[i]));
00291         }
00292         return linf;
00293     }
00297     double dist2(const Point &v) const
00298     {
00299         double l2 = 0;
00300         double d;
00301         for (int i = 0; i < n_; ++i) {
00302             d = pstart_[i] - v.pstart_[i];
00303             l2 += d*d;
00304         }
00305         return l2;
00306     }
00310     double dist(const Point &v) const
00311     {
00312         return sqrt(dist2(v));
00313     }
00317     double distInf(const Point &v) const
00318     {
00319         double linf = 0;
00320         double d;
00321         for (int i = 0; i < n_; ++i) {
00322             d = pstart_[i] - v.pstart_[i];
00323             linf = std::max(linf, fabs(d));
00324         }
00325         return linf;
00326     }
00329     void normalize()
00330     {
00331         double tl = length();
00332         DEBUG_ERROR_IF(tl == 0.0, "Cannot normalize vector of zero length");
00333         (*this) /= tl;
00334     }
00335 
00336     double normalize_checked() 
00337     {
00338         double tl = length(); 
00339         if (tl<1.0e-12)
00340             return 0;
00341 
00342         (*this) /= tl; 
00343         return tl;
00344     }
00345 
00347     Point  operator + (const Point     &v) const
00348     {
00349         Point res(*this);
00350         res += v;
00351         return res;
00352     }
00354     void     operator +=(const Point     &v)
00355     {
00356         DEBUG_ERROR_IF(n_!=v.n_,
00357                  "Dimension mismatch.");
00358         for (int i = 0; i < n_; ++i)
00359             pstart_[i] += v.pstart_[i];
00360     }
00361 
00363     Point  operator - (const Point     &v) const
00364     {
00365         Point res(*this);
00366         res -= v;
00367         return res;
00368     }
00370     void     operator -=(const Point     &v)
00371     {
00372         DEBUG_ERROR_IF(n_!=v.n_,
00373                  "Dimension mismatch.");
00374         for (int i = 0; i < n_; ++i)
00375             pstart_[i] -= v.pstart_[i];
00376     }
00378     Point  operator * (double d) const
00379     {
00380         Point res(*this);
00381         res *= d;
00382         return res;
00383     }
00385     void     operator *=(double d)
00386     {
00387         for (int i = 0; i < n_; ++i)
00388             pstart_[i] *= d;
00389     }
00390 
00392     Point  operator / (double d) const
00393     {
00394         Point res(*this);
00395         res /= d;
00396         return res;
00397     }
00399     void     operator /=(double d)
00400     {
00401         for (int i = 0; i < n_; ++i)
00402             pstart_[i] /= d;
00403     }
00404 
00406     Point  operator - () const
00407     {
00408         Point res(*this);
00409         for (int i = 0; i < n_; ++i)
00410             res.pstart_[i] = - pstart_[i];
00411         return res;
00412     }
00413 
00416     double   operator * (const Point     &v) const
00417     {
00418         DEBUG_ERROR_IF(n_!=v.n_,
00419                  "Dimension mismatch.");
00420         double res = 0;
00421         for (int i = 0; i < n_; ++i)
00422             res += pstart_[i]*v.pstart_[i];
00423         return res;
00424     }
00425 
00428     Point  operator % (const Point     &v) const
00429     {
00430         DEBUG_ERROR_IF(n_ != 3 || v.n_ != 3,
00431                  "Dimension mismatch.");
00432         return Point(pstart_[1]*v.pstart_[2] - pstart_[2]*v.pstart_[1],
00433                      pstart_[2]*v.pstart_[0] - pstart_[0]*v.pstart_[2],
00434                      pstart_[0]*v.pstart_[1] - pstart_[1]*v.pstart_[0]);
00435     }
00436 
00439     Point cross(const Point     &v) const
00440     {
00441         return operator%(v);
00442     }
00443 
00445     void setToCrossProd(const Point &u, const Point &v)
00446     {
00447         DEBUG_ERROR_IF(u.n_!=v.n_,
00448                  "Dimension mismatch.");
00449         DEBUG_ERROR_IF(u.n_!=3,
00450                  "Dimension must be 3.");
00451 
00452         bool have_already = owns_ && (n_ >= v.n_);
00453         if (!have_already) {
00454             Point temp(3);
00455             swap(temp);
00456         } else {
00457             n_ = 3;
00458         }
00459         pstart_[0]=u.pstart_[1]*v.pstart_[2] - u.pstart_[2]*v.pstart_[1];
00460         pstart_[1]=u.pstart_[2]*v.pstart_[0] - u.pstart_[0]*v.pstart_[2];
00461         pstart_[2]=u.pstart_[0]*v.pstart_[1] - u.pstart_[1]*v.pstart_[0];
00462     }
00463 
00466     double cosAngle(const Point& v) const
00467     {
00468         double tl1 = length();
00469         double tl2 = v.length();
00470         //(DEBUG_ERROR_IF(tl1*tl2 == 0.0, "Vector of zero length");
00471         if (tl1*tl2 == 0.0) 
00472         {
00473             //MESSAGE("Vector of zero length in angle compuation");
00474             return 0.0;
00475         }
00476         double res = ((*this)*v)/(tl1*tl2);
00477         res = std::min(1.0, std::max(-1.0, res));
00478         return res;
00479     }
00480 
00483     double angle(const Point& v) const
00484     {
00485         return acos(cosAngle(v));
00486     }
00487 
00490     double angle_smallest(const Point& v) const
00491     {
00492         double tl1 = length();
00493         double tl2 = v.length();
00494         //DEBUG_ERROR_IF(tl1*tl2 == 0.0, "Vector of zero length");
00495         double tcos = fabs(((*this)*v)/(tl1*tl2));
00496         tcos = std::min(1.0, tcos);
00497         return acos(tcos);
00498     }
00499 
00500 };
00501 
00503     inline Point operator * (double d, const Point& p)
00504     { return p*d; }
00505 
00507     inline std::istream& operator>>(std::istream& is, Go::Point& v)
00508     { v.read(is); return is; }
00509 
00511     inline std::ostream& operator<<(std::ostream& os, const Go::Point& v)
00512     { v.write(os); return os; }
00513 
00514     // comparison operator
00515     inline bool operator<(const Point& p1, const Point& p2)
00516     {
00517         const int dim = p1.dimension();
00518         DEBUG_ERROR_IF(p2.dimension() != dim, "Dimension Mismatch");
00519         for (int i = dim-1; i >= 0; --i) {
00520             if (p1[i] > p2[i]) return false;
00521             if (p1[i] < p2[i]) return true;
00522         }
00523         return false;
00524     }
00525 
00527 } // End of namespace Go
00528 
00529 
00530 
00531 #endif // _GOPOINT_H
00532 
00533 
00534 
00535 
00536 
00537 

Generated on Mon Jun 11 14:48:18 2007 for GoTools Core Library by  doxygen 1.5.1