Ignore:
Timestamp:
Apr 21, 2010, 1:48:09 PM (15 years ago)
Author:
hudson
Message:

Check for complex polygons raises an exception.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • anuga_core/source/anuga/utilities/polygon.py

    r7687 r7690  
    322322    return False
    323323
     324   
    324325def is_complex(polygon, verbose=False):
    325     """Check if a polygon is complex (self-intersecting)
    326     """
    327    
     326    """Check if a polygon is complex (self-intersecting).
     327       Uses a sweep algorithm that is O(n^2) in the worst case, but
     328       for most normal looking polygons it'll be O(n log n).
     329
     330       polygon is a list of points that define a closed polygon.
     331       verbose will print a list of the intersection points if true
     332       
     333       Return True if polygon is complex.
     334    """           
     335           
     336    def key_xpos(item):
     337        return (item[0][0])
     338   
     339    def segments_joined(seg0, seg1):
     340        for i in seg0:
     341            for j in seg1:   
     342                if i == j: return True
     343        return False
     344       
    328345    polygon = ensure_numeric(polygon, num.float)
    329346
     347    # build a list of discrete segments from the polygon
     348    unsorted_segs = []
    330349    for i in range(0, len(polygon)-1):
    331         for j in range(i+1, len(polygon)-1):   
    332                 (type, point) = intersection([polygon[i], polygon[i+1]], [polygon[j], polygon[j+1]])
    333 
    334                 if (abs(i-j) > 1 and type == 1) or (type == 2 and list(point[0]) != list(point[1])) or (type == 3) and type != 4:
     350        unsorted_segs.append([list(polygon[i]), list(polygon[i+1])])
     351    unsorted_segs.append([list(polygon[0]), list(polygon[-1])])
     352   
     353    # all segments must point in same direction
     354    for val in unsorted_segs:
     355        if val[0][0] > val[1][0]:
     356            val[0], val[1] = val[1], val[0]   
     357           
     358    l_x = sorted(unsorted_segs, key=key_xpos)
     359
     360    comparisons = 0
     361   
     362    # loop through, only comparing lines that partially overlap in x
     363    for index, leftmost in enumerate(l_x):
     364        cmp = index+1
     365        while cmp < len(l_x) and leftmost[1][0] > l_x[cmp][0][0]:
     366            if not segments_joined(leftmost, l_x[cmp]):
     367                (type, point) = intersection(leftmost, l_x[cmp])
     368                comparisons += 1
     369                if type != 0 and type != 4 or (type == 2 and list(point[0]) != list(point[1])):
    335370                    if verbose:
    336                         print 'Self-intersecting polygon found, type ', type, ' point', point, 'vertex indices ', i, j               
    337                     return True
     371                        print 'Self-intersecting polygon found, type ', type, ' point', point,
     372                        print 'vertices: ', leftmost, ' - ', l_x[cmp]               
     373                    return True           
     374            cmp += 1
    338375       
    339376    return False
     377   
    340378   
    341379def is_inside_polygon_quick(point, polygon, closed=True, verbose=False):
     
    9961034        polygon.append([float(fields[0]), float(fields[1])])
    9971035   
    998     # check this is a valid polygon   
    999     # if is_complex(polygon):   
    1000             # msg = 'ERROR: Self-intersecting polygon detected in file' + filename +'. '
    1001             # msg += 'Please fix.'
    1002             # log.critical(msg)
    1003 # #            raise Exception, msg
     1036    # check this is a valid polygon.
     1037    if is_complex(polygon, verbose=True):   
     1038        msg = 'ERROR: Self-intersecting polygon detected in file ' + filename +'. '
     1039        msg += 'A complex polygon will not necessarily break the algorithms within ANUGA, '
     1040        msg += 'but it usually signifies pathological data. Please fix this file.'
     1041        raise Exception, msg
    10041042   
    10051043    return polygon
Note: See TracChangeset for help on using the changeset viewer.