WFMath  1.0.1
point.h
00001 // point.h (point class copied from libCoal, subsequently modified)
00002 //
00003 //  The WorldForge Project
00004 //  Copyright (C) 2000, 2001, 2002  The WorldForge Project
00005 //
00006 //  This program is free software; you can redistribute it and/or modify
00007 //  it under the terms of the GNU General Public License as published by
00008 //  the Free Software Foundation; either version 2 of the License, or
00009 //  (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 //
00020 //  For information about WorldForge and its authors, please contact
00021 //  the Worldforge Web Site at http://www.worldforge.org.
00022 //
00023 
00024 // Author: Ron Steinke
00025 
00026 #ifndef WFMATH_POINT_H
00027 #define WFMATH_POINT_H
00028 
00029 #include <wfmath/const.h>
00030 
00031 #include <memory>
00032 #include <iosfwd>
00033 
00034 #include <cmath>
00035 
00036 namespace WFMath {
00037 
00038 template<int dim>
00039 Point<dim>& operator+=(Point<dim>& p, const Vector<dim>& v);
00040 template<int dim>
00041 Point<dim>& operator-=(Point<dim>& p, const Vector<dim>& v);
00042 
00043 template<int dim>
00044 Vector<dim> operator-(const Point<dim>& c1, const Point<dim>& c2);
00045 template<int dim>
00046 Point<dim> operator+(const Point<dim>& c, const Vector<dim>& v);
00047 template<int dim>
00048 Point<dim> operator+(const Vector<dim>& v, const Point<dim>& c);
00049 template<int dim>
00050 Point<dim> operator-(const Point<dim>& c, const Vector<dim>& v);
00051 
00052 template<int dim>
00053 CoordType SquaredDistance(const Point<dim>& p1, const Point<dim>& p2);
00054 template<int dim>
00055 CoordType Distance(const Point<dim>& p1, const Point<dim>& p2)
00056   {return std::sqrt(SquaredDistance(p1, p2));}
00057 template<int dim>
00058 CoordType SloppyDistance(const Point<dim>& p1, const Point<dim>& p2)
00059   {return (p1 - p2).sloppyMag();}
00060 
00062 template<int dim, template<class, class> class container>
00063 Point<dim> Barycenter(const container<Point<dim>, std::allocator<Point<dim> > >& c);
00065 
00071 template<int dim, template<class, class> class container,
00072       template<class, class> class container2>
00073 Point<dim> Barycenter(const container<Point<dim>, std::allocator<Point<dim> > >& c,
00074           const container2<CoordType, std::allocator<CoordType> >& weights);
00075 
00076 // This is used a couple of places in the library
00077 template<int dim>
00078 Point<dim> Midpoint(const Point<dim>& p1, const Point<dim>& p2,
00079         CoordType dist = 0.5);
00080 
00081 template<int dim>
00082 std::ostream& operator<<(std::ostream& os, const Point<dim>& m);
00083 template<int dim>
00084 std::istream& operator>>(std::istream& is, Point<dim>& m);
00085 
00086 template<typename Shape>
00087 class ZeroPrimitive;
00088 
00090 
00094 template<int dim = 3>
00095 class Point
00096 {
00097  friend class ZeroPrimitive<Point<dim> >;
00098  public:
00100   Point () : m_valid(false) {}
00102   Point (const Point& p);
00104   explicit Point (const AtlasInType& a);
00106   explicit Point(const Vector<dim>& vector);
00107 
00111   static const Point<dim>& ZERO();
00112 
00113   friend std::ostream& operator<< <dim>(std::ostream& os, const Point& p);
00114   friend std::istream& operator>> <dim>(std::istream& is, Point& p);
00115 
00117   AtlasOutType toAtlas() const;
00119   void fromAtlas(const AtlasInType& a);
00120 
00121   Point& operator= (const Point& rhs);
00122 
00123   bool isEqualTo(const Point &p, CoordType epsilon = numeric_constants<CoordType>::epsilon()) const;
00124   bool operator== (const Point& rhs) const      {return isEqualTo(rhs);}
00125   bool operator!= (const Point& rhs) const      {return !isEqualTo(rhs);}
00126 
00127   bool isValid() const {return m_valid;}
00129   void setValid(bool valid = true) {m_valid = valid;}
00130 
00132   Point& setToOrigin();
00133 
00134   // Operators
00135 
00136   // Documented in vector.h
00137   friend Vector<dim> operator-<dim>(const Point& c1, const Point& c2);
00138   friend Point operator+<dim>(const Point& c, const Vector<dim>& v);
00139   friend Point operator-<dim>(const Point& c, const Vector<dim>& v);
00140   friend Point operator+<dim>(const Vector<dim>& v, const Point& c);
00141 
00142   friend Point& operator+=<dim>(Point& p, const Vector<dim>& rhs);
00143   friend Point& operator-=<dim>(Point& p, const Vector<dim>& rhs);
00144 
00146   Point& rotate(const RotMatrix<dim>& m, const Point& p)
00147   {return (*this = p + Prod(*this - p, m));}
00148 
00149   // Functions so that Point<> has the generic shape interface
00150 
00151   size_t numCorners() const {return 1;}
00152   Point<dim> getCorner(size_t) const { return *this;}
00153   Point<dim> getCenter() const {return *this;}
00154 
00155   Point shift(const Vector<dim>& v) {return *this += v;}
00156   Point moveCornerTo(const Point& p, size_t)
00157   {return operator=(p);}
00158   Point moveCenterTo(const Point& p) {return operator=(p);}
00159 
00160   Point& rotateCorner(const RotMatrix<dim>&, size_t)
00161   {return *this;}
00162   Point& rotateCenter(const RotMatrix<dim>&) {return *this;}
00163   Point& rotatePoint(const RotMatrix<dim>& m, const Point& p) {return rotate(m, p);}
00164 
00165   // 3D rotation functions
00166   Point& rotate(const Quaternion& q, const Point& p);
00167   Point& rotateCorner(const Quaternion&, size_t)
00168   { return *this;}
00169   Point& rotateCenter(const Quaternion&) {return *this;}
00170   Point& rotatePoint(const Quaternion& q, const Point& p);
00171 
00172   // The implementations of these lie in axisbox_funcs.h and
00173   // ball_funcs.h, to reduce include dependencies
00174   AxisBox<dim> boundingBox() const;
00175   Ball<dim> boundingSphere() const;
00176   Ball<dim> boundingSphereSloppy() const;
00177 
00178   Point toParentCoords(const Point& origin,
00179       const RotMatrix<dim>& rotation = RotMatrix<dim>().identity()) const
00180   {return origin + (*this - Point().setToOrigin()) * rotation;}
00181   Point toParentCoords(const AxisBox<dim>& coords) const;
00182   Point toParentCoords(const RotBox<dim>& coords) const;
00183 
00184   // toLocal is just like toParent, expect we reverse the order of
00185   // translation and rotation and use the opposite sense of the rotation
00186   // matrix
00187 
00188   Point toLocalCoords(const Point& origin,
00189       const RotMatrix<dim>& rotation = RotMatrix<dim>().identity()) const
00190   {return Point().setToOrigin() + rotation * (*this - origin);}
00191   Point toLocalCoords(const AxisBox<dim>& coords) const;
00192   Point toLocalCoords(const RotBox<dim>& coords) const;
00193 
00194   // 3D only
00195   Point toParentCoords(const Point& origin, const Quaternion& rotation) const;
00196   Point toLocalCoords(const Point& origin, const Quaternion& rotation) const;
00197 
00198   // Member access
00199 
00201   CoordType operator[](const int i) const {return m_elem[i];}
00203   CoordType& operator[](const int i)      {return m_elem[i];}
00204 
00206   friend CoordType SquaredDistance<dim>(const Point& p1, const Point& p2);
00207 
00208 // FIXME instatiation problem when declared as friend
00209 //  template<template<class> class container>
00210 //  friend Point Barycenter(const container<Point>& c);
00211 
00213 
00219   friend Point<dim> Midpoint<dim>(const Point& p1, const Point& p2, CoordType dist);
00220 
00221   // 2D/3D stuff
00222 
00224   Point (CoordType x, CoordType y); // 2D only
00226   Point (CoordType x, CoordType y, CoordType z); // 3D only
00227 
00228   // Label the first three components of the vector as (x,y,z) for
00229   // 2D/3D convienience
00230 
00232   CoordType x() const   {return m_elem[0];}
00234   CoordType& x()        {return m_elem[0];}
00236   CoordType y() const   {return m_elem[1];}
00238   CoordType& y()        {return m_elem[1];}
00240   CoordType z() const;
00242   CoordType& z();
00243 
00245   Point& polar(CoordType r, CoordType theta);
00247   void asPolar(CoordType& r, CoordType& theta) const;
00248 
00250   Point& polar(CoordType r, CoordType theta, CoordType z);
00252   void asPolar(CoordType& r, CoordType& theta, CoordType& z) const;
00254   Point& spherical(CoordType r, CoordType theta, CoordType phi);
00256   void asSpherical(CoordType& r, CoordType& theta, CoordType& phi) const;
00257 
00258   const CoordType* elements() const {return m_elem;}
00259 
00260  private:
00261   CoordType m_elem[dim];
00262   bool m_valid;
00263 };
00264 
00265 template<>
00266 inline CoordType Point<3>::z() const
00267 {
00268   return m_elem[2];
00269 }
00270 
00271 template<>
00272 inline CoordType& Point<3>::z()
00273 {
00274   return m_elem[2];
00275 }
00276 
00277 template<int dim>
00278 inline Point<dim> operator+(const Point<dim>& c, const Vector<dim>& v)
00279 {
00280   Point<dim> out(c);
00281 
00282   out += v;
00283 
00284   return out;
00285 }
00286 
00287 template<int dim>
00288 inline Point<dim> operator+(const Vector<dim>& v, const Point<dim>& c)
00289 {
00290   Point<dim> out(c);
00291 
00292   out += v;
00293 
00294   return out;
00295 }
00296 
00297 template<int dim>
00298 inline Point<dim> operator-(const Point<dim>& c, const Vector<dim>& v)
00299 {
00300   Point<dim> out(c);
00301 
00302   out -= v;
00303 
00304   return out;
00305 }
00306 
00307 template<>
00308 inline Point<2>::Point(CoordType x, CoordType y) : m_valid(true)
00309 {
00310   m_elem[0] = x;
00311   m_elem[1] = y;
00312 }
00313 
00314 template<>
00315 inline Point<3>::Point(CoordType x, CoordType y, CoordType z) : m_valid(true)
00316 {
00317   m_elem[0] = x;
00318   m_elem[1] = y;
00319   m_elem[2] = z;
00320 }
00321 
00322 } // namespace WFMath
00323 
00324 #endif  // WFMATH_POINT_H