Changeset 987
- Timestamp:
- Mar 2, 2005, 1:22:13 PM (20 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
r970 r987 8 8 9 9 class PointError(exceptions.Exception): pass 10 class FlagError(exceptions.Exception): pass 10 11 11 12 OUTPUT_FILE_TITLE = "# The alpha shape boundary defined by point index pairs of edges" … … 35 36 self._set_points(points) 36 37 self._alpha_shape_algorithm(alpha) 37 38 38 39 39 def _set_points(self, points): … … 70 70 return self.boundary 71 71 72 def set_boundary_type(self,flag=0,small=0.2): 73 """ 74 Use the flag to set constraints on the boundary 75 0 Return raw boundary i.e. the regular edges 76 1 filter to remove small holes 77 2 (includes 1) plus remove sharp indents in boundary 78 3 (includes 2) plus test for pinch-off i.e. boundary vertex with more than two edges. 79 """ 80 reg_edge = self.get_regular_edges(self.alpha) 81 bdry = [self.edge[k] for k in reg_edge] 82 83 if flag>=1 : 72 def set_boundary_type(self,raw_boundary=True, 73 remove_holes=False, 74 smooth_indents=False, 75 expand_pinch=False, 76 boundary_points_fraction=0.2): 77 """ 78 Use the flags to set constraints on the boundary 79 raw_boundary Return raw boundary i.e. the regular edges 80 remove_holes filter to remove small holes 81 smooth_indents remove sharp indents in boundary 82 expand_pinch plus test for pinch-off 83 i.e. boundary vertex with more than two edges. 84 """ 85 86 if raw_boundary: 87 reg_edge = self.get_regular_edges(self.alpha) 88 self.boundary = [self.edge[k] for k in reg_edge] 89 self._init_boundary_triangles() 90 if remove_holes: 84 91 #remove holes 85 bdry = self._remove_holes(bdry,small)86 if flag>=2:92 self.boundary = self._remove_holes(boundary_points_fraction) 93 if smooth_indents: 87 94 #remove sharp indents 88 bdry = self._smooth_indents(bdry)89 if flag>=3:95 self.boundary = self._smooth_indents() 96 if expand_pinch: 90 97 #deal with pinch-off 91 bdry = self._expand_pinch(bdry) 92 93 self.boundary = bdry 98 self.boundary = self._expand_pinch() 94 99 95 100 … … 117 122 reg_edge = self.get_regular_edges(alpha) 118 123 self.boundary = [self.edge[k] for k in reg_edge] 124 self._init_boundary_triangles() 119 125 120 126 … … 178 184 self.boundary = [self.edge[k] for k in reg_edge] 179 185 #print "alpha boundary edges ", self.boundary 186 self._init_boundary_triangles() 180 187 181 # this produces a baaad boundary182 #boundary = []183 #for point_index in range(len(self.points)-1):184 # boundary.append([point_index,point_index +1])185 #boundary.append([len(self.points)-1,0])186 #self.boundary = boundary187 188 return 188 189 … … 250 251 return 251 252 252 def _edge_intervals_array_based(self):253 # THIS DOESN'T WORK YET254 255 # for each edge, find triples256 # (length/2, min_adj_triradius, max_adj_triradius) if unattached257 # (min_adj_triradius, min_adj_triradius, max_adj_triradius) if attached.258 259 edges = []260 edgenbrs = []261 edgeinterval = []262 263 x = self.points[:,0]264 y = self.points[:,1]265 ind0 = [self.deltri[j][0] for j in range(len(self.deltri))]266 ind1 = [self.deltri[j][1] for j in range(len(self.deltri))]267 ind2 = [self.deltri[j][2] for j in range(len(self.deltri))]268 269 x0 = array([ x[j] for j in ind1 ])270 y0 = array([ y[j] for j in ind1 ])271 x1 = array([ x[j] for j in ind2 ])272 y1 = array([ y[j] for j in ind2 ])273 x2 = array([ x[j] for j in ind3 ])274 y2 = array([ y[j] for j in ind3 ])275 276 dx0 = x1-x2277 dx1 = x2-x0278 dx2 = x0-x1279 dy0 = y1-y2280 dy1 = y2-y0281 dy2 = y0-y1282 283 elen0 = sqrt(dx0*dx0 + dy0*dy0)284 elen1 = sqrt(dx1*dx1 + dy1*dy1)285 elen2 = sqrt(dx2*dx2 + dy2*dy2)286 287 anglesgn0 = -dx1*dx2-dy1*dy2288 anglesgn1 = -dx2*dx0-dy2*dy0289 anglesgn2 = -dx0*dx1-dy0*dy1290 291 # not sure how to convert the rest of the algorithm....292 293 for t in range(len(self.deltri)):294 tri = self.deltri[t]295 trinbr = self.deltrinbr[t]296 297 for i in [0,1,2]:298 j = (i+1)%3299 k = (i+2)%3300 if trinbr[i]==-1:301 edges.append((tri[j], tri[k]))302 edgenbrs.append((t, -1))303 edgeinterval.append([0.5*elen[i], self.triradius[t], INF])304 elif (tri[j]<tri[k]):305 edges.append((tri[j], tri[k]))306 edgenbrs.append((t, trinbr[i]))307 edgeinterval.append([0.5*elen[i],\308 min(self.triradius[t],self.triradius[trinbr[i]]),\309 max(self.triradius[t],self.triradius[trinbr[i]]) ])310 else:311 continue312 #if angle[i]>pi/2:313 if anglesign[i] < 0:314 edgeinterval[-1][0] = edgeinterval[-1][1]315 316 self.edge = edges317 self.edgenbr = edgenbrs318 self.edgeinterval = edgeinterval319 #print "edges: ",edges, "\n"320 #print "edge nbrs:", edgenbrs ,"\n"321 #print "edge intervals: ",edgeinterval , "\n"322 253 323 254 … … 449 380 return vertices 450 381 451 452 def _remove_holes(self,bdry,small): 382 def _init_boundary_triangles(self): 383 """ 384 Creates the initial list of triangle indices 385 exterior to and touching the boundary of the alpha shape 386 """ 387 def tri_rad_gta(k): 388 return self.triradius[k]>self.alpha 389 390 extrind = filter(tri_rad_gta, range(len(self.triradius))) 391 392 bv = self._vertices_from_edges(self.boundary) 393 394 btri = [] 395 for et in extrind: 396 v0 = self.deltri[et][0] 397 v1 = self.deltri[et][1] 398 v2 = self.deltri[et][2] 399 if v0 in bv or v1 in bv or v2 in bv: 400 btri.append(et) 401 402 self.boundarytriangle = btri 403 404 #print "exterior triangles: ", extrind 405 406 407 def _remove_holes(self,small): 453 408 """ 454 409 Given the edges in bdry, find the largest exterior components. 455 410 """ 456 411 457 print "running _remove_holes \n" 412 #print "running _remove_holes \n" 413 414 bdry = self.boundary 458 415 459 416 def findroot(i): … … 519 476 vdiscard = [verts[k] for k in littlecomp] 520 477 newbdry = [e for e in bdry if not((e[0] in vdiscard) or (e[1] in vdiscard))] 478 # remove boundary triangles that touch discarded components 479 newbt = [] 480 for bt in self.boundarytriangle: 481 v0 = self.deltri[bt][0] 482 v1 = self.deltri[bt][1] 483 v2 = self.deltri[bt][2] 484 if not (v0 in vdiscard or v1 in vdiscard or v2 in vdiscard): 485 newbt.append(bt) 486 self.boundarytriangle = newbt 521 487 else: 522 488 newbdry = bdry 523 489 524 490 return newbdry 525 491 526 492 527 528 def _smooth_indents(self,bdry): 493 def _smooth_indents(self): 529 494 """ 530 495 Given edges in bdry, test for acute-angle indents and remove them. 531 496 """ 532 533 print "running _smooth_indents \n" 534 535 # first find triangles not in alpha-shape 536 def tri_rad_gta(k): 537 return self.triradius[k]>self.alpha 538 539 extrind = filter(tri_rad_gta, range(len(self.triradius))) 540 #print "exterior triangles: ", extrind 541 542 # find triangles that share two edges with bdry 543 # i.e. triangles that have all verts in bdry. 497 498 #print "running _smooth_indents \n" 499 500 bdry = self.boundary 501 bdrytri = self.boundarytriangle 544 502 verts = self._vertices_from_edges(bdry) 545 546 bdrytri = [] 547 for ind in extrind: 548 bvct = 0 503 504 # find boundary triangles that have two edges in bdry 505 b2etri = [] 506 for ind in bdrytri: 507 bect = 0 549 508 for j in [0,1,2]: 550 if self.deltri[ind][j] in verts:551 bvct +=1552 if bvct==3:553 bdrytri.append(ind)554 555 #print "boundary triangles ", bdrytri509 eda = (self.deltri[ind][(j+1)%3], self.deltri[ind][(j+2)%3]) 510 edb = (self.deltri[ind][(j+2)%3], self.deltri[ind][(j+1)%3]) 511 if eda in bdry or edb in bdry: 512 bect +=1 513 if bect==2: 514 b2etri.append(ind) 556 515 557 516 # test the bdrytri triangles for acute angles 558 probtri = []559 for tind in b drytri:517 acutetri = [] 518 for tind in b2etri: 560 519 tri = self.deltri[tind] 561 520 dx = array([self.points[tri[(i+1)%3],0] - self.points[tri[(i+2)%3],0] for i in [0,1,2]]) … … 563 522 anglesign = array([(-dx[(i+1)%3]*dx[(i+2)%3]-dy[(i+1)%3]*dy[(i+2)%3]) for i in [0,1,2]]) 564 523 if product(anglesign) > 0: 565 probtri.append(tind) 566 567 #print "problem triangles ", probtri 568 569 # adjust the bdry edges of the probtri triangles 570 for pind in probtri: 524 acutetri.append(tind) 525 526 #print "acute boundary triangles ", acutetri 527 528 # adjust the bdry edges and triangles by adding in the acutetri triangles 529 for pind in acutetri: 530 bdrytri.remove(pind) 571 531 tri = self.deltri[pind] 572 #print "triangle verts: ", tri573 532 for i in [0,1,2]: 574 edga = (tri[(i+1)%3], tri[(i+2)%3]) 575 edgb = (tri[(i+2)%3], tri[(i+1)%3]) 576 if edga in bdry: 577 bdry.remove(edga) 578 elif edgb in bdry: 579 bdry.remove(edgb) 580 else: 581 bdry.append(edga) 582 583 return bdry 584 585 def _expand_pinch(self,bdry): 533 bdry.append((tri[(i+1)%3], tri[(i+2)%3])) 534 535 self.boundarytriangle = bdrytri 536 537 newbdry = [] 538 for ed in bdry: 539 numed = bdry.count(ed)+bdry.count((ed[1],ed[0])) 540 if numed%2 == 1: 541 newbdry.append(ed) 542 543 #print "new boundary ", newbdry 544 return newbdry 545 546 def _expand_pinch(self): 586 547 """ 587 548 Given edges in bdry, test for vertices with more than 2 incident edges. 588 549 Expand by adding back in associated triangles... 589 550 """ 590 print "running _expand_pinch \n" 591 592 #verts = self._vertices_from_edges(bdry) 593 551 #print "running _expand_pinch \n" 552 553 bdry = self.boundary 554 bdrytri = self.boundarytriangle 555 594 556 v1 = [bdry[k][0] for k in range(len(bdry))] 595 557 v2 = [bdry[k][1] for k in range(len(bdry))] 596 558 v = v1+v2 597 559 v.sort() 598 probv = [v[k] for k in range(len(v)) if (v[k]!=v[k-1] and v.count(k)>2) ] 599 600 # first find triangles not in alpha-shape 601 def tri_rad_gta(k): 602 return self.triradius[k]>self.alpha 603 604 extrind = filter(tri_rad_gta, range(len(self.triradius))) 605 #print "exterior triangles: ", extrind 606 607 # find exterior triangles that have a vertex in probv 560 probv = [v[k] for k in range(len(v)) if (v[k]!=v[k-1] and v.count(v[k])>2) ] 561 #print "problem vertices: ", probv 562 563 # find boundary triangles that have at least one vertex in probv 608 564 probtri = [] 609 for ind in extrind:610 for j in [0,1,2]:611 if (self.deltri[ind][j] in probv):612 tr = (ind,j)613 if probtri.count(tr)==0:614 probtri.append(tr)615 616 # 565 for ind in bdrytri: 566 v0 = self.deltri[ind][0] 567 v1 = self.deltri[ind][1] 568 v2 = self.deltri[ind][2] 569 if v0 in probv or v1 in probv or v2 in probv: 570 probtri.append(ind) 571 572 #print "problem boundary triangle indices ", probtri 617 573 618 574 # "add in" the problem triangles 619 for t in probtri: 620 tri = self.deltri[t[0]] 621 opeda = ( tri[(t[1]+1)%3], tri[(t[1]+2)%3] ) 622 opedb = ( tri[(t[1]+2)%3], tri[(t[1]+1)%3] ) 623 # oped is the edge opposite the problem vertex 624 # if oped is in bdry remove it and the other triangle edges 625 # otherwise add oped to the bdry and remove the other triangle edges 626 627 if opeda in bdry: 628 bdry.remove(opeda) 629 elif opedb in bdry: 630 bdry.remove(opedb) 631 else: 632 bdry.append(opeda) 633 634 if (tri[t[1]], tri[(t[1]+1)%3]) in bdry: 635 bdry.remove((tri[t[1]], tri[(t[1]+1)%3])) 636 if (tri[(t[1]+1)%3], tri[t[1]]) in bdry: 637 bdry.remove((tri[(t[1]+1)%3], tri[t[1]])) 638 if (tri[t[1]], tri[(t[1]+2)%3]) in bdry: 639 bdry.remove((tri[t[1]], tri[(t[1]+2)%3])) 640 if (tri[(t[1]+2)%3], tri[t[1]]) in bdry: 641 bdry.remove((tri[(t[1]+2)%3], tri[t[1]])) 642 643 return bdry 644 575 for pind in probtri: 576 bdrytri.remove(pind) 577 tri = self.deltri[pind] 578 for i in [0,1,2]: 579 bdry.append((tri[(i+1)%3], tri[(i+2)%3])) 580 581 self.boundarytriangle = bdrytri 582 583 newbdry = [] 584 for ed in bdry: 585 numed = bdry.count(ed)+bdry.count((ed[1],ed[0])) 586 if numed%2 == 1: 587 newbdry.append(ed) 588 589 #print "new boundary ", newbdry 590 return newbdry 591 592 645 593 #------------------------------------------------------------- 646 594 if __name__ == "__main__": -
inundation/ga/storm_surge/alpha_shape/test_alpha_shape.py
r970 r987 107 107 108 108 alpha = Alpha_Shape([a,b,c,cd,d,e,f]) 109 alpha.set_boundary_type( 1)109 alpha.set_boundary_type(0,1,0,0) 110 110 result = alpha.get_boundary() 111 111 #print "result",result 112 112 answer = [(0, 3), (3, 6), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)] 113 113 assert allclose(answer, result) 114 pass114 115 115 116 116 … … 125 125 126 126 alpha = Alpha_Shape([a,b,c,cd,d,e,f]) 127 alpha.set_boundary_type( 2)127 alpha.set_boundary_type(0,0,1,0) 128 128 result = alpha.get_boundary() 129 129 #print "result",result 130 130 answer = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 0)] 131 131 assert allclose(answer, result) 132 pass 132 133 134 def test_boundary_3(self): 135 a = [452.0, -300.0] 136 b = [637.0, -322.0] 137 c = [844.0, -474.0] 138 d = [900.0, -585.0] 139 e = [726.0, -492.0] 140 f = [481.0, -354.0] 141 g = [744.0, -388.0] 142 143 alpha = Alpha_Shape([a,b,c,d,e,f,g]) 144 alpha.set_boundary_type(0,0,0,1) 145 result = alpha.get_boundary() 146 answer = [(1, 0), (0, 5), (3, 2), (4, 3), (2, 6), (6, 1), (5, 4)] 147 assert allclose(answer, result) 148 133 149 134 150
Note: See TracChangeset
for help on using the changeset viewer.