00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef POINT2D_H_DEFINED
00039 #define POINT2D_H_DEFINED
00040
00041 #include "Image/Dims.H"
00042 #include "Util/Promotions.H"
00043 #include "Util/log.H"
00044 #include <cmath>
00045 #include <string>
00046 #include <vector>
00047
00048
00049
00050
00051
00052 template <class T>
00053 class Point2D
00054 {
00055 public:
00056
00057 inline Point2D();
00058
00059
00060 inline Point2D(const T ii, const T jj);
00061
00062
00063 explicit inline Point2D(const Dims& d);
00064
00065
00066
00067
00068 template <class U>
00069 explicit inline Point2D(const Point2D<U>& a);
00070
00071
00072 inline Point2D<T>& operator+=(const Point2D<T> &p);
00073
00074 inline Point2D<T>& operator-=(const Point2D<T> &p);
00075
00076 inline Point2D<T>& operator*=(const Point2D<T> &p);
00077
00078 inline Point2D<T>& operator/=(const Point2D<T> &p);
00079
00080
00081 template <class U>
00082 inline Point2D<typename promote_trait<T,U>::TP>
00083 operator+(const Point2D<U> &p) const;
00084
00085 template <class U>
00086 inline Point2D<typename promote_trait<T,U>::TP>
00087 operator-(const Point2D<U> &p) const;
00088
00089 template <class U>
00090 inline Point2D<typename promote_trait<T,U>::TP>
00091 operator*(const Point2D<U> &p) const;
00092
00093 template <class U>
00094 inline Point2D<typename promote_trait<T,U>::TP>
00095 operator/(const Point2D<U> &p) const;
00096
00097
00098 inline Point2D<T>& operator+=(const T val);
00099
00100 inline Point2D<T>& operator-=(const T val);
00101
00102 inline Point2D<T>& operator*=(const T val);
00103
00104 inline Point2D<T>& operator/=(const T val);
00105
00106
00107 template <class U>
00108 inline Point2D<typename promote_trait<T,U>::TP> operator+(const U val) const;
00109
00110
00111 template <class U>
00112 inline Point2D<typename promote_trait<T,U>::TP> operator-(const U val) const;
00113
00114
00115 template <class U>
00116 inline Point2D<typename promote_trait<T,U>::TP> operator*(const U val) const;
00117
00118
00119 template <class U>
00120 inline Point2D<typename promote_trait<T,U>::TP> operator/(const U val) const;
00121
00122
00123 inline bool isValid() const;
00124
00125
00126 inline typename promote_trait<T,float>::TP
00127 squdist(const Point2D<T>& p) const;
00128
00129
00130 inline typename promote_trait<T,float>::TP
00131 distance(const Point2D<T>& p) const;
00132
00133
00134 inline typename promote_trait<T,float>::TP
00135 magnitude() const;
00136
00137
00138 inline typename promote_trait<T,float>::TP
00139 distanceToLine(const Point2D<T>& p, const Point2D<T>& q,
00140 const bool getsigned = false) const;
00141
00142
00143 inline typename promote_trait<T,float>::TP
00144 distanceToSegment(const Point2D<T>& p, const Point2D<T>& q) const;
00145
00146
00147 inline void clampToDims(const Dims& dims);
00148
00149
00150 T i, j;
00151 };
00152
00153
00154
00155 template <class T, class U>
00156 inline bool operator==(const Point2D<T>& p1, const Point2D<U>& p2);
00157
00158
00159 template <class T, class U>
00160 inline bool operator!=(const Point2D<T>& p1, const Point2D<U>& p2);
00161
00162
00163 template <class T, class U>
00164 inline bool operator>(const Point2D<T>& p1, const Point2D<U>& p2);
00165
00166
00167 template <class T, class U>
00168 inline bool operator<(const Point2D<T>& p1, const Point2D<U>& p2);
00169
00170
00171
00172 template <class T>
00173 std::string convertToString(const Point2D<T>& val);
00174
00175
00176 template <class T>
00177 void convertFromString(const std::string& str, Point2D<T>& val);
00178
00179
00180 template <class T>
00181 inline bool pnpoly(const std::vector<Point2D<T> > &polygon,
00182 const Point2D<T>& p);
00183
00184
00185 template <class T>
00186 inline Point2D<T> centroid(const std::vector<Point2D<T> > &polygon);
00187
00188
00189 template <class T>
00190 inline double area(const std::vector<Point2D<T> > &polygon,
00191 const bool getsigned = false);
00192
00193
00194 template <class T>
00195 inline double angleMeasure(const Point2D<T> & A,
00196 const Point2D<T> & B,
00197 const Point2D<T> & C);
00198
00199
00200 template <class T>
00201 inline bool pnTriangle(const Point2D<T>& A,
00202 const Point2D<T>& B,
00203 const Point2D<T>& C,
00204 const Point2D<T>& P);
00205
00206
00207
00208 template <class T>
00209 inline Point2D<T>::Point2D()
00210 { i = 0; j = 0; }
00211
00212
00213 template <class T>
00214 inline Point2D<T>::Point2D(const T ii, const T jj)
00215 { i = ii; j = jj; }
00216
00217
00218 template <class T>
00219 inline Point2D<T>::Point2D(const Dims& d)
00220 { i = d.w(); j = d.h(); }
00221
00222
00223 template <class T>
00224 template <class U>
00225 inline Point2D<T>::Point2D(const Point2D<U>& a)
00226 : i(clamped_convert<T>(a.i)), j(clamped_convert<T>(a.j))
00227 { }
00228
00229
00230 template <class T>
00231 inline Point2D<T>& Point2D<T>::operator+=(const Point2D<T> &p)
00232 { i += p.i; j += p.j; return *this; }
00233
00234
00235 template <class T>
00236 inline Point2D<T>& Point2D<T>::operator-=(const Point2D<T> &p)
00237 { i -= p.i; j -= p.j; return *this; }
00238
00239
00240 template <class T>
00241 inline Point2D<T>& Point2D<T>::operator*=(const Point2D<T> &p)
00242 { i *= p.i; j *= p.j; return *this; }
00243
00244
00245 template <class T>
00246 inline Point2D<T>& Point2D<T>::operator/=(const Point2D<T> &p)
00247 { i /= p.i; j /= p.j; return *this; }
00248
00249
00250 template <class T>
00251 template <class U>
00252 inline Point2D<typename promote_trait<T,U>::TP>
00253 Point2D<T>::operator+(const Point2D<U> &p) const
00254 { return Point2D<typename promote_trait<T,U>::TP>(i + p.i, j + p.j); }
00255
00256
00257 template <class T>
00258 template <class U>
00259 inline Point2D<typename promote_trait<T,U>::TP>
00260 Point2D<T>::operator-(const Point2D<U> &p) const
00261 { return Point2D<typename promote_trait<T,U>::TP>(i - p.i, j - p.j); }
00262
00263
00264 template <class T>
00265 template <class U>
00266 inline Point2D<typename promote_trait<T,U>::TP>
00267 Point2D<T>::operator*(const Point2D<U> &p) const
00268 { return Point2D<typename promote_trait<T,U>::TP>(i * p.i, j * p.j); }
00269
00270
00271 template <class T>
00272 template <class U>
00273 inline Point2D<typename promote_trait<T,U>::TP>
00274 Point2D<T>::operator/(const Point2D<U> &p) const
00275 { return Point2D<typename promote_trait<T,U>::TP>(i / p.i, j / p.j); }
00276
00277
00278 template <class T>
00279 inline Point2D<T>& Point2D<T>::operator+=(const T val)
00280 { i += val; j += val; return *this; }
00281
00282
00283 template <class T>
00284 inline Point2D<T>& Point2D<T>::operator-=(const T val)
00285 { i -= val; j -= val; return *this; }
00286
00287
00288 template <class T>
00289 inline Point2D<T>& Point2D<T>::operator*=(const T val)
00290 { i *= val; j *= val; return *this; }
00291
00292
00293 template <class T>
00294 inline Point2D<T>& Point2D<T>::operator/=(const T val)
00295 { i /= val; j /= val; return *this; }
00296
00297
00298 template <class T>
00299 template <class U>
00300 inline Point2D<typename promote_trait<T,U>::TP>
00301 Point2D<T>::operator+(const U val) const
00302 { return Point2D<typename promote_trait<T,U>::TP>(this->i+val, this->j+val); }
00303
00304
00305 template <class T>
00306 template <class U>
00307 inline Point2D<typename promote_trait<T,U>::TP>
00308 Point2D<T>::operator-(const U val) const
00309 { return Point2D<typename promote_trait<T,U>::TP>(this->i-val, this->j-val); }
00310
00311
00312 template <class T>
00313 template <class U>
00314 inline Point2D<typename promote_trait<T,U>::TP>
00315 Point2D<T>::operator*(const U val) const
00316 { return Point2D<typename promote_trait<T,U>::TP>(this->i*val, this->j*val); }
00317
00318
00319 template <class T>
00320 template <class U>
00321 inline Point2D<typename promote_trait<T,U>::TP>
00322 Point2D<T>::operator/(const U val) const
00323 { return Point2D<typename promote_trait<T,U>::TP>(this->i/val, this->j/val); }
00324
00325
00326 template <class T, class U>
00327 inline bool operator==(const Point2D<T>& p1, const Point2D<U>& p2)
00328 { return p1.i == p2.i && p1.j == p2.j; }
00329
00330
00331 template <class T, class U>
00332 inline bool operator!=(const Point2D<T>& p1, const Point2D<U>& p2)
00333 { return p1.i != p2.i || p1.j != p2.j; }
00334
00335
00336 template <class T, class U>
00337 inline bool operator>(const Point2D<T>& p1, const Point2D<U>& p2)
00338 { return p1.i > p2.i && p1.j > p2.j; }
00339
00340
00341 template <class T, class U>
00342 inline bool operator<(const Point2D<T>& p1, const Point2D<U>& p2)
00343 { return p1.i < p2.i && p1.j < p2.j; }
00344
00345
00346 template <class T>
00347 inline bool Point2D<T>::isValid() const
00348 { return ((i >= 0) && (j >= 0)); }
00349
00350
00351 template <class T>
00352 inline typename promote_trait<T,float>::TP
00353 Point2D<T>::squdist(const Point2D<T>& p) const
00354 {
00355 typedef typename promote_trait<T,float>::TP TF;
00356 TF d1 = p.i - i, d2 = p.j - j;
00357 return (d1 * d1 + d2 * d2);
00358 }
00359
00360
00361 template <class T>
00362 inline typename promote_trait<T,float>::TP
00363 Point2D<T>::distance(const Point2D<T>& p) const
00364 { return sqrt(squdist(p)); }
00365
00366
00367 template <class T>
00368 inline typename promote_trait<T,float>::TP
00369 Point2D<T>::magnitude() const
00370 { return sqrt((i*i) + (j*j)); }
00371
00372
00373 template <class T>
00374 inline typename promote_trait<T,float>::TP
00375 Point2D<T>::distanceToLine(const Point2D<T>& p, const Point2D<T>& q,
00376 const bool getsigned) const
00377 {
00378
00379 typedef typename promote_trait<T,float>::TP TF;
00380 TF a = q.j - p.j, b = q.i - p.i, c = q.i * p.j - q.j * p.i;
00381 if (getsigned) return (a*i-b*j+c)/sqrt(a*a + b*b);
00382 else return fabs(a*i-b*j+c)/sqrt(a*a + b*b);
00383 }
00384
00385
00386 template <class T>
00387 inline typename promote_trait<T,float>::TP
00388 Point2D<T>::distanceToSegment(const Point2D<T>& p, const Point2D<T>& q) const
00389 {
00390
00391 Point2D<T> V0 = q-p, V1 = (*this)-q, V2 = (*this)-p;
00392 if (V0.i*V1.i + V0.j*V1.j>0) return distance(q);
00393 if (V0.i*V2.i + V0.j*V2.j<0) return distance(p);
00394 return distanceToLine(p,q);
00395 }
00396
00397
00398 template <class T>
00399 inline void Point2D<T>::clampToDims(const Dims& dims)
00400 {
00401 if (dims.isEmpty())
00402 LFATAL("clampToDims() requires non-empty Dims");
00403
00404 if (i < 0) i = 0; else if (i >= dims.w()) i = dims.w()-1;
00405 if (j < 0) j = 0; else if (j >= dims.h()) j = dims.h()-1;
00406 }
00407
00408
00409
00410
00411 template <class T>
00412 inline bool pnpoly(const std::vector<Point2D<T> > &polygon,
00413 const Point2D<T>& p)
00414 {
00415 bool c = false; const uint ps = polygon.size();
00416 for (uint i = 0, j = ps-1; i < ps; j = i++)
00417 if ((((polygon[i].j <= p.j) && (p.j < polygon[j].j)) ||
00418 ((polygon[j].j <= p.j) && (p.j < polygon[i].j))) &&
00419 (p.i < (polygon[j].i - polygon[i].i) *
00420 (p.j - polygon[i].j) / (polygon[j].j - polygon[i].j)
00421 + polygon[i].i))
00422 c = !c;
00423
00424 return c;
00425 }
00426
00427
00428 template <class T>
00429 inline Point2D<T> centroid(const std::vector<Point2D<T> > &polygon)
00430 {
00431 Point2D<T> CM(0,0);
00432 const uint ps = polygon.size();
00433 for (uint i = 0; i < ps; i++) CM += polygon[i];
00434 return CM / ps;
00435 }
00436
00437
00438 template <class T>
00439 inline double area(const std::vector<Point2D<T> > &polygon, const bool getsigned)
00440 {
00441 double area = 0.0;
00442 const uint ps = polygon.size();
00443 for (uint i = 0, j = ps-1; i < ps; j = i++)
00444 area += polygon[i].i*polygon[j].j - polygon[i].j*polygon[j].i;
00445 if (getsigned) return (0.5 * area);
00446 else return fabs(0.5 * area);
00447 }
00448
00449
00450 template <class T>
00451 inline double angleMeasure(const Point2D<T> & A,
00452 const Point2D<T> & B,
00453 const Point2D<T> & C)
00454 {
00455 const double eps = 0.00001;
00456 double Sab = A.distance(B), Sac = A.distance(C), Sbc = B.distance(C);
00457
00458 if (Sab * Sac * Sbc == 0 || fabs(Sab - Sac + Sbc) < eps
00459 || fabs(- Sab + Sac + Sbc) < eps) return 0;
00460 else if(fabs(Sab + Sac - Sbc) < eps) return 3.1415;
00461
00462 int sgn = (A.i*(B.j-C.j) + B.i*(C.j-A.j) * C.i*(A.j-B.j)) < 0 ? 1 : -1;
00463 return sgn * acos((Sac*Sac+Sab*Sab-Sbc*Sbc)/(2*Sab*Sac));
00464 }
00465
00466
00467 template <class T>
00468 inline bool pnTriangle(const Point2D<T>& A,
00469 const Point2D<T>& B,
00470 const Point2D<T>& C,
00471 const Point2D<T>& P)
00472 {
00473
00474
00475 T ax = C.i - B.i; T ay = C.j - B.j;
00476 T bx = A.i - C.i; T by = A.j - C.j;
00477 T cx = B.i - A.i; T cy = B.j - A.j;
00478 T apx= P.i - A.i; T apy= P.j - A.j;
00479 T bpx= P.i - B.i; T bpy= P.j - B.j;
00480 T cpx= P.i - C.i; T cpy= P.j - C.j;
00481
00482 T aCROSSbp = ax*bpy - ay*bpx;
00483 T cCROSSap = cx*apy - cy*apx;
00484 T bCROSScp = bx*cpy - by*cpx;
00485
00486 return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 #endif