Changeset 987


Ignore:
Timestamp:
Mar 2, 2005, 1:22:13 PM (20 years ago)
Author:
duncan
Message:

vanessa's changes, my changes

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  
    88
    99class PointError(exceptions.Exception): pass
     10class FlagError(exceptions.Exception): pass
    1011
    1112OUTPUT_FILE_TITLE = "# The alpha shape boundary defined by point index pairs of edges"
     
    3536        self._set_points(points)
    3637        self._alpha_shape_algorithm(alpha)
    37            
    3838
    3939    def _set_points(self, points):
     
    7070        return self.boundary
    7171
    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:
    8491            #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:
    8794            #remove sharp indents
    88             bdry = self._smooth_indents(bdry)
    89         if flag>=3:
     95            self.boundary = self._smooth_indents()
     96        if expand_pinch:
    9097            #deal with pinch-off
    91             bdry = self._expand_pinch(bdry)
    92        
    93         self.boundary = bdry
     98            self.boundary = self._expand_pinch()
    9499       
    95100
     
    117122        reg_edge = self.get_regular_edges(alpha)   
    118123        self.boundary = [self.edge[k] for k in reg_edge]
     124        self._init_boundary_triangles()
    119125   
    120126           
     
    178184        self.boundary = [self.edge[k] for k in reg_edge]
    179185        #print "alpha boundary edges ", self.boundary
     186        self._init_boundary_triangles()
    180187           
    181         # this produces a baaad boundary
    182         #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 = boundary
    187188        return
    188189
     
    250251        return
    251252
    252     def _edge_intervals_array_based(self):
    253         # THIS DOESN'T WORK YET
    254 
    255         # for each edge, find triples
    256         # (length/2, min_adj_triradius, max_adj_triradius) if unattached
    257         # (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-x2
    277         dx1 = x2-x0
    278         dx2 = x0-x1
    279         dy0 = y1-y2
    280         dy1 = y2-y0
    281         dy2 = y0-y1
    282 
    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*dy2
    288         anglesgn1 = -dx2*dx0-dy2*dy0
    289         anglesgn2 = -dx0*dx1-dy0*dy1
    290 
    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)%3
    299                 k = (i+2)%3
    300                 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                     continue
    312                 #if angle[i]>pi/2:
    313                 if anglesign[i] < 0:
    314                     edgeinterval[-1][0] = edgeinterval[-1][1]
    315                    
    316         self.edge = edges
    317         self.edgenbr = edgenbrs
    318         self.edgeinterval = edgeinterval
    319         #print "edges: ",edges, "\n"
    320         #print "edge nbrs:", edgenbrs ,"\n"
    321         #print "edge intervals: ",edgeinterval , "\n"
    322253
    323254
     
    449380        return vertices
    450381
    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):
    453408        """
    454409        Given the edges in bdry, find the largest exterior components.
    455410        """
    456411
    457         print "running _remove_holes \n"
     412        #print "running _remove_holes \n"
     413
     414        bdry = self.boundary
    458415       
    459416        def findroot(i):
     
    519476            vdiscard = [verts[k] for k in littlecomp]
    520477            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
    521487        else:
    522488            newbdry = bdry
    523 
     489   
    524490        return newbdry
    525491
    526492
    527 
    528     def _smooth_indents(self,bdry):
     493    def _smooth_indents(self):
    529494        """
    530495        Given edges in bdry, test for acute-angle indents and remove them.
    531496        """
    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
    544502        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
    549508            for j in [0,1,2]:
    550                 if self.deltri[ind][j] in verts:
    551                     bvct +=1
    552             if bvct==3:
    553                 bdrytri.append(ind)
    554 
    555         #print "boundary triangles ", bdrytri
     509                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)
    556515
    557516        # test the bdrytri triangles for acute angles
    558         probtri = []
    559         for tind in bdrytri:
     517        acutetri = []
     518        for tind in b2etri:
    560519            tri = self.deltri[tind]
    561520            dx = array([self.points[tri[(i+1)%3],0] - self.points[tri[(i+2)%3],0] for i in [0,1,2]])
     
    563522            anglesign = array([(-dx[(i+1)%3]*dx[(i+2)%3]-dy[(i+1)%3]*dy[(i+2)%3]) for i in [0,1,2]])
    564523            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)
    571531            tri = self.deltri[pind]
    572             #print "triangle verts: ", tri
    573532            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):
    586547        """
    587548        Given edges in bdry, test for vertices with more than 2 incident edges.
    588549        Expand by adding back in associated triangles...
    589550        """
    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       
    594556        v1 = [bdry[k][0] for k in range(len(bdry))]
    595557        v2 = [bdry[k][1] for k in range(len(bdry))]
    596558        v = v1+v2
    597559        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
    608564        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         # print "problem boundary triangle indices ", probtri
     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
    617573
    618574        # "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
    645593#-------------------------------------------------------------
    646594if __name__ == "__main__":
  • inundation/ga/storm_surge/alpha_shape/test_alpha_shape.py

    r970 r987  
    107107
    108108        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)
    110110        result = alpha.get_boundary()
    111111        #print "result",result
    112112        answer = [(0, 3), (3, 6), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
    113113        assert allclose(answer, result)
    114         pass
     114   
    115115
    116116
     
    125125
    126126        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)
    128128        result = alpha.get_boundary()
    129129        #print "result",result
    130130        answer = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 0)]
    131131        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
    133149
    134150       
Note: See TracChangeset for help on using the changeset viewer.