00001 /*!@file Image/Point2D.H A basic 2D point class */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/Point2D.H $ 00035 // $Id: Point2D.H 14734 2011-04-14 18:59:24Z lior $ 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> // for string conversions 00046 #include <vector> 00047 00048 //! This is a basic class to encode 2D integer coordinates 00049 /*! This is a completely public class whose goal is just to provide a 00050 shorthand notation for 2D integer coordinates. 00051 */ 00052 template <class T> 00053 class Point2D 00054 { 00055 public: 00056 //! The default constructor initializes the coordinates to (0,0) 00057 inline Point2D(); 00058 00059 //! Initialize the Point2D from horizontal & vertical coordinates 00060 inline Point2D(const T ii, const T jj); 00061 00062 //! Initialize from a Dims object; i=w, j=h 00063 explicit inline Point2D(const Dims& d); 00064 00065 //! Explicit conversion from type T to another type U 00066 /*! Note that this simply uses clamped_convert, so it will clamp 00067 coordinates to the available range of T, and may round down. */ 00068 template <class U> 00069 explicit inline Point2D(const Point2D<U>& a); 00070 00071 //! += operator 00072 inline Point2D<T>& operator+=(const Point2D<T> &p); 00073 //! -= operator 00074 inline Point2D<T>& operator-=(const Point2D<T> &p); 00075 //! *= operator 00076 inline Point2D<T>& operator*=(const Point2D<T> &p); 00077 //! /= operator 00078 inline Point2D<T>& operator/=(const Point2D<T> &p); 00079 00080 //! + operator 00081 template <class U> 00082 inline Point2D<typename promote_trait<T,U>::TP> 00083 operator+(const Point2D<U> &p) const; 00084 //! - operator 00085 template <class U> 00086 inline Point2D<typename promote_trait<T,U>::TP> 00087 operator-(const Point2D<U> &p) const; 00088 //! * operator 00089 template <class U> 00090 inline Point2D<typename promote_trait<T,U>::TP> 00091 operator*(const Point2D<U> &p) const; 00092 //! / operator 00093 template <class U> 00094 inline Point2D<typename promote_trait<T,U>::TP> 00095 operator/(const Point2D<U> &p) const; 00096 00097 //! += operator 00098 inline Point2D<T>& operator+=(const T val); 00099 //! -= operator 00100 inline Point2D<T>& operator-=(const T val); 00101 //! *= operator 00102 inline Point2D<T>& operator*=(const T val); 00103 //! /= operator 00104 inline Point2D<T>& operator/=(const T val); 00105 00106 //! + operator 00107 template <class U> 00108 inline Point2D<typename promote_trait<T,U>::TP> operator+(const U val) const; 00109 00110 //! - operator 00111 template <class U> 00112 inline Point2D<typename promote_trait<T,U>::TP> operator-(const U val) const; 00113 00114 //! * operator 00115 template <class U> 00116 inline Point2D<typename promote_trait<T,U>::TP> operator*(const U val) const; 00117 00118 //! / operator 00119 template <class U> 00120 inline Point2D<typename promote_trait<T,U>::TP> operator/(const U val) const; 00121 00122 //! test whether i and j are both positive 00123 inline bool isValid() const; 00124 00125 //! the square of the euclidean distance 00126 inline typename promote_trait<T,float>::TP 00127 squdist(const Point2D<T>& p) const; 00128 00129 //! the euclidean distance from p 00130 inline typename promote_trait<T,float>::TP 00131 distance(const Point2D<T>& p) const; 00132 00133 //! the Magnitude 00134 inline typename promote_trait<T,float>::TP 00135 magnitude() const; 00136 00137 //! the euclidean distance from line pq 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 //! the euclidean distance from segment pq 00143 inline typename promote_trait<T,float>::TP 00144 distanceToSegment(const Point2D<T>& p, const Point2D<T>& q) const; 00145 00146 //! clamp the coords such that the point fits into image of dimensions dims 00147 inline void clampToDims(const Dims& dims); 00148 00149 //! 2D coordinates 00150 T i, j; 00151 }; 00152 00153 00154 //! == operator 00155 template <class T, class U> 00156 inline bool operator==(const Point2D<T>& p1, const Point2D<U>& p2); 00157 00158 //! != operator 00159 template <class T, class U> 00160 inline bool operator!=(const Point2D<T>& p1, const Point2D<U>& p2); 00161 00162 //! > operator 00163 template <class T, class U> 00164 inline bool operator>(const Point2D<T>& p1, const Point2D<U>& p2); 00165 00166 //! < operator 00167 template <class T, class U> 00168 inline bool operator<(const Point2D<T>& p1, const Point2D<U>& p2); 00169 00170 00171 //! Point2D<T> overload: format is "<i>,<j>" 00172 template <class T> 00173 std::string convertToString(const Point2D<T>& val); 00174 00175 //! Point2D<T> overload: format is "<i>,<j>" 00176 template <class T> 00177 void convertFromString(const std::string& str, Point2D<T>& val); 00178 00179 //! Is a point inside a polygon? 00180 template <class T> 00181 inline bool pnpoly(const std::vector<Point2D<T> > &polygon, 00182 const Point2D<T>& p); 00183 00184 //! Where is the center of mass of a polygon? 00185 template <class T> 00186 inline Point2D<T> centroid(const std::vector<Point2D<T> > &polygon); 00187 00188 //! What is the area of a polygon? 00189 template <class T> 00190 inline double area(const std::vector<Point2D<T> > &polygon, 00191 const bool getsigned = false); 00192 00193 //! What is the measure (in radians, signed -pi to pi) of angle BAC? 00194 template <class T> 00195 inline double angleMeasure(const Point2D<T> & A, 00196 const Point2D<T> & B, 00197 const Point2D<T> & C); 00198 00199 //! determine if a point P is inside a triangle with vertices A,B,C 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 // standard geometry 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 // test if point is "past" segment 00391 Point2D<T> V0 = q-p, V1 = (*this)-q, V2 = (*this)-p; //vectors 00392 if (V0.i*V1.i + V0.j*V1.j>0) return distance(q); // is "past" q 00393 if (V0.i*V2.i + V0.j*V2.j<0) return distance(p); // is "past" 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 // Original algo by Randolph Franklin, 00410 // http://astronomy.swin.edu.au/~pbourke/geometry/insidepoly/ 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 /* So things look consistent in everyone's emacs... */ 00494 /* Local Variables: */ 00495 /* indent-tabs-mode: nil */ 00496 /* End: */ 00497 00498 #endif