Point2D.H

Go to the documentation of this file.
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
Generated on Sun May 8 08:40:56 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3