![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
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
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).