00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef JOT_POINT3D_H
00024 #define JOT_POINT3D_H
00025
00027
00028
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
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
00074 void operator %=(const P &p) { _x += p[0]; _y += p[1]; _z += p[2]; }
00075
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 };
00081
00082
00083
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
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
00134
00135
00136
00137
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
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
00196
00197
00198
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
00240
00241
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
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
00260
00261
00262 void prepend( L * poly ) { L pts(*poly);
00263 for (int i = 0; i < _num; i++)
00264 pts += (*this)[i];
00265
00266 clear();
00267 *this = pts;
00268 }
00269
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