Object-oriented Scientific Computing Library: Version 0.910
pinside.h
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_PINSIDE_H
00024 #define O2SCL_PINSIDE_H
00025 
00026 #include <o2scl/ovector_tlate.h>
00027 #include <o2scl/array.h>
00028 #include <o2scl/test_mgr.h>
00029 #include <o2scl/vec_arith.h>
00030 
00031 #ifndef DOXYGENP
00032 namespace o2scl {
00033 #endif
00034 
00035   /** \brief Test line intersection and point inside polygon
00036 
00037       This is a fast and dirty implementation of the point inside
00038       polygon test from Jerome L. Lewis, SIGSCE Bulletin, 34 (2002)
00039       81.
00040 
00041       Note that an error in that article ("count-" should have been
00042       "count--") has been corrected here. 
00043 
00044       \future The inside() functions actually copy the points twice.
00045       This can be made more efficient.
00046 
00047       \comment
00048       See also
00049       http://www.ecse.rpi.edu/Homepages/wrf/Research/
00050       Short_Notes/pnpoly.html#Polyhedron
00051       which suggests the following code
00052       int pnpoly(int nvert, float *vertx, float *verty, float testx, 
00053       float testy) {
00054       int i, j, c = 0;
00055       for (i = 0, j = nvert-1; i < nvert; j = i++) {
00056       if ( ((verty[i]>testy) != (verty[j]>testy)) &&
00057       (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / 
00058       (verty[j]-verty[i]) + vertx[i]) )
00059       c = !c;
00060       }
00061       return c;
00062       }
00063       \endcomment
00064 
00065   */
00066   class pinside {
00067 
00068   protected:
00069   
00070     /// Internal point definition for \ref pinside
00071     struct point {
00072       double x;
00073       double y;
00074     };
00075   
00076     /// Internal line definition for \ref pinside
00077     struct line {
00078       point p1;
00079       point p2;
00080     };
00081   
00082     /// Test if line segments \c P and \c Q intersect
00083     int intersect(line P, line Q);
00084   
00085     /// Test if point \c t is inside polygon \c p of size \c N
00086     int inside(point t, point p[], int N);
00087   
00088   public:
00089 
00090     /** \brief Determine if two line segments intersect
00091 
00092         The function returns 1 if the line segment
00093         determined by the endpoints \f$ (x_1,y_1) \f$ 
00094         and \f$ (x_2,y_2) \f$ and the line segment 
00095         determined by the endpoints \f$ (x_3,y_3) \f$ 
00096         and \f$ (x_4,y_4) \f$ intersect, and 0 otherwise.
00097     */
00098     int intersect(double x1, double y1, double x2, double y2, 
00099                   double x3, double y3, double x4, double y4) {
00100       line P={{x1,y1},{x2,y2}};
00101       line Q={{x3,y3},{x4,y4}};
00102       return intersect(P,Q);
00103     }
00104 
00105     /** \brief Determine if point (x,y) is inside a polygon
00106 
00107         This returns 1 if the point (x,y) is inside the polygon
00108         defined by \c xa and \c ya, and 0 otherwise. 
00109 
00110         Note that if the point (x,y) is exactly on the polygon,
00111         then the result of this function is not well-defined
00112         and it will return either 0 or 1. 
00113     */
00114     int inside(double x, double y, const o2scl::ovector_base &xa,
00115                const o2scl::ovector_base &ya);
00116   
00117     /** \brief Determine if point (x,y) is inside a polygon
00118 
00119         This returns 1 if the point (x,y) is inside the polygon
00120         defined by \c xa and \c ya, and 0 otherwise. 
00121 
00122         The parameter \c n should be the number of polygon points
00123         specified in vectors \c xa and \c ya.
00124 
00125         Note that if the point (x,y) is exactly on the polygon,
00126         then the result of this function is not well-defined
00127         and it will return either 0 or 1.
00128     */
00129     template<class vec_t>
00130       int inside(double x, double y, size_t n, const vec_t &xa, 
00131                  const vec_t &ya) {
00132       
00133       size_t ix;
00134       point t, *p=new point[n+1];
00135       t.x=x;
00136       t.y=y;
00137 
00138       // We have to copy the vectors so we can rearrange them because
00139       // they are const
00140       o2scl::ovector xb(n), yb(n);
00141       vector_copy(n,xa,xb);
00142       vector_copy(n,ya,yb);
00143 
00144       // Ensure that (yb[0],ya[0]) is the point with the smallest x
00145       // coordinate among all the points with the smallest y coordinate
00146       double xmin=xb[0];
00147       double ymin=yb[0];
00148       ix=0;
00149       for(size_t i=0;i<n;i++) {
00150         if (yb[i]<ymin) {
00151           ymin=yb[i];
00152           ix=i;
00153         }
00154       }
00155       for(size_t i=0;i<n;i++) {
00156         if (yb[i]==ymin && xb[i]<xmin) {
00157           xmin=xb[i];
00158           ix=i;
00159         }
00160       }
00161       vector_rotate<vec_t,double>(n,xb,ix);
00162       vector_rotate<vec_t,double>(n,yb,ix);
00163 
00164       // Copy to p[]
00165       for(size_t i=0;i<n;i++) {
00166         p[i+1].x=xb[i];
00167         p[i+1].y=yb[i];
00168       }
00169     
00170       int ret=inside(t,p,n);
00171       delete[] p;
00172 
00173       return ret;
00174     }
00175 
00176     /// Perform some simple testing
00177     int test(test_mgr &t);
00178 
00179   };
00180 
00181 #ifndef DOXYGENP
00182 }
00183 #endif
00184 
00185 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.