Changeset 1420
- Timestamp:
- May 18, 2005, 2:02:07 PM (19 years ago)
- Location:
- inundation/ga/storm_surge/alpha_shape
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
inundation/ga/storm_surge/alpha_shape/alpha_shape.py
r1381 r1420 1 """Alpha shape 1 """Alpha shape 2 Determine the shape of a set of points. 3 4 As mentionned in Edelsbrunner's and Mucke's paper, one can 5 intuitively think of an alpha-shape as the following: 6 test 7 Imagine a huge mass of ice-cream making up the space and containing 8 the points S as ``hard'' chocolate pieces. Using one of these 9 sphere-formed ice-cream spoons we carve out all parts of the ice-cream 10 block we can reach without bumping into chocolate pieces, thereby even 11 carving out holes in the inside (eg. parts not reachable by simply 12 moving the spoon from the outside). We will eventually end up with a 13 (not necessarily convex) object bounded by caps, arcs and points. If 14 we now straighten all ``round'' faces to triangles and line segments, 15 we have an intuitive description of what is called the alpha-shape. 2 16 """ 3 17 … … 14 28 15 29 def alpha_shape_via_files(point_file, boundary_file, alpha= None): 16 30 """ 31 Load a point file and return the alpha shape boundary as a boundary file. 32 33 Inputs: 34 point_file: File location of the input file, points format (.xya or .pts) 35 boundary_file: File location of the generated output file 36 alpha: The alpha value can be optionally specified. If it is not specified 37 the optimum alpha value will be used. 38 """ 17 39 point_dict = import_points_file(point_file) 18 40 points = point_dict['pointlist'] 19 #title_string = point_dict['title']20 41 21 42 alpha = Alpha_Shape(points) … … 25 46 26 47 def __init__(self, points, alpha = None): 27 28 """ 29 Inputs: 30 48 """ 49 alpha_shape inputs a set of points and can return the alpha 50 shape boundary. 51 52 Inputs: 31 53 points: List of coordinate pairs [[x1, y1],[x2, y2]..] 32 33 alpha: alpha shape parameter 34 54 alpha: The alpha value can be optionally specified. If it is 55 not specified the optimum alpha value will be used. 35 56 """ 36 57 self._set_points(points) 37 self._alpha_shape_algorithm(alpha )58 self._alpha_shape_algorithm(alpha=alpha) 38 59 39 60 def _set_points(self, points): 40 61 """ 62 Create self.points array, do Error checking 63 Inputs: 64 points: List of coordinate pairs [[x1, y1],[x2, y2]..] 41 65 """ 42 66 # print "setting points" … … 67 91 def get_boundary(self): 68 92 """ 93 Return a list of tuples. Each tuples represents a segment, 94 by giving the index of the segments two end points. 95 The list of tuple represents the alpha shape. 69 96 """ 70 97 return self.boundary … … 76 103 boundary_points_fraction=0.2): 77 104 """ 78 Use the flags to set constraints on the boundary 105 Use the flags to set constraints on the boundary: 79 106 raw_boundary Return raw boundary i.e. the regular edges 80 107 remove_holes filter to remove small holes … … 111 138 def get_alpha(self): 112 139 """ 113 Return current alpha value 140 Return current alpha value. 114 141 """ 115 142 return self.alpha … … 125 152 126 153 127 def _alpha_shape_algorithm(self,alpha): 128 129 # A python style guide suggests using _[function name] to 130 # specify internal functions 131 # - this is the first time I've used it though - DSG 154 def _alpha_shape_algorithm(self, alpha=None): 155 """ 156 Given a set of points (self.points) and an optional alpha value 157 determines the alpha shape (stored in self.boundary, 158 accessed by get_boundary). 159 160 Inputs: 161 alpha: The alpha value can be optionally specified. If it is 162 not specified the optimum alpha value will be used. 163 """ 132 164 133 165 #print "starting alpha shape algorithm" … … 189 221 190 222 def _tri_circumradius(self): 191 192 # compute circumradii of the delaunay triangles 223 """ 224 Compute circumradii of the delaunay triangles 225 """ 226 193 227 x = self.points[:,0] 194 228 y = self.points[:,1] … … 244 278 except ZeroDivisionError: 245 279 print "There are serious problems with the delaunay triangles" 246 raise 280 raise #DSG maybe don't catch this error? Is recovery possible? 247 281 248 282 249 283 self.triradius = 0.5*sqrt(dx*dx + dy*dy) 250 284 #print "triangle radii", self.triradius 251 return285 252 286 253 287 254 288 255 289 def _edge_intervals(self): 256 # for each edge, find triples 257 # (length/2, min_adj_triradius, max_adj_triradius) if unattached 258 # (min_adj_triradius, min_adj_triradius, max_adj_triradius) if attached. 259 260 # It should be possible to rewrite this routine in an array-friendly form 261 # like _tri_circumradius() if we need to speed things up. 290 """ 291 for each edge, find triples 292 (length/2, min_adj_triradius, max_adj_triradius) if unattached 293 (min_adj_triradius, min_adj_triradius, max_adj_triradius) if attached. 294 """ 295 296 # It should be possible to rewrite this routine in an array-friendly 297 # form like _tri_circumradius() if we need to speed things up. 262 298 263 299 edges = [] … … 267 303 tri = self.deltri[t] 268 304 trinbr = self.deltrinbr[t] 269 dx = array([self.points[tri[(i+1)%3],0] - self.points[tri[(i+2)%3],0] for i in [0,1,2]]) 270 dy = array([self.points[tri[(i+1)%3],1] - self.points[tri[(i+2)%3],1] for i in [0,1,2]]) 305 dx = array([self.points[tri[(i+1)%3],0] - 306 self.points[tri[(i+2)%3],0] for i in [0,1,2]]) 307 dy = array([self.points[tri[(i+1)%3],1] - 308 self.points[tri[(i+2)%3],1] for i in [0,1,2]]) 271 309 elen = sqrt(dx*dx+dy*dy) 272 310 #angle = array([(-dx[(i+1)%3]*dx[(i+2)%3]-dy[(i+1)%3]*dy[(i+2)%3])/(elen[(i+1)%3]*elen[(i+2)%3]) for i in [0,1,2]]) 273 311 #angle = arccos(angle) 274 312 # really only need sign - not angle value: 275 anglesign = array([(-dx[(i+1)%3]*dx[(i+2)%3]-dy[(i+1)%3]*dy[(i+2)%3]) for i in [0,1,2]]) 313 anglesign = array([(-dx[(i+1)%3]*dx[(i+2)%3]- 314 dy[(i+1)%3]*dy[(i+2)%3]) for i in [0,1,2]]) 276 315 277 316 #print "dx ",dx,"\n" … … 291 330 edgenbrs.append((t, trinbr[i])) 292 331 edgeinterval.append([0.5*elen[i],\ 293 294 332 min(self.triradius[t],self.triradius[trinbr[i]]),\ 333 max(self.triradius[t],self.triradius[trinbr[i]]) ]) 295 334 else: 296 335 continue … … 307 346 308 347 def _vertex_intervals(self): 309 # for each vertex find pairs 310 # (min_adj_triradius, max_adj_triradius) 348 """ 349 for each vertex find pairs 350 (min_adj_triradius, max_adj_triradius) 351 """ 311 352 nv = len(self.points) 312 353 vertexnbrs = [ [] for i in range(nv)] … … 331 372 # print "nbr radii: ",radii 332 373 # vertexinterval[i] = [0,INF] 374 375 #DSG is it ok to catch this error and continue? 333 376 pass 334 377 … … 354 397 """ 355 398 def reg_edge(k): 356 return self.edgeinterval[k][1]<=alpha and self.edgeinterval[k][2]>alpha 399 return self.edgeinterval[k][1]<=alpha and \ 400 self.edgeinterval[k][2]>alpha 357 401 358 402 return filter(reg_edge, range(len(self.edgeinterval))) … … 364 408 """ 365 409 def exp_vert(k): 366 return self.vertexinterval[k][0]<=alpha and self.vertexinterval[k][1]>alpha 410 return self.vertexinterval[k][0]<=alpha and \ 411 self.vertexinterval[k][1]>alpha 367 412 368 413 return filter(exp_vert, range(len(self.vertexinterval))) … … 562 607 # an acute angle spanned by two edges along the boundary.. 563 608 # MUST FIX. 609 #DSG - should this be fixed? 564 610 if anglesign[tind[1]] > 0: 565 611 acutetri.append(tind[0]) … … 646 692 import os, sys 647 693 usage = "usage: %s point_file.xya boundary_file.bnd [alpha]"%os.path.basename(sys.argv[0]) 648 # I made up the .bnd affix. Other ideas welcome. -DSG649 694 if len(sys.argv) < 3: 650 695 print usage -
inundation/ga/storm_surge/alpha_shape/test_alpha_shape.py
r1364 r1420 346 346 (126.437678428,28.0083464873), \ 347 347 (133.639824668,50.0149044415), \ 348 (176.852702105,43.612996673), \ alpha = Alpha_Shape(348 (176.852702105,43.612996673), \ 349 349 (123.636843779,-24.4072733675), \ 350 350 (73.6219393379,35.2104927268), \
Note: See TracChangeset
for help on using the changeset viewer.