Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

point3d.H

Go to the documentation of this file.
00001 /*
00002  * Copyright 2000, Brown University, Providence, RI.
00003  * 
00004  *                         All Rights Reserved
00005  * 
00006  * Permission to use, copy, modify, and distribute this software and its
00007  * documentation for any purpose other than its incorporation into a
00008  * commercial product is hereby granted without fee, provided that the
00009  * above copyright notice appear in all copies and that both that
00010  * copyright notice and this permission notice appear in supporting
00011  * documentation, and that the name of Brown University not be used in
00012  * advertising or publicity pertaining to distribution of the software
00013  * without specific, written prior permission.
00014  * 
00015  * BROWN UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
00016  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY
00017  * PARTICULAR PURPOSE.  IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE FOR
00018  * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00019  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00020  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00021  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00022  */
00023 #ifndef JOT_POINT3D_H
00024 #define JOT_POINT3D_H
00025 
00027 // DESCRIPTION :
00028 //    the '%' operator allows points to be added together
00030 
00031 #include <limits.h>
00032 #include "vector3d.H"
00033 #include "std/config.H"
00034 #include "nearest_pt.H"
00035 #include "std/list.H"
00036 
00037 template <class P, class V>
00038 class _point3d
00039 {
00040 protected:
00041     Greal _x, _y, _z;
00042 
00043 public:
00044 
00045     _point3d()                             : _x(0),    _y(0),    _z(0)   {}
00046     _point3d(Greal x, Greal y, Greal z) : _x(x),    _y(y),    _z(z)   {}
00047 
00048     void          set(Greal x, Greal y, Greal z)  { _x=x; _y=y; _z=z; }
00049     const Greal *data()            const{ return &_x; }
00050 
00051     P  operator  *(Greal s)        const{ return P(_x*s, _y*s, _z*s);}
00052     P  operator  /(Greal s)        const{ return P(_x/s, _y/s, _z/s);}
00053     // Point + Point
00054     P  operator  %(const P &p)      const{ return P(_x+p[0], _y+p[1], _z+p[2]);}
00055     P  operator  +(const V &v)      const{ return P(_x+v[0], _y+v[1], _z+v[2]);}
00056     V  operator  -(const P &p)      const{ return V(_x-p[0], _y-p[1], _z-p[2]);}
00057     P  operator  -(const V &v)      const{ return P(_x-v[0], _y-v[1], _z-v[2]);}
00058     P  operator  -()                const{ return P(-_x, -_y, -_z);}
00059     
00060     Greal  operator [](int index)  const{ return (&_x)[index]; }
00061     Greal& operator [](int index)       { return (&_x)[index]; }
00062 
00063     Greal  distSqrd   (const P &p) const{ return (_x-p._x)*(_x-p._x) + 
00064                                                      (_y-p._y)*(_y-p._y) + 
00065                                                      (_z-p._z)*(_z-p._z); }
00066     Greal  dist       (const P &p) const{ return sqrt(distSqrd(p));}
00067 
00068     bool    isEqual    (const P &p, Greal epsSqrd = epsAbsSqrdMath()) const 
00069                                          { return distSqrd(p) <= epsSqrd; }
00070 
00071     bool    operator ==(const P &p) const{ return _x==p._x&&_y==p._y&&_z==p._z;}
00072     bool    operator !=(const P &p) const{ return _x!=p._x||_y!=p._y||_z!=p._z;}
00073     // Point = Point + Point
00074     void    operator %=(const P &p)      { _x += p[0]; _y += p[1]; _z += p[2]; }
00075     // Point = Point + Vector
00076     void    operator +=(const V &v)      { _x += v[0]; _y += v[1]; _z += v[2]; }
00077     void    operator -=(const V &v)      { _x -= v[0]; _y -= v[1]; _z -= v[2]; }
00078     void    operator *=(Greal   s)       { _x *= s; _y *= s; _z *= s; }
00079     void    operator /=(Greal   s)       { _x /= s; _y /= s; _z /= s; }
00080 }; // class point3d
00081 
00082 
00083 /* ---------- inlined global functions using _point3d template ------ */
00084 
00085 template <class P, class V>
00086 inline ostream &
00087 operator<<(ostream &os, const _point3d<P,V> &p) 
00088 { 
00089    return os << "< " << p[0] << " " << p[1] << " " << p[2] << " > ";
00090 }
00091 
00092 
00093 template <class P, class V>
00094 inline istream &
00095 operator>>(istream &is, _point3d<P,V> &p) 
00096 { 
00097    char dummy;
00098    return is >> dummy >> p[0] >> p[1] >> p[2] >> dummy;
00099 }
00100 
00101 
00102 template <class P, class V>
00103 inline Greal 
00104 det(const _point3d<P,V> &a, const _point3d<P,V> &b, const _point3d<P,V> &c)
00105 {
00106    return (a[0] * (b[1]*c[2] - b[2]*c[1]) +
00107            a[1] * (b[2]*c[0] - b[0]*c[2]) +
00108            a[2] * (b[0]*c[1] - b[1]*c[0]));
00109 } 
00110 
00111 
00112 template <class P>
00113 extern bool     areCoplanar(const P &, const P &, const P &, const P &);
00114 
00115 
00116 // -----------------------------------------------------------------------
00117 //
00118 //   point3d_list -
00119 //
00120 // -----------------------------------------------------------------------
00121 template <class L, class T, class P, class V>
00122 class _point3d_list : public ARRAY<P> {
00123  protected:
00124    ARRAY<Greal>    _partial_length;
00125 
00126  public :
00127    _point3d_list(int max=16)       :ARRAY<P>(max),_partial_length(0) { }
00128    _point3d_list(const ARRAY<P> &p):ARRAY<P>(p),  _partial_length(0) { }
00129    _point3d_list(const ARRAY<P> &p, const T &t):ARRAY<P>(p),_partial_length(0) 
00130                                                            { xform(t); }
00131 
00132    void   xform   (const T &t);
00133    // computes everything about the point on the line closest to p.
00134    // returns the point, its distance to the line,
00135    // and the index of the point that starts its segment.
00136    // (that is, the point is on the line segment between
00137    // points [seg_index] and [seg_index+1])
00138    void   closest (const P &p, P &nearpt, Greal &neardist, int &segind) const{
00139       neardist = DBL_MAX;
00140      
00141       for (int i = 0; i < num()-1; i++) {
00142          const P a((*this)[i]);
00143          const P b((*this)[i+1]);
00144          const P npt = nearest_pt_to_line_seg(p,a,b);
00145          const Greal d = (npt-p).lengthSqrd();
00146          if (d < neardist) {
00147             neardist = d;
00148             nearpt   = npt;
00149             segind   = i;
00150          }
00151       }
00152       neardist = sqrt(neardist);
00153    }
00154    Greal closest (const P &p, P  &nearpt, int    &nearind) const {
00155       Greal d;
00156       int    i;
00157       closest(p, nearpt, d, i);
00158 
00159       P a((*this)[i]);
00160       P b((*this)[i+1]);
00161       if ((p-a).length() < (p-b).length())
00162            nearind = i;
00163       else nearind = i+1;
00164       return d;
00165    }
00166    P closest (const P &p) const {
00167       P nearpt(DBL_MAX,DBL_MAX,DBL_MAX);
00168       Greal dist;
00169       int    index;
00170       closest (p, nearpt, dist, index);
00171       return nearpt;
00172    }
00173    V      tan     (int i) const { P *ar = _array;
00174                                   const int n=num()-1;
00175                                   if (i<0 || i>n || n<1) return V();
00176                                   if (i==0) return (ar[1]-ar[  0]).normalize();
00177                                   if (i==n) return (ar[n]-ar[n-1]).normalize();
00178                                   return ((ar[i+1]-ar[i]).normalize() +
00179                                           (ar[i]-ar[i-1]).normalize()).
00180                                                                    normalize();
00181                                   }
00182 
00183    // Interpolation
00184    P      interpolate       (Greal s, V *tan=0, int*segp=0, Greal*tp=0) const{
00185                  int seg;
00186                  Greal t;
00187                  interpolate_length(s, seg, t);
00188                  const V v = _array[seg+1]-_array[seg];
00189                  if (tan)  *tan  = v.normalize();
00190                  if (segp) *segp = seg;
00191                  if (tp)   *tp   = t;
00192 
00193                  return _array[seg]+v*t;
00194                  }
00195          // assume update_length() has been called.
00196          // note if there are 0 or 1 points, _length will be 0, we return early.
00197          // note also, generally returns 0<=t<1,
00198          // except at the extreme right, returns t=1;
00199    void   interpolate_length(Greal s, int &seg, Greal &t)  const {
00200 
00201      const Greal val = s*length();
00202      if (val <= 0) { 
00203         seg = 0; 
00204         t   = 0; 
00205         return; 
00206      }
00207      if (val >= length()) { 
00208         seg = _num-2; 
00209         t = 1; 
00210         return; 
00211      }
00212 
00213      int l=0, r=_num-1, m;
00214      while ((m = (l+r) >> 1) != l) {
00215         if (val < _partial_length[m])       
00216          r = m;
00217         else l = m;
00218      }
00219      seg = m;
00220      t = (val-_partial_length[m])/(_partial_length[m+1]-_partial_length[m]);
00221       }
00222    Greal invert             (const P &pt) const {
00223       P      nearpt;
00224       Greal neardist;
00225       int    seg_index;
00226 
00227       closest(pt, nearpt, neardist, seg_index);
00228       return invert(pt, seg_index);
00229    }
00230    Greal invert             (const P &pt, int seg ) const {
00231       const V v     = _array[seg + 1] - _array[seg];
00232       const V vnorm = v.normalize();
00233       const P pp    = _array[seg] + ( (pt - _array[seg]) * vnorm ) * vnorm;
00234 
00235       Greal len = _partial_length[seg] + (pp-_array[seg]).length();
00236       return len/length();
00237    }
00238 
00239    // Parameterization / Lengths
00240    
00241    // Update partial lengths
00242    void   update_length      () { Greal len = 0;
00243                                   _partial_length.clear();
00244                                   if (_num > 0)
00245                                      _partial_length.realloc(_num);
00246                                   _partial_length += 0;
00247                                   for ( int i=1; i< _num; i++ ) {
00248                                      len += segment_length(i-1);
00249                                      _partial_length += len;
00250                                   }
00251                                }
00252    Greal partial_length     (int i) const { return i>=_partial_length.num() ? 
00253                                                    0 : _partial_length[i]; }
00254    // Partial lengths must be up to date
00255    Greal length             ()      const { return _partial_length.last(); }
00256    V      segment            (int i) const { return _array[i+1]-_array[i];}
00257    Greal segment_length     (int i) const { return segment(i).length(); }
00258 
00259    // Editing
00260    
00261    // Prepend poly to our list
00262    void   prepend( L * poly ) { L pts(*poly); 
00263                                 for (int i = 0; i < _num; i++)
00264                                    pts += (*this)[i];
00265 
00266                                 clear();   // Is this necessary?
00267                                 *this = pts;
00268                               }
00269    // Append poly to our list
00270    void   append ( L *poly ) { *this += *poly; }
00271    L*     clone_piece( int k1, int k2 ) const;
00272    V      normal() const {
00273                V  ret(V::Y);
00274                if (num() > 2) {
00275                   const int delta = num() / (num() == 3 ? 3 : 4);
00276                   const P a = _array[0];
00277                   const P b = _array[delta];
00278                   const P c = _array[2 * delta];
00279                   const P d = _array[(3 * delta) % num()];
00280                   ret = V((c[1]-a[1])*(d[2]-b[2]) + (c[2]-a[2])*(b[1]-d[1]),
00281                           (c[2]-a[2])*(d[0]-b[0]) + (c[0]-a[0])*(b[2]-d[2]),
00282                           (c[0]-a[0])*(d[1]-b[1]) + (c[1]-a[1])*(b[0]-d[0]));
00283                }
00284                return ret;
00285           }
00286 
00287    P      average () const { P sum; for(int i=0;i<num();i++) sum=sum%(*this)[i];
00288                              return sum/(num() ? num():1); }
00289    L      inset(Greal ins) const { 
00290               L cur;
00291               T rot(T::rotation(V::Y,1.57));
00292               for (int i = 0; i < num(); i++)
00293                  cur += inset_pt(i, rot, ins);
00294               return cur;
00295           }
00296    P      inset_pt(int ind, const T &rot, Greal inset) const {
00297                P p1((*this)[(ind-1+num())%num()]);
00298                P p2((*this)[ ind               ]);
00299                P p3((*this)[(ind+1)      %num()]);
00300 
00301                if (num() == 2) {
00302                   if (ind == 1)
00303                        return P(p2 - (rot * (p3-p2)).normalize() * inset);
00304                   else return P(p2 - (rot * (p2-p1)).normalize() * inset);
00305                }
00306 
00307                return P(p2 + ((rot * (p3-p2)).normalize() + 
00308                               (rot * (p2-p1)).normalize() ).normalize()*inset);
00309             }
00310 };
00311 
00312 #ifdef GLUE_NEEDS_TEMPLATES_IN_H_FILE
00313 #include "point3d.C"
00314 #endif
00315 #endif

Generated on Mon Sep 15 16:25:57 2003 for gluebase by doxygen1.2.18