django/contrib/gis/geos/tests/pymutable_geometries.py
author Justin Bronn <jbronn@geodjango.org>
Sat Jan 31 15:18:50 2009 -0600 (3 years ago)
branchtrunk
changeset 138 466bece04a15
child 354 3fcbf6e3e599
permissions -rw-r--r--
Merged in patch from Aryeh Leib Taurog for #9877, adapting as necessary.
     1 from django.contrib.gis.geos import *
     2 from random import random
     3 
     4 SEQ_LENGTH = 10
     5 SEQ_RANGE = (-1 * SEQ_LENGTH, SEQ_LENGTH)
     6 SEQ_BOUNDS = (-1 * SEQ_LENGTH, -1, 0, SEQ_LENGTH - 1)
     7 SEQ_OUT_OF_BOUNDS = (-1 * SEQ_LENGTH -1 , SEQ_LENGTH)
     8 
     9 def seqrange(): return xrange(*SEQ_RANGE)
    10 
    11 def random_coord(dim    = 2,           # coordinate dimensions
    12                  rng    = (-50,50),    # coordinate range
    13                  num_type     = float,
    14                  round_coords = True):
    15 
    16     if round_coords:
    17         num = lambda: num_type(round(random() * (rng[1]-rng[0]) + rng[0]))
    18     else:
    19         num = lambda: num_type(random() * (rng[1]-rng[0]) + rng[0])
    20     
    21     return tuple( num() for axis in xrange(dim) )
    22 
    23 def random_list(length = SEQ_LENGTH, ring = False, **kwargs):
    24     result  = [ random_coord(**kwargs) for index in xrange(length) ]
    25     if ring:
    26         result[-1] = result[0]
    27 
    28     return result
    29 
    30 random_list.single = random_coord
    31 
    32 def random_coll(count = SEQ_LENGTH, **kwargs):
    33     return [ tuple(random_list(**kwargs)) for i in xrange(count) ]
    34 
    35 random_coll.single = random_list
    36 
    37 class PyMutTestGeom:
    38     "The Test Geometry class container."
    39     def __init__(self, geom_type, coords_fcn=random_list, subtype=tuple, **kwargs):
    40         self.geom_type  = geom_type
    41         self.subtype    = subtype
    42         self.coords_fcn = coords_fcn
    43         self.fcn_args   = kwargs
    44         self.coords = self.coords_fcn(**kwargs)
    45         self.geom   = self.make_geom()
    46 
    47     def newitem(self, **kwargs):
    48         a = self.coords_fcn.single(**kwargs)
    49         return self.subtype(a), tuple(a)
    50 
    51     @property
    52     def tuple_coords(self):
    53         return tuple(self.coords)
    54 
    55     def make_geom(self):
    56         return self.geom_type(map(self.subtype,self.coords))
    57 
    58 
    59 def slice_geometries(ring=True): 
    60     testgeoms = [
    61         PyMutTestGeom(LineString),
    62         PyMutTestGeom(MultiPoint, subtype=Point),
    63         PyMutTestGeom(MultiLineString, coords_fcn=random_coll, subtype=LineString),
    64         ]
    65     if ring:
    66         testgeoms.append(PyMutTestGeom(LinearRing, ring=True))
    67 
    68     return testgeoms
    69 
    70 def getslice_functions(): 
    71     def gs_01(x): x[0:4],   
    72     def gs_02(x): x[5:-1],  
    73     def gs_03(x): x[6:2:-1],
    74     def gs_04(x): x[:],     
    75     def gs_05(x): x[:3],    
    76     def gs_06(x): x[::2],   
    77     def gs_07(x): x[::-4],  
    78     def gs_08(x): x[7:7],   
    79     def gs_09(x): x[20:],   
    80 
    81     # don't really care about ringy-ness here
    82     return mark_ring(vars(), 'gs_')
    83 
    84 def delslice_functions():
    85     def ds_01(x): del x[0:4]   
    86     def ds_02(x): del x[5:-1]  
    87     def ds_03(x): del x[6:2:-1]
    88     def ds_04(x): del x[:]     # should this be allowed?
    89     def ds_05(x): del x[:3]    
    90     def ds_06(x): del x[1:9:2]   
    91     def ds_07(x): del x[::-4]  
    92     def ds_08(x): del x[7:7]   
    93     def ds_09(x): del x[-7:-2]
    94 
    95     return mark_ring(vars(), 'ds_')
    96 
    97 def setslice_extended_functions(g):
    98     a = g.coords_fcn(3, rng=(100,150))
    99     def maptype(x,a):
   100         if isinstance(x, list): return a
   101         else: return map(g.subtype, a)
   102 
   103     def sse_00(x): x[:3:1]      = maptype(x, a)
   104     def sse_01(x): x[0:3:1]     = maptype(x, a)
   105     def sse_02(x): x[2:5:1]     = maptype(x, a)
   106     def sse_03(x): x[-3::1]     = maptype(x, a)
   107     def sse_04(x): x[-4:-1:1]   = maptype(x, a)
   108     def sse_05(x): x[8:5:-1]    = maptype(x, a)
   109     def sse_06(x): x[-6:-9:-1]  = maptype(x, a)
   110     def sse_07(x): x[:8:3]      = maptype(x, a)
   111     def sse_08(x): x[1::3]      = maptype(x, a)
   112     def sse_09(x): x[-2::-3]    = maptype(x, a)
   113     def sse_10(x): x[7:1:-2]    = maptype(x, a)
   114     def sse_11(x): x[2:8:2]     = maptype(x, a)
   115 
   116     return mark_ring(vars(), 'sse_')
   117 
   118 def setslice_simple_functions(g):
   119     a = g.coords_fcn(3, rng=(100,150))
   120     def maptype(x,a):
   121         if isinstance(x, list): return a
   122         else: return map(g.subtype, a)
   123 
   124     def ss_00(x): x[:0]  = maptype(x, a)
   125     def ss_01(x): x[:1]  = maptype(x, a)
   126     def ss_02(x): x[:2]  = maptype(x, a)
   127     def ss_03(x): x[:3]  = maptype(x, a)
   128     def ss_04(x): x[-4:] = maptype(x, a)
   129     def ss_05(x): x[-3:] = maptype(x, a)
   130     def ss_06(x): x[-2:] = maptype(x, a)
   131     def ss_07(x): x[-1:] = maptype(x, a)
   132     def ss_08(x): x[5:]  = maptype(x, a)
   133     def ss_09(x): x[:]   = maptype(x, a)
   134     def ss_10(x): x[4:4] = maptype(x, a)
   135     def ss_11(x): x[4:5] = maptype(x, a)
   136     def ss_12(x): x[4:7] = maptype(x, a)
   137     def ss_13(x): x[4:8] = maptype(x, a)
   138     def ss_14(x): x[10:] = maptype(x, a)
   139     def ss_15(x): x[20:30]  = maptype(x, a)
   140     def ss_16(x): x[-13:-8] = maptype(x, a)
   141     def ss_17(x): x[-13:-9] = maptype(x, a)
   142     def ss_18(x): x[-13:-10] = maptype(x, a)
   143     def ss_19(x): x[-13:-11] = maptype(x, a)
   144 
   145     return mark_ring(vars(), 'ss_')
   146 
   147 def test_geos_functions():
   148 
   149     return (
   150         lambda x: x.num_coords,
   151         lambda x: x.empty,
   152         lambda x: x.valid,
   153         lambda x: x.simple,
   154         lambda x: x.ring,
   155         lambda x: x.boundary,
   156         lambda x: x.convex_hull,
   157         lambda x: x.extend,
   158         lambda x: x.area,
   159         lambda x: x.length,
   160             )
   161 
   162 def mark_ring(locals, name_pat, length=SEQ_LENGTH):
   163     '''
   164     Accepts an array of functions which perform slice modifications
   165     and labels each function as to whether or not it preserves ring-ness
   166     '''
   167     func_array = [ val for name, val in locals.items()
   168                     if hasattr(val, '__call__')
   169                     and name.startswith(name_pat) ]
   170 
   171     for i in xrange(len(func_array)):
   172         a = range(length)
   173         a[-1] = a[0]
   174         func_array[i](a)
   175         ring = len(a) == 0 or (len(a) > 3 and a[-1] == a[0])
   176         func_array[i].ring = ring
   177 
   178     return func_array
   179 
   180 def getcoords(o):
   181     if hasattr(o, 'coords'):
   182         return o.coords
   183     else:
   184         return o