Ignore:
Timestamp:
Jun 4, 2010, 10:03:48 PM (14 years ago)
Author:
hudson
Message:

Cleaned up unit tests to use API.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/anuga_core/source/anuga/geometry/polygon.py

    r7711 r7778  
    77from math import sqrt
    88from anuga.utilities.numerical_tools import ensure_numeric
    9 from anuga.geospatial_data.geospatial_data import ensure_absolute, Geospatial_data
     9from anuga.geospatial_data.geospatial_data import ensure_absolute, \
     10                                                    Geospatial_data
    1011from anuga.config import netcdf_float
    1112import anuga.utilities.log as log
     
    6970                         % (str(p1), str(p2), str(p3), str(p4)))
    7071
    71 #                     0s1    0e1    1s0    1e0   # line 0 starts on 1, 0 ends 1, 1 starts 0, 1 ends 0
    72 collinear_result = { (False, False, False, False): lines_dont_coincide,
    73                      (False, False, False, True ): lines_error,
    74                      (False, False, True,  False): lines_error,
    75                      (False, False, True,  True ): lines_1_fully_included_in_0,
    76                      (False, True,  False, False): lines_error,
    77                      (False, True,  False, True ): lines_overlap_opposite_direction2,
    78                      (False, True,  True,  False): lines_overlap_same_direction2,
    79                      (False, True,  True,  True ): lines_1_fully_included_in_0,
    80                      (True,  False, False, False): lines_error,
    81                      (True,  False, False, True ): lines_overlap_same_direction,
    82                      (True,  False, True,  False): lines_overlap_opposite_direction,
    83                      (True,  False, True,  True ): lines_1_fully_included_in_0,
    84                      (True,  True,  False, False): lines_0_fully_included_in_1,
    85                      (True,  True,  False, True ): lines_0_fully_included_in_1,
    86                      (True,  True,  True,  False): lines_0_fully_included_in_1,
    87                      (True,  True,  True,  True ): lines_0_fully_included_in_1
    88                    }
     72collinear_result = {
     73# line 0 starts on 1, 0 ends 1, 1 starts 0, 1 ends 0
     74#       0s1    0e1    1s0    1e0   
     75       (False, False, False, False): lines_dont_coincide,
     76       (False, False, False, True ): lines_error,
     77       (False, False, True,  False): lines_error,
     78       (False, False, True,  True ): lines_1_fully_included_in_0,
     79       (False, True,  False, False): lines_error,
     80       (False, True,  False, True ): lines_overlap_opposite_direction2,
     81       (False, True,  True,  False): lines_overlap_same_direction2,
     82       (False, True,  True,  True ): lines_1_fully_included_in_0,
     83       (True,  False, False, False): lines_error,
     84       (True,  False, False, True ): lines_overlap_same_direction,
     85       (True,  False, True,  False): lines_overlap_opposite_direction,
     86       (True,  False, True,  True ): lines_1_fully_included_in_0,
     87       (True,  True,  False, False): lines_0_fully_included_in_1,
     88       (True,  True,  False, True ): lines_0_fully_included_in_1,
     89       (True,  True,  True,  False): lines_0_fully_included_in_1,
     90       (True,  True,  True,  True ): lines_0_fully_included_in_1
     91   }
    8992
    9093##
     
    275278   
    276279    # Quickly reject points that are clearly outside
    277     if point[0] < min(triangle[:,0]): return False
    278     if point[0] > max(triangle[:,0]): return False   
    279     if point[1] < min(triangle[:,1]): return False
    280     if point[1] > max(triangle[:,1]): return False       
     280    if point[0] < min(triangle[:, 0]): return False
     281    if point[0] > max(triangle[:, 0]): return False   
     282    if point[1] < min(triangle[:, 1]): return False
     283    if point[1] > max(triangle[:, 1]): return False       
    281284
    282285
     
    367370                (type, point) = intersection(leftmost, l_x[cmp])
    368371                comparisons += 1
    369                 if type != 0 and type != 4 or (type == 2 and list(point[0]) != list(point[1])):
     372                if type != 0 and type != 4 or (type == 2 and list(point[0]) !=\
     373                                                list(point[1])):
    370374                    if verbose:
    371                         print 'Self-intersecting polygon found, type ', type, ' point', point,
     375                        print 'Self-intersecting polygon found, type ', type
     376                        print 'point', point,
    372377                        print 'vertices: ', leftmost, ' - ', l_x[cmp]               
    373378                    return True           
     
    586591    if count == len(indices):
    587592        # No points are outside
    588         return indices[:count],[]
     593        return indices[:count], []
    589594    else:
    590595        return  indices[:count], indices[count:][::-1]  #return reversed
    591596
    592 ##
    593 # @brief Sort a list of points into contiguous points inside+outside a polygon.
    594 # @param points A set of points (tuple, list or array).
    595 # @param polygon A set of points defining a polygon (tuple, list or array).
    596 # @param closed True if points on boundary are considered 'inside' polygon.
    597 # @param verbose True if this function is to be verbose.
    598 # @return (indices, count) where indices are point indices and count is the
    599 #          delimiter index between point inside (on left) and others.
     597
     598
    600599def separate_points_by_polygon(points, polygon,
    601600                               closed=True,
     
    644643    if check_input:
    645644        #Input checks
    646         assert isinstance(closed, bool), 'Keyword argument "closed" must be boolean'
    647         assert isinstance(verbose, bool), 'Keyword argument "verbose" must be boolean'
     645        assert isinstance(closed, bool), \
     646                    'Keyword argument "closed" must be boolean'
     647        assert isinstance(verbose, bool), \
     648                    'Keyword argument "verbose" must be boolean'
    648649
    649650        try:
     
    737738    return abs(poly_area/2)
    738739
    739 ##
    740 # @brief Plot a set of polygons.
    741 # @param polygons_points List of polygons to plot.
    742 # @param style List of styles for each polygon.
    743 # @param figname Name to save figure to.
    744 # @param label Title for the plot.
    745 # @param verbose True if this function is to be verbose.
    746 # @return A list of min/max x and y values [minx, maxx, miny, maxy].
    747 # @note A style value is 'line' for polygons, 'outside' for points outside.
     740
    748741def plot_polygons(polygons_points,
    749742                  style=None,
     
    818811            if s == 'outside': colour.append('r.')
    819812            if s == 'point': colour.append('g.')
    820             if s <> 'line':
    821                 if s <> 'outside':
    822                     if s <> 'point':
     813            if s != 'line':
     814                if s != 'outside':
     815                    if s != 'point':
    823816                        colour.append(s)
    824817
     
    836829        title(label)
    837830
    838     #raw_input('wait 1')
    839     #FIXME(Ole): This makes for some strange scalings sometimes.
    840     #if minx <> 0:
    841     #    axis([minx*0.9,maxx*1.1,miny*0.9,maxy*1.1])
    842     #else:
    843     #    if miny == 0:
    844     #        axis([-maxx*.01,maxx*1.1,-maxy*0.01,maxy*1.1])
    845     #    else:
    846     #        axis([-maxx*.01,maxx*1.1,miny*0.9,maxy*1.1])
    847 
    848831    if figname is not None:
    849832        savefig(figname)
     
    856839    return vec
    857840
    858 ##
    859 # @brief
    860 # @param polygon A set of points defining a polygon.
    861 # @param verbose True if this function is to be verbose.
    862 # @return A tuple (x, y) of X and Y coordinates of the polygon.
    863 # @note We duplicate the first point so can have closed polygon in plot.
     841
    864842def poly_xy(polygon, verbose=False):
    865843    """ this is used within plot_polygons so need to duplicate
    866844        the first point so can have closed polygon in plot
     845        # @param polygon A set of points defining a polygon.
     846        # @param verbose True if this function is to be verbose.
     847        # @return A tuple (x, y) of X and Y coordinates of the polygon.
     848        # @note We duplicate the first point so can have closed polygon in plot.
    867849    """
    868850
     
    884866
    885867
    886 ##
    887 # @brief Define a class that defines a callable object for a polygon.
    888 # @note Object created is function: f: x,y -> z
    889 #       where x, y and z are vectors and z depends on whether x,y belongs
    890 #       to specified polygons.
    891868class Polygon_function:
    892869    """Create callable object f: x,y -> z, where a,y,z are vectors and
     
    923900    """
    924901
    925     ##
    926     # @brief Create instance of a polygon function.
    927     # @param regions A list of (x,y) tuples defining a polygon.
    928     # @param default Value or function returning value for points outside poly.
    929     # @param geo_reference ??
    930902    def __init__(self, regions, default=0.0, geo_reference=None):
     903        """
     904        # @brief Create instance of a polygon function.
     905        # @param regions A list of (x,y) tuples defining a polygon.
     906        # @param default Value or function returning value for points outside poly.
     907        # @param geo_reference ??
     908        """
     909
    931910        try:
    932911            len(regions)
     
    967946            self.regions.append((P, value))
    968947
    969     ##
    970     # @brief Implement the 'callable' property of Polygon_function.
    971     # @param x List of x coordinates of points ot interest.
    972     # @param y List of y coordinates of points ot interest.
    973948    def __call__(self, x, y):
     949        """
     950        # @brief Implement the 'callable' property of Polygon_function.
     951        # @param x List of x coordinates of points ot interest.
     952        # @param y List of y coordinates of points ot interest.
     953        """
    974954        x = num.array(x, num.float)
    975955        y = num.array(y, num.float)
     
    1014994################################################################################
    1015995
    1016 ##
    1017 # @brief Read polygon data from a file.
     996def read_polygon(filename, delimiter=','):
     997    """Read points assumed to form a polygon.
     998
    1018999# @param filename Path to file containing polygon data.
    10191000# @param delimiter Delimiter to split polygon data with.
    10201001# @return A list of point data from the polygon file.
    1021 def read_polygon(filename, delimiter=','):
    1022     """Read points assumed to form a polygon.
     1002
    10231003
    10241004    There must be exactly two numbers in each line separated by the delimiter.
     
    10361016    # check this is a valid polygon.
    10371017    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.'
     1018        msg = 'ERROR: Self-intersecting polygon detected in file '
     1019        msg += filename +'. A complex polygon will not '
     1020        msg += 'necessarily break the algorithms within ANUGA, but it'
     1021        msg += 'usually signifies pathological data. Please fix this file.'
    10411022        raise Exception, msg
    10421023   
     
    10691050    pass
    10701051
    1071 ##
    1072 # @brief Populate given polygon with uniformly distributed points.
    1073 # @param polygon Polygon to uniformly fill.
    1074 # @param number_of_points Number of points required in polygon.
    1075 # @param seed Seed for random number generator.
    1076 # @param exclude List of polygons inside main where points should be excluded.
    1077 # @return List of random points inside input polygon.
    1078 # @note Delimiter is assumed to be a comma.
     1052
    10791053def populate_polygon(polygon, number_of_points, seed=None, exclude=None):
    10801054    """Populate given polygon with uniformly distributed points.
     
    11311105    return points
    11321106
    1133 ##
    1134 # @brief Get a point inside a polygon that is close to an edge.
    1135 # @param polygon List  of vertices of polygon.
    1136 # @param delta Maximum distance from an edge is delta * sqrt(2).
    1137 # @return A point that is inside polgon and close to the polygon edge.
     1107
    11381108def point_in_polygon(polygon, delta=1e-8):
    11391109    """Return a point inside a given polygon which will be close to the
     
    11861156    return point
    11871157
    1188 ##
    1189 # @brief Calculate approximate number of triangles inside a bounding polygon.
    1190 # @param interior_regions
    1191 # @param bounding_poly
    1192 # @param remainder_res
    1193 # @return The number of triangles.
     1158
    11941159def number_mesh_triangles(interior_regions, bounding_poly, remainder_res):
    11951160    """Calculate the approximate number of triangles inside the
     
    12471212    return int(total_number_of_triangles)
    12481213
     1214
     1215def decimate_polygon(polygon, factor=10):
     1216    """Reduce number of points in polygon by the specified
     1217    factor (default=10, hence the name of the function) such that
     1218    the extrema in both axes are preserved.
     1219
    12491220##
    12501221# @brief Reduce number of points in polygon by the specified factor.
    12511222# @param polygon The polygon to reduce.
    12521223# @param factor The factor to reduce polygon points by (default 10).
    1253 # @return The reduced polygon points list.
    12541224# @note The extrema of both axes are preserved.
    1255 def decimate_polygon(polygon, factor=10):
    1256     """Reduce number of points in polygon by the specified
    1257     factor (default=10, hence the name of the function) such that
    1258     the extrema in both axes are preserved.
    12591225
    12601226    Return reduced polygon
     
    12851251    return reduced_polygon
    12861252
    1287 ##
    1288 # @brief Interpolate linearly from polyline nodes to midpoints of triangles.
    1289 # @param data The data on the polyline nodes.
    1290 # @param polyline_nodes ??
    1291 # @param gauge_neighbour_id ??  FIXME(Ole): I want to get rid of this
    1292 # @param point_coordinates ??
    1293 # @param verbose True if this function is to be verbose.
     1253
    12941254def interpolate_polyline(data,
    12951255                         polyline_nodes,
     
    13701330               
    13711331    return points, vertices
    1372 ##
    1373 # @brief
    1374 # @param data
    1375 # @param polyline_nodes
    1376 # @param gauge_neighbour_id
    1377 # @param interpolation_points
    1378 # @param interpolated_values
    1379 # @param rtol
    1380 # @param atol
    1381 # @return
    1382 # @note OBSOLETED BY C-EXTENSION
    1383 def _interpolate_polyline(data,
    1384                           polyline_nodes,
    1385                           gauge_neighbour_id,
    1386                           interpolation_points,
    1387                           interpolated_values,
    1388                           rtol=1.0e-6,
    1389                           atol=1.0e-8):
    1390     """Auxiliary function used by interpolate_polyline
    1391 
    1392     NOTE: OBSOLETED BY C-EXTENSION
    1393     """
    1394 
    1395     number_of_nodes = len(polyline_nodes)
    1396     number_of_points = len(interpolation_points)
    1397 
    1398     for j in range(number_of_nodes):
    1399         neighbour_id = gauge_neighbour_id[j]
    1400 
    1401         # FIXME(Ole): I am convinced that gauge_neighbour_id can be discarded,
    1402         #             but need to check with John J.
    1403         # Keep it for now (17 Jan 2009)
    1404         # When gone, we can simply interpolate between neighbouring nodes,
    1405         # i.e. neighbour_id = j+1.
    1406         # and the test below becomes something like: if j < number_of_nodes...
    1407 
    1408         if neighbour_id >= 0:
    1409             x0, y0 = polyline_nodes[j,:]
    1410             x1, y1 = polyline_nodes[neighbour_id,:]
    1411 
    1412             segment_len = sqrt((x1-x0)**2 + (y1-y0)**2)
    1413             segment_delta = data[neighbour_id] - data[j]
    1414             slope = segment_delta/segment_len
    1415 
    1416             for i in range(number_of_points):
    1417                 x, y = interpolation_points[i,:]
    1418                 if point_on_line([x, y], [[x0, y0], [x1, y1]],
    1419                                  rtol=rtol, atol=atol):
    1420                     dist = sqrt((x-x0)**2 + (y-y0)**2)
    1421                     interpolated_values[i] = slope*dist + data[j]
    14221332
    14231333
Note: See TracChangeset for help on using the changeset viewer.