00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, 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 /** 00036 \brief Test line intersection and point inside polygon 00037 00038 This is a fast and dirty implementation of the point inside 00039 polygon test from Jerome L. Lewis, SIGSCE Bulletin, 34 (2002) 00040 81. 00041 00042 Note that an error in that article ("count-" should have been 00043 "count--") has been corrected here. 00044 00045 \future The inside() functions actually copy the points twice. 00046 This can be made more efficient. 00047 00048 \comment 00049 See also 00050 http://www.ecse.rpi.edu/Homepages/wrf/Research/ 00051 Short_Notes/pnpoly.html#Polyhedron 00052 which suggests the following code 00053 int pnpoly(int nvert, float *vertx, float *verty, float testx, 00054 float testy) { 00055 int i, j, c = 0; 00056 for (i = 0, j = nvert-1; i < nvert; j = i++) { 00057 if ( ((verty[i]>testy) != (verty[j]>testy)) && 00058 (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / 00059 (verty[j]-verty[i]) + vertx[i]) ) 00060 c = !c; 00061 } 00062 return c; 00063 } 00064 \endcomment 00065 00066 */ 00067 class pinside { 00068 00069 protected: 00070 00071 /// Internal point definition for \ref pinside 00072 struct point { 00073 double x; 00074 double y; 00075 }; 00076 00077 /// Internal line definition for \ref pinside 00078 struct line { 00079 point p1; 00080 point p2; 00081 }; 00082 00083 /// Test if line segments \c P and \c Q intersect 00084 int intersect(line P, line Q); 00085 00086 /// Test if point \c t is inside polygon \c p of size \c N 00087 int inside(point t, point p[], int N); 00088 00089 public: 00090 00091 /** 00092 \brief Determine if two line segments intersect 00093 00094 The function returns 1 if the line segment 00095 determined by the endpoints \f$ (x_1,y_1) \f$ 00096 and \f$ (x_2,y_2) \f$ and the line segment 00097 determined by the endpoints \f$ (x_3,y_3) \f$ 00098 and \f$ (x_4,y_4) \f$ intersect, and 0 otherwise. 00099 */ 00100 int intersect(double x1, double y1, double x2, double y2, 00101 double x3, double y3, double x4, double y4) { 00102 line P={{x1,y1},{x2,y2}}; 00103 line Q={{x3,y3},{x4,y4}}; 00104 return intersect(P,Q); 00105 } 00106 00107 /** 00108 \brief Determine if point (x,y) is inside a polygon 00109 00110 This returns 1 if the point (x,y) is inside the polygon 00111 defined by \c xa and \c ya, and 0 otherwise. 00112 00113 Note that if the point (x,y) is exactly on the polygon, 00114 then the result of this function is not well-defined 00115 and it will return either 0 or 1. 00116 */ 00117 int inside(double x, double y, const o2scl::ovector_base &xa, 00118 const o2scl::ovector_base &ya); 00119 00120 /** 00121 \brief Determine if point (x,y) is inside a polygon 00122 00123 This returns 1 if the point (x,y) is inside the polygon 00124 defined by \c xa and \c ya, and 0 otherwise. 00125 00126 The parameter \c n should be the number of polygon points 00127 specified in vectors \c xa and \c ya. 00128 00129 Note that if the point (x,y) is exactly on the polygon, 00130 then the result of this function is not well-defined 00131 and it will return either 0 or 1. 00132 */ 00133 template<class vec_t> 00134 int inside(double x, double y, size_t n, const vec_t &xa, 00135 const vec_t &ya) { 00136 00137 size_t ix; 00138 point t, *p=new point[n+1]; 00139 t.x=x; 00140 t.y=y; 00141 00142 // We have to copy the vectors so we can rearrange them because 00143 // they are const 00144 o2scl::ovector xb(n), yb(n); 00145 vector_copy(n,xa,xb); 00146 vector_copy(n,ya,yb); 00147 00148 // Ensure that (yb[0],ya[0]) is the point with the smallest x 00149 // coordinate among all the points with the smallest y coordinate 00150 double xmin=xb[0]; 00151 double ymin=yb[0]; 00152 ix=0; 00153 for(size_t i=0;i<n;i++) { 00154 if (yb[i]<ymin) { 00155 ymin=yb[i]; 00156 ix=i; 00157 } 00158 } 00159 for(size_t i=0;i<n;i++) { 00160 if (yb[i]==ymin && xb[i]<xmin) { 00161 xmin=xb[i]; 00162 ix=i; 00163 } 00164 } 00165 vector_rotate<double,vec_t>(n,xb,ix); 00166 vector_rotate<double,vec_t>(n,yb,ix); 00167 00168 // Copy to p[] 00169 for(size_t i=0;i<n;i++) { 00170 p[i+1].x=xb[i]; 00171 p[i+1].y=yb[i]; 00172 } 00173 00174 int ret=inside(t,p,n); 00175 delete[] p; 00176 00177 return ret; 00178 } 00179 00180 /// Perform some simple testing 00181 int test(test_mgr &t); 00182 00183 }; 00184 00185 #ifndef DOXYGENP 00186 } 00187 #endif 00188 00189 #endif
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page