Changeset 999 for inundation/ga/storm_surge/pyvolution
- Timestamp:
- Mar 4, 2005, 12:20:11 PM (20 years ago)
- Location:
- inundation/ga/storm_surge/pyvolution
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/ga/storm_surge/pyvolution/test_util.py
r998 r999 826 826 polygon = [[0,0], [1,0], [1,1], [0,1]] 827 827 828 829 R = inside_polygon( (0.5, 0.5), polygon)830 print 'Inside = ', R831 print832 833 R = inside_polygon( (0.5, 0.5), polygon)834 print 'Inside = ', R835 print836 837 import sys; sys.exit()838 828 assert inside_polygon( (0.5, 0.5), polygon ) 839 829 assert not inside_polygon( (0.5, 1.5), polygon ) … … 953 943 #------------------------------------------------------------- 954 944 if __name__ == "__main__": 955 suite = unittest.makeSuite(TestCase,'test_inside_polygon_main') 945 #suite = unittest.makeSuite(TestCase,'test_inside_polygon_main') 946 suite = unittest.makeSuite(TestCase,'test') 956 947 runner = unittest.TextTestRunner() 957 948 runner.run(suite) -
inundation/ga/storm_surge/pyvolution/util.py
r997 r999 87 87 88 88 #FIXME (OLE): Should check origin of domain against that of file 89 89 #In fact, this is where origin should be converted to that of domain 90 #Also, check that file covers domain fully. 90 91 91 92 assert type(filename) == type(''),\ … … 974 975 py = polygon[:,1] 975 976 976 #Used for an optimisation when points are far away from pol gon977 #Used for an optimisation when points are far away from polygon 977 978 minpx = min(px); maxpx = max(px) 978 979 minpy = min(py); maxpy = max(py) … … 1022 1023 1023 1024 1025 1026 def inside_polygon_c(point, polygon, closed = True, verbose = False): 1027 """Determine whether points are inside or outside a polygon 1028 1029 C-wrapper 1030 """ 1031 1032 from Numeric import array, Float, reshape, zeros, Int 1033 1034 1035 #Input checks 1036 try: 1037 point = array(point).astype(Float) 1038 except: 1039 msg = 'Point %s could not be converted to Numeric array' %point 1040 raise msg 1041 1042 try: 1043 polygon = array(polygon).astype(Float) 1044 except: 1045 msg = 'Polygon %s could not be converted to Numeric array' %polygon 1046 raise msg 1047 1048 assert len(polygon.shape) == 2,\ 1049 'Polygon array must be a 2d array of vertices: %s' %polygon 1050 1051 1052 assert polygon.shape[1] == 2,\ 1053 'Polygon array must have two columns: %s' %polygon 1054 1055 1056 if len(point.shape) == 1: 1057 one_point = True 1058 points = reshape(point, (1,2)) 1059 else: 1060 one_point = False 1061 points = point 1062 1063 from util_ext import inside_polygon 1064 1065 indices = zeros( points.shape[0], Int ) 1066 1067 count = inside_polygon(points, polygon, indices, 1068 int(closed), int(verbose)) 1069 1070 #print 'O', point, count 1071 1072 if one_point: 1073 return count == 1 1074 else: 1075 return indices[:count] 1076 1024 1077 class Polygon_function: 1025 1078 """Create callable object f: x,y -> z, where a,y,z are vectors and … … 1134 1187 Examples: 1135 1188 populate_polygon( [[0,0], [1,0], [1,1], [0,1]], 5 ) 1136 will return five randomly s leected points inside the unit square1189 will return five randomly selected points inside the unit square 1137 1190 """ 1138 1191 … … 1183 1236 1184 1237 1185 1186 1187 1238 ############################################## 1188 1239 #Initialise module … … 1190 1241 import compile 1191 1242 if compile.can_use_C_extension('util_ext.c'): 1192 from util_ext import gradient, point_on_line 1243 from util_ext import gradient, point_on_line 1244 inside_polygon = inside_polygon_c 1193 1245 else: 1194 1246 gradient = gradient_python -
inundation/ga/storm_surge/pyvolution/util_ext.c
r671 r999 59 59 60 60 61 int _inside_polygon(int M, // Number of points 62 int N, // Number of polygon vertices 63 double* points, 64 double* polygon, 65 int* indices, // M-Array for storage indices 66 int closed, 67 int verbose) { 68 69 double minpx, maxpx, minpy, maxpy, x, y, px_i, py_i, px_j, py_j; 70 int i, j, k, count, inside; 71 72 //Find min and max of poly used for optimisation when points 73 //are far away from polygon 74 75 76 minpx = polygon[0]; maxpx = minpx; 77 minpy = polygon[1]; maxpy = minpy; 78 79 for (i=0; i<N; i++) { 80 px_i = polygon[2*i]; 81 py_i = polygon[2*i + 1]; 82 83 if (px_i < minpx) minpx = px_i; 84 if (px_i > maxpx) maxpx = px_i; 85 if (py_i < minpy) minpy = py_i; 86 if (py_i > maxpy) maxpy = py_i; 87 } 88 89 //Begin main loop (for each point) 90 count = 0; 91 for (k=0; k<M; k++) { 92 //FIXME: Do this later 93 //if (verbose){ 94 // if (k %((M+10)/10)==0: print 'Doing %d of %d' %(k, M) 95 96 x = points[2*k]; 97 y = points[2*k + 1]; 98 99 inside = 0; 100 101 //Optimisation 102 if ((x > maxpx) || (x < minpx)) continue; 103 if ((y > maxpy) || (y < minpy)) continue; 104 105 //Check polygon 106 for (i=0; i<N; i++) { 107 //printf("k,i=%d,%d\n", k, i); 108 j = (i+1)%N; 109 110 px_i = polygon[2*i]; 111 py_i = polygon[2*i+1]; 112 px_j = polygon[2*j]; 113 py_j = polygon[2*j+1]; 114 115 //Check for case where point is contained in line segment 116 if (_point_on_line(x, y, px_i, py_i, px_j, py_j)) { 117 if (closed == 1) { 118 inside = 1; 119 } else { 120 inside = 0; 121 } 122 break; 123 } else { 124 //Check if truly inside polygon 125 if ( ((py_i < y) && (py_j >= y)) || 126 ((py_j < y) && (py_i >= y)) ) { 127 if (px_i + (y-py_i)/(py_j-py_i)*(px_j-px_i) < x) 128 inside = 1-inside; 129 } 130 } 131 } 132 if (inside == 1) { 133 indices[count] = k; 134 count++; 135 } 136 } // End k 137 138 return count; 139 } 140 141 142 61 143 // Gateways to Python 62 144 PyObject *point_on_line(PyObject *self, PyObject *args) { … … 81 163 return result; 82 164 } 165 166 167 168 PyObject *inside_polygon(PyObject *self, PyObject *args) { 169 //def inside_polygon(point, polygon, closed, verbose, one_point): 170 // """Determine whether points are inside or outside a polygon 171 // 172 // Input: 173 // point - Tuple of (x, y) coordinates, or list of tuples 174 // polygon - list of vertices of polygon 175 // one_poin - If True Boolean value should be returned 176 // If False, indices of points inside returned 177 // closed - (optional) determine whether points on boundary should be 178 // regarded as belonging to the polygon (closed = True) 179 // or not (closed = False) 180 181 // 182 // Output: 183 // If one point is considered, True or False is returned. 184 // If multiple points are passed in, the function returns indices 185 // of those points that fall inside the polygon 186 // 187 // Examples: 188 // inside_polygon( [0.5, 0.5], [[0,0], [1,0], [1,1], [0,1]] ) 189 // will evaluate to True as the point 0.5, 0.5 is inside the unit square 190 // 191 // inside_polygon( [[0.5, 0.5], [1, -0.5], [0.3, 0.2]] ) 192 // will return the indices [0, 2] as only the first and the last point 193 // is inside the unit square 194 // 195 // Remarks: 196 // The vertices may be listed clockwise or counterclockwise and 197 // the first point may optionally be repeated. 198 // Polygons do not need to be convex. 199 // Polygons can have holes in them and points inside a hole is 200 // regarded as being outside the polygon. 201 // 202 // 203 // Algorithm is based on work by Darel Finley, 204 // http://www.alienryderflex.com/polygon/ 205 // 206 // 207 208 PyArrayObject 209 *point, 210 *polygon, 211 *indices; 212 213 int closed, verbose; //Flags 214 int count, M, N; 215 216 // Convert Python arguments to C 217 if (!PyArg_ParseTuple(args, "OOOii", 218 &point, 219 &polygon, 220 &indices, 221 &closed, 222 &verbose)) 223 return NULL; 224 225 M = point -> dimensions[0]; //Number of points 226 N = polygon -> dimensions[0]; //Number of vertices in polygon 227 228 //printf("M=%d, N=%d\n", M, N); 229 // Call underlying routine 230 count = _inside_polygon(M, N, 231 (double*) point -> data, 232 (double*) polygon -> data, 233 (int*) indices -> data, 234 closed, verbose); 235 236 //NOTE: return number of points inside.. 237 //printf("COunt=%d\n", count); 238 return Py_BuildValue("i", count); 239 } 240 83 241 84 242 … … 117 275 {"gradient", gradient, METH_VARARGS, "Print out"}, 118 276 {"point_on_line", point_on_line, METH_VARARGS, "Print out"}, 277 {"inside_polygon", inside_polygon, METH_VARARGS, "Print out"}, 119 278 {NULL, NULL, 0, NULL} /* sentinel */ 120 279 };
Note: See TracChangeset
for help on using the changeset viewer.