Point.h

Go to the documentation of this file.
00001 #ifndef Point_HEADER
00002 #define Point_HEADER
00003 
00004 #include <boost/array.hpp>
00005 #include <math.h> // sqrt
00006 #include <limits> // numeric_limits
00007 
00008 namespace Geometry {
00009 
00010 template <size_t d>
00011 class Point : public boost::array<double, d> {
00012   private:
00013     bool operator==(Point other);
00014 
00015   public:
00016     typedef boost::array<double, d> super;
00017     Point() { }
00018     Point(double v) { assign(v); }
00019     Point(const super& t) : super(t) { }
00020     Point(const Point& p) : super(p) { }
00021     Point(const double *v, size_t
00022 #ifndef NDEBUG
00023           n
00024 #endif
00025           ) {
00026       assert(n >= d);
00027       for(unsigned i = 0; i < d; i++) {
00028         (*this)[i] = v[i];
00029       }
00030     }
00031 
00032     template <class iterator>
00033     Point(iterator begin, const iterator&
00034 #ifndef NDEBUG
00035         end
00036 #endif
00037         ) {
00038       assert(end - begin == d);
00039       for(unsigned i = 0; i < d; i++, begin++) {
00040         (*this)[i] = *begin;
00041       }
00042     }
00043 
00044     /* This constructor is appealing, but then it
00045        destroys typechecking between points of
00046        different dimension.  Leave it dead. */
00047     /* template <class container> Point(const container& c); */
00048 
00049     /* gcc seems to be stupid about inlining and constant-propagating through
00050        array::assign (which calls fill_n).  So we define it here, where hopefully
00051        gcc will notice the loop has known length. */
00052     void assign(double v) {
00053       for(unsigned i = 0; i < d; ++i) {
00054         this->elems[i] = v;
00055       }
00056     }
00057 
00058     static unsigned dim() { return d; }
00059     static const unsigned dimension = d;
00060 
00061     //unit vector in the j dimension
00062     static Point unit(unsigned j) {
00063       Point rval(0.0);
00064       rval[j] = 1.0;
00065       return rval;
00066     }
00067 
00068     // the all ones vector
00069     static Point allones() {
00070       Point rval(1.0);
00071       return rval;
00072     }
00073 
00074     // a random unit vector drawn u.a.r. from the cube
00075     // and normalized.  TODO: This is not u.a.r. from the
00076     // sphere.
00077     static Point unitrand() {
00078       Point p; // uninitialized
00079       for(unsigned i = 0; i < d; ++i) {
00080         p[i] = random();
00081       }
00082       double len = sqrt(p.norm2());
00083       p *= 1.0 / len;
00084       return p;
00085     }
00086     static Point randPoint(double max) {
00087       Point p = unitrand();
00088       double r = (double)random() / (double)std::numeric_limits<long>::max();
00089       assert(r < 1.0); // may flip vector; whatever.
00090       p *= r * max;
00091       return p;
00092     }
00093 
00094     void operator+= (const Point& p) {
00095       for (unsigned i = 0; i < d; ++i) {
00096         (*this)[i] += p[i];
00097       }
00098     }
00099 
00100     Point operator+ (const Point& p) const {
00101       Point copy = *this; copy += p; return copy;
00102     }
00103 
00104     void operator-= (const Point& p) {
00105       for (unsigned i = 0; i < d; ++i) {
00106         (*this)[i] -= p[i];
00107       }
00108     }
00109 
00110     Point operator- (const Point& p) const {
00111       Point copy = *this; copy -= p; return copy;
00112     }
00113 
00114     void operator*= (double x) {
00115       for (unsigned i = 0; i < d; ++i) {
00116         (*this)[i] *= x;
00117       }
00118     }
00119 
00120     Point operator* (double x) const {
00121       Point copy = *this; copy *= x; return copy;
00122     }
00123 
00124     void operator/= (double x) {
00125       for (unsigned i = 0; i < d; ++i) {
00126         (*this)[i] /= x;
00127       }
00128     }
00129 
00130     Point operator/ (double x) const {
00131       Point copy = *this; copy /= x; return copy;
00132     }
00133 
00134     double dot(const Point& p) const {
00135       double sum = 0.0;
00136       for(unsigned i = 0; i < d; i++) {
00137         sum += (*this)[i] * p[i];
00138       }
00139       return sum;
00140     }
00141 
00142     double dist2(const Point& q) const {
00143       double sum = 0.0;
00144       for(unsigned i = 0; i < d; i++) {
00145         double diff = (*this)[i] - q[i];
00146         sum += diff * diff;
00147       }
00148       return sum;
00149     }
00150 
00151     double norm2() const {
00152       double sum = 0.0;
00153       for(unsigned i = 0; i < d; i++) {
00154         sum += (*this)[i] * (*this)[i];
00155       }
00156       return sum;
00157     }
00158 
00159     double norm1() const {
00160       double sum = 0.0;
00161       for(unsigned i = 0; i < d; i++) {
00162         sum += (*this)[i];
00163       }
00164       return sum;
00165     }
00166 
00167     bool bitwiseEqual(const Point& other) const {
00168       return std::equal(this->begin(), this->end(), other.begin());
00169     }
00170 
00171     std::string toString() const {
00172       std::string s = "(";
00173       for (unsigned i = 0; i < d; i++) {
00174         char buffer[4000];
00175         snprintf(buffer, sizeof(buffer), " %g", (*this)[i]);
00176         s += buffer;
00177       }
00178       s += " )";
00179       return s;
00180     }
00181 };
00182 
00189 inline Point<3> crossProduct(const Point<3>& a, const Point<3>& b) {
00190   Point<3> p;
00191   p[0] = a[1]*b[2] - a[2]*b[1];
00192   p[1] = a[2]*b[0] - a[0]*b[2];
00193   p[2] = a[0]*b[1] - a[1]*b[0];
00194   return p;
00195 }
00196 
00197 
00198 }
00199 
00200 #endif

Generated on Thu Mar 27 19:04:14 2008 by  doxygen 1.4.6