Changeset 655


Ignore:
Timestamp:
Dec 2, 2004, 10:58:26 AM (19 years ago)
Author:
ole
Message:

Added inside_polynomial and point_on_line with tests

Location:
inundation/ga/storm_surge/pyvolution
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • inundation/ga/storm_surge/pyvolution/mesh.py

    r648 r655  
    130130        self.build_tagged_elements_dictionary(tagged_elements)
    131131       
    132         #Update boundary indices
     132        #Update boundary indices FIXME: OBSOLETE
    133133        #self.build_boundary_structure()       
    134134
     
    313313        """
    314314
    315         #FIXME: Maybe obsolete
     315        #FIXME: Now Obsolete - maybe use some comments from here in
     316        #domain.set_boundary
    316317
    317318        if self.boundary is None:
  • inundation/ga/storm_surge/pyvolution/test_util.py

    r629 r655  
    332332        assert allclose( 2*sin(120*pi/600)/3 + sin(60*pi/600)/3, q[2] )
    333333       
     334    def test_point_on_line(self):
     335               
     336        #Endpoints first       
     337        assert point_on_line( (0, 0), [(0,0), (1,0)] ) 
     338        assert point_on_line( (1, 0), [(0,0), (1,0)] )         
     339
     340        #Then points on line   
     341        assert point_on_line( (0.5, 0), [(0,0), (1,0)] )
     342        assert point_on_line( (0, 0.5), [(0,1), (0,0)] )               
     343        assert point_on_line( (1, 0.5), [(1,1), (1,0)] )       
     344        assert point_on_line( (0.5, 0.5), [(0,0), (1,1)] )             
     345       
     346        #Then points not on line               
     347        assert not point_on_line( (0.5, 0), [(0,1), (1,1)] )   
     348        assert not point_on_line( (0, 0.5), [(0,0), (1,1)] )
     349       
     350       
     351       
     352    def test_inside_polygon(self):
     353   
     354        #Simplest case: Polygon is the unit square
     355        polygon = [[0,0], [1,0], [1,1], [0,1]]
     356 
     357        x = y = 0.5
     358        assert inside_polygon( (x, y), polygon )               
     359       
     360        y = 1.5
     361        assert not inside_polygon( (x, y), polygon )                           
     362        #Try point on borders   
     363        assert inside_polygon( (1., 0.5), polygon, closed=True)
     364        assert inside_polygon( (0.5, 1), polygon, closed=True) 
     365        assert inside_polygon( (0., 0.5), polygon, closed=True)
     366        assert inside_polygon( (0.5, 0.), polygon, closed=True)
     367       
     368        assert not inside_polygon( (0.5, 1), polygon, closed=False)     
     369        assert not inside_polygon( (0., 0.5), polygon, closed=False)   
     370        assert not inside_polygon( (0.5, 0.), polygon, closed=False)   
     371        assert not inside_polygon( (1., 0.5), polygon, closed=False)   
    334372       
    335373             
     374        #More convoluted and non convex polygon
     375        polygon = [[0,0], [1,0], [0.5,-1], [2, -1], [2,1], [0,1]]
     376        assert inside_polygon( (0.5, 0.5), polygon )
     377        assert inside_polygon( (1, -0.5), polygon )
     378        assert inside_polygon( (1.5, 0), polygon )
     379       
     380        assert not inside_polygon( (0.5, 1.5), polygon )       
     381        assert not inside_polygon( (0.5, -0.5), polygon )               
     382       
     383       
     384       
     385        #Now try the vector formulation returning indices
     386        points = [ [0.5, 0.5], [1, -0.5], [1.5, 0], [0.5, 1.5], [0.5, -0.5]]
     387        res = inside_polygon( points, polygon )
     388       
     389        assert allclose( res, [0,1,2] )
     390       
     391       
     392
     393                     
    336394#-------------------------------------------------------------
    337395if __name__ == "__main__":
  • inundation/ga/storm_surge/pyvolution/util.py

    r630 r655  
    4747
    4848
     49
     50def point_on_line(point, line):
     51    """Determine whether a point is on a line segment
     52   
     53    Input:
     54        point: (x, y)
     55        line: [ (x0, y0), (x1, y1) ]
     56       
     57    """
     58   
     59    #FIXME: Could do with some optimisation         
     60       
     61    from Numeric import array, dot, allclose
     62    from math import sqrt
     63
     64    x = point[0]
     65    y = point[1]   
     66   
     67    x0 = line[0][0]                     
     68    x1 = line[1][0]
     69    y0 = line[0][1]       
     70    y1 = line[1][1]
     71
     72   
     73    a = array([x - x0, y - y0])                 
     74    b = array([x1 - x0, y1 - y0])
     75   
     76    len_a = sqrt(sum(a**2))           
     77    len_b = sqrt(sum(b**2))                 
     78               
     79    if len_a == 0 or len_a == len_b:
     80       return True
     81    else:
     82       x = dot(a, b)/len_b       
     83       return allclose(x, len_a)
     84
     85       
     86   
     87def inside_polygon(point, polygon, closed = True):
     88    """Determine whether points are inside or outside a polygon
     89   
     90    Input:
     91       point - Tuple of (x, y) coordinates, or list of tuples
     92       polygon - list of vertices of polygon
     93   
     94    Output:
     95       If one point is considered, True or False is returned.
     96       If multiple points are passed in, the function returns indices
     97       of those points that fall inside the polygon     
     98       
     99    Examples:
     100       inside_polygon( [0.5, 0.5], [[0,0], [1,0], [1,1], [0,1]] )
     101       will evaluate to True as the point 0.5, 0.5 is inside the unit square
     102       
     103       inside_polygon( [[0.5, 0.5], [1, -0.5], [0.3, 0.2]] )
     104       will return the indices [0, 2] as only the first and the last point
     105       is inside the unit square
     106       
     107    Remarks:
     108       <Copy from source Franklins code >   
     109               
     110               
     111       points at a vertex are considered to be inside         
     112       
     113    Algorithm due to Darel Finley, http://www.alienryderflex.com/polygon/
     114   
     115   
     116    FIXME: More comments about algoritm
     117    FIXME: Deal with case where point on border of polygon (closed)
     118       
     119    """   
     120
     121    from Numeric import array, Float, reshape
     122   
     123   
     124    #Input checks
     125    try:
     126        point = array(point).astype(Float)         
     127    except:
     128        msg = 'Point %s could not be converted to Numeric array' %point
     129        raise msg       
     130       
     131    try:
     132        polygon = array(polygon).astype(Float)             
     133    except:
     134        msg = 'Polygon %s could not be converted to Numeric array' %polygon
     135        raise msg               
     136   
     137    assert len(polygon.shape) == 2,\
     138       'Polygon array must be a 2d array of vertices: %s' %polygon
     139
     140       
     141    assert polygon.shape[1] == 2,\
     142       'Polygon array must have two columns: %s' %polygon   
     143
     144
     145    if len(point.shape) == 1:
     146        one_point = True
     147        points = reshape(point, (1,2))
     148    else:       
     149        one_point = False
     150        points = point
     151
     152    N = polygon.shape[0] #Number of vertices in polygon
     153
     154    px = polygon[:,0]
     155    py = polygon[:,1]   
     156               
     157    #Begin algorithm
     158    indices = []
     159    for k in range(points.shape[0]):
     160        #for each point   
     161        x = points[k, 0]
     162        y = points[k, 1]       
     163
     164           
     165        inside = False
     166        for i in range(N):
     167            j = (i+1)%N
     168           
     169            #Check for case where point is contained in line segment   
     170            if point_on_line( (x,y), [ [px[i], py[i]], [px[j], py[j]] ]):
     171                if closed:
     172                    inside = True
     173                else:       
     174                    inside = False
     175                break
     176       
     177            #Check truly inside polygon             
     178            if px[i] < y and py[j] >= y or\
     179               py[j] < y and py[i] >= y:
     180                if px[i] + (y-py[i])/(py[j]-py[i])*(px[j]-px[i]) < x:
     181                    inside = not inside
     182                   
     183        if inside: indices.append(k)
     184   
     185    if one_point:
     186        return inside
     187    else:
     188        return indices
     189             
    49190
    50191class File_function:
Note: See TracChangeset for help on using the changeset viewer.