Django

Code

Changeset 5478

Show
Ignore:
Timestamp:
06/15/07 01:02:04 (1 year ago)
Author:
jbronn
Message:

gis: GDAL improvements; added Driver class, improved tests, removed non-existent exception, updated geometries for tests, updated documentation.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/gdal/DataSource.py

    r5397 r5478  
    77from django.contrib.gis.gdal.OGRError import OGRException, check_err 
    88from django.contrib.gis.gdal.Layer import Layer 
     9from django.contrib.gis.gdal.Driver import Driver 
    910 
    1011""" 
     
    1213   an interface for reading vector geometry data from many different file 
    1314   formats (including ESRI shapefiles). 
     15 
     16  When instantiating a DataSource object, use the filename of a 
     17   GDAL-supported data source.  For example, a SHP file or a 
     18   TIGER/Line file from the government. 
     19 
     20  The ds_driver keyword is used internally when a ctypes pointer 
     21    is passed in directly. 
    1422 
    1523  Example: 
     
    2331            desc = feature['description'] 
    2432 
    25   More documentation forthcoming. 
     33            # We can also increment through all of the fields 
     34            #  attached to this feature. 
     35            for field in feature: 
     36                # Get the name of the field (e.g. 'description') 
     37                nm = field.name 
     38 
     39                # Get the type (integer) of the field, e.g. 0 => OFTInteger 
     40                t = field.type 
     41 
     42                # Returns the value the field; OFTIntegers return ints, 
     43                #  OFTReal returns floats, all else returns string. 
     44                val = field.value 
    2645""" 
    2746 
     
    2948#  http://www.gdal.org/ogr/ogr__api_8h.html 
    3049# 
    31 # The OGR_DS* routines are relevant here. 
     50# The OGR_DS_* routines are relevant here. 
    3251 
    3352class DataSource(object): 
     
    3756     
    3857    #### Python 'magic' routines #### 
    39     def __init__(self, ds_file): 
     58    def __init__(self, ds_input, ds_driver=False): 
    4059 
    4160        # Registering all the drivers, this needs to be done 
    4261        #  _before_ we try to open up a data source. 
    43         if not lgdal.OGRRegisterAll(): 
    44             raise OGRException, 'Could not register all data source drivers!' 
     62        if not lgdal.OGRGetDriverCount() and not lgdal.OGRRegisterAll(): 
     63            raise OGRException, 'Could not register all the OGR data source drivers!' 
    4564 
    46         # The data source driver is a void pointer. 
    47         ds_driver = c_void_p() 
     65        if isinstance(ds_input, StringType): 
    4866 
    49         # OGROpen will auto-detect the data source type. 
    50         ds = lgdal.OGROpen(c_char_p(ds_file), c_int(0), byref(ds_driver)) 
     67            # The data source driver is a void pointer. 
     68            ds_driver = c_void_p() 
     69 
     70            # OGROpen will auto-detect the data source type. 
     71            ds = lgdal.OGROpen(c_char_p(ds_input), c_int(0), byref(ds_driver)) 
     72        elif isinstance(ds_input, c_void_p) and isinstance(ds_driver, c_void_p): 
     73            ds = ds_input 
     74        else: 
     75            raise OGRException, 'Invalid data source input type: %s' % str(type(ds_input)) 
    5176 
    5277        # Raise an exception if the returned pointer is NULL 
    5378        if not ds: 
    5479            self._ds = False 
    55             raise OGRException, 'Invalid data source file "%s"' % ds_file 
     80            raise OGRException, 'Invalid data source file "%s"' % ds_input 
    5681        else: 
    5782            self._ds = ds 
    58             self._driver = ds_driver 
     83            self._driver = Driver(ds_driver) 
    5984 
    6085    def __del__(self): 
     
    84109    def __str__(self): 
    85110        "Returns OGR GetName and Driver for the Data Source." 
    86         return '%s (%s)' % (self.name, self.driver
     111        return '%s (%s)' % (self.name, str(self.driver)
    87112 
    88113    #### DataSource Properties #### 
    89114    @property 
    90115    def driver(self): 
    91         "Returns the name of the data source driver." 
    92         return string_at(lgdal.OGR_Dr_GetName(self._driver)) 
     116        "Returns the Driver object for this Data Source." 
     117        return self._driver 
    93118         
    94119    @property 
  • django/branches/gis/django/contrib/gis/gdal/Feature.py

    r5397 r5478  
    11# types and ctypes 
    2 import types 
     2from types import StringType 
    33from ctypes import c_char_p, c_int, string_at 
    44 
     
    3232    def __getitem__(self, index): 
    3333        "Gets the Field at the specified index." 
    34         if isinstance(index, types.StringType): 
     34        if isinstance(index, StringType): 
    3535            i = self.index(index) 
    3636        else: 
  • django/branches/gis/django/contrib/gis/gdal/Field.py

    r5397 r5478  
    99# The OGR_Fld_* routines are relevant here. 
    1010class Field(object): 
    11     "A class that wraps an OGR Field." 
     11    "A class that wraps an OGR Field, needs to be instantiated from a Feature object." 
    1212 
    1313    _fld = 0 # Initially NULL 
  • django/branches/gis/django/contrib/gis/gdal/__init__.py

    r5397 r5478  
     1from Driver import Driver 
    12from DataSource import DataSource 
    23from SpatialReference import SpatialReference, CoordTransform 
  • django/branches/gis/django/contrib/gis/gdal/libgdal.py

    r5397 r5478  
    11import os, sys 
    22from ctypes import CDLL 
     3from django.contrib.gis.gdal.OGRError import OGRException 
    34 
    45if os.name == 'nt': 
    5     # Windows NT library 
     6    # Windows NT shared library 
    67    lib_name = 'libgdal-1.dll' 
    78elif os.name == 'posix': 
     
    1112        lib_name = 'libgdal.so' 
    1213    elif platform == 'Darwin': 
    13         # Mac OSX Shared Library 
     14        # Mac OSX shared library 
    1415        lib_name = 'libgdal.dylib' 
    1516    else: 
    16         raise GDALException, 'Unknown POSIX platform "%s"' % platform 
     17        raise OGRException, 'Unknown POSIX platform "%s"' % platform 
    1718else: 
    18     raise GDALException, 'Unsupported OS "%s"' % os.name 
     19    raise OGRException, 'Unsupported OS "%s"' % os.name 
    1920 
    20 # The GDAL C library 
     21# This loads the GDAL/OGR C library 
    2122lgdal = CDLL(lib_name) 
    2223                                                                             
  • django/branches/gis/django/contrib/gis/gdal/OGRGeometry.py

    r5397 r5478  
    11# types & ctypes 
    2 from types import StringType 
    3 from ctypes import \ 
    4      byref, string_at, create_string_buffer, POINTER, \ 
    5      c_char_p, c_double, c_int, c_void_p 
     2from types import IntType, StringType 
     3from ctypes import byref, string_at, c_char_p, c_double, c_int, c_void_p 
    64 
    75# Getting the GDAL C library and error checking facilities 
     
    97from django.contrib.gis.gdal.OGRError import check_err, OGRException 
    108from django.contrib.gis.gdal.SpatialReference import SpatialReference, CoordTransform 
     9 
     10""" 
     11  The OGRGeometry is a wrapper for using the OGR Geometry class 
     12    (see http://www.gdal.org/ogr/classOGRGeometry.html).  OGRGeometry 
     13    may be instantiated when reading geometries from OGR Data Sources 
     14    (e.g. SHP files), or when given OGC WKT (a string). 
     15 
     16  While the 'full' API is not present yet, the API is "pythonic" unlike 
     17    the traditional and "next-generation" OGR Python bindings.  One major 
     18    advantage OGR Geometries have over their GEOS counterparts is support 
     19    for spatial reference systems and their transformation. 
     20 
     21  Example: 
     22    >>> from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, SpatialReference 
     23    >>> wkt1, wkt2 = 'POINT(-90 30)', 'POLYGON((0 0, 5 0, 5 5, 0 5)' 
     24    >>> pnt = OGRGeometry(wkt1) 
     25    >>> print pnt 
     26    POINT (-90 30) 
     27    >>> mpnt = OGRGeometry(OGRGeomType('MultiPoint'), SpatialReference('WGS84')) 
     28    >>> mpnt.add(wkt1) 
     29    >>> mpnt.add(wkt1) 
     30    >>> print mpnt 
     31    MULTIPOINT (-90 30,-90 30) 
     32    >>> print mpnt.srs.name 
     33    WGS 84 
     34    >>> print mpnt.srs.proj 
     35    +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs 
     36    >>> mpnt.transform_to(SpatialReference('NAD27')) 
     37    >>> print mpnt.proj 
     38    +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs 
     39    >>> print mpnt 
     40    MULTIPOINT (-89.999930378602485 29.999797886557641,-89.999930378602485 29.999797886557641) 
     41     
     42  The OGRGeomType class is to make it easy to specify an OGR geometry type: 
     43    >>> from django.contrib.gis.gdal import OGRGeomType 
     44    >>> gt1 = OGRGeomType(3) # Using an integer for the type 
     45    >>> gt2 = OGRGeomType('Polygon') # Using a string 
     46    >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive 
     47    >>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects 
     48    True 
     49""" 
    1150 
    1251# For more information, see the OGR C API source code: 
     
    3069 
    3170    # Ordered array of acceptable strings and their corresponding OGRwkbGeometryType 
    32     __ogr_str = ['Unknown', 'Point', 'LineString', 'Polygon', 'MultiPoint', 
     71    __ogr_str = ['Point', 'LineString', 'Polygon', 'MultiPoint', 
    3372                 'MultiLineString', 'MultiPolygon', 'GeometryCollection', 
    34                  'None', 'LinearRing'] 
    35     __ogr_int = [0, 1, 2, 3, 4, 5, 6, 7, 100, 101] 
     73                 'LinearRing'] 
     74    __ogr_int = [1, 2, 3, 4, 5, 6, 7, 101] 
    3675 
    3776    def __init__(self, input): 
     
    4180        elif isinstance(input, StringType): 
    4281            idx = self._has_str(self.__ogr_str, input) 
    43             if not idx
     82            if idx == None
    4483                raise OGRException, 'Invalid OGR String Type "%s"' % input 
    4584            self._index = idx 
     
    62101        elif isinstance(other, StringType): 
    63102            idx = self._has_str(self.__ogr_str, other) 
    64             if idx: return self._index == idx 
     103            if not (idx == None): return self._index == idx 
    65104            return False 
    66105        elif isinstance(other, int): 
     
    71110 
    72111    def _has_str(self, arr, s): 
    73         slow = s.lower() 
     112        "Case-insensitive search of the string array for the given pattern." 
     113        s_low = s.lower() 
    74114        for i in xrange(len(arr)): 
    75             if slow == arr[i].lower(): return i 
     115            if s_low == arr[i].lower(): return i 
    76116        return None 
    77117 
     
    100140 
    101141        if isinstance(input, StringType): 
     142            # Getting the spatial reference 
     143            self._init_srs(srs) 
     144 
    102145            # First, trying the input as WKT 
    103146            buf = c_char_p(input) 
    104147            g = c_void_p() 
    105148 
    106             # Getting the spatial  
    107             if not isinstance(srs, SpatialReference): 
    108                 s = SpatialReference() # creating an empty spatial reference 
    109             else: 
    110                 s = srs.clone() # cloning the given spatial reference 
    111  
    112149            try: 
    113                 check_err(lgdal.OGR_G_CreateFromWkt(byref(buf), s._srs, byref(g))) 
     150                check_err(lgdal.OGR_G_CreateFromWkt(byref(buf), self._s._srs, byref(g))) 
    114151            except OGRException, msg: 
    115152                try: 
     
    119156                    raise OGRException, 'Could not initialize on WKT "%s"' % input 
    120157        elif isinstance(input, OGRGeomType): 
     158            self._init_srs(srs) 
    121159            g = lgdal.OGR_G_CreateGeometry(input.num) 
    122         elif isinstance(input, int): 
     160            lgdal.OGR_G_AssignSpatialReference(g, self._s._srs) 
     161        elif isinstance(input, IntType): 
    123162            # OGR Pointer (integer) was the input 
    124163            g = input 
     
    134173        self.__class__ = GEO_CLASSES[self.geom_type.num] 
    135174 
     175    def _init_srs(self, srs): 
     176        # Getting the spatial 
     177        if not isinstance(srs, SpatialReference): 
     178            self._s = SpatialReference() # creating an empty spatial reference 
     179        else: 
     180            self._s = srs.clone() # cloning the given spatial reference 
     181 
     182    def __add__(self, other): 
     183        "Returns the union of the two geometries." 
     184        return self.union(other) 
     185 
    136186    def __del__(self): 
    137187        "Deletes this Geometry." 
     
    140190    def __eq__(self, other): 
    141191        "Is this Geometry equal to the other?" 
    142         return lgdal.OGR_G_Equals(self._g, other._g
     192        return self.equals(other
    143193 
    144194    def __str__(self): 
     
    164214    @property 
    165215    def point_count(self): 
    166         "The number of Points in this Geometry." 
     216        "Returns the number of Points in this Geometry." 
    167217        return lgdal.OGR_G_GetPointCount(self._g) 
     218 
     219    @property 
     220    def num_coords(self): 
     221        "Returns the number of Points in this Geometry." 
     222        return self.point_count 
    168223 
    169224    @property 
     
    188243        check_err(lgdal.OGR_G_ExportToWkt(self._g, byref(buf))) 
    189244        return string_at(buf) 
     245 
     246    @property 
     247    def area(self): 
     248        "Returns the area for a LinearRing, Polygon, or MultiPolygon; 0 otherwise." 
     249        a = lgdal.OGR_G_GetArea(self._g) 
     250        return a.value 
    190251     
    191252    #### Geometry Methods #### 
     
    194255        return OGRGeometry(lgdal.OGR_G_Clone(self._g)) 
    195256 
     257    def close_rings(self): 
     258        """If there are any rings within this geometry that have not been 
     259        closed, this routine will do so by adding the starting point at the 
     260        end.""" 
     261        # Closing the open rings. 
     262        lgdal.OGR_G_CloseRings(self._g) 
     263        # This "fixes" a GDAL bug. See http://trac.osgeo.org/gdal/ticket/1673 
     264        foo = self.wkt 
     265 
    196266    def transform(self, coord_trans): 
    197267        "Transforms this Geometry with the given CoordTransform object." 
     
    205275            raise OGRException, 'SpatialReference object required for transform_to.' 
    206276        check_err(lgdal.OGR_G_TransformTo(self._g, srs._srs)) 
     277 
     278    #### Topology Methods #### 
     279    def _topology(self, topo_func, other): 
     280        """A generalized function for topology operations, takes a GDAL function and 
     281        the other geometry to perform the operation on.""" 
     282        if not isinstance(other, OGRGeometry): 
     283            raise OGRException, 'Must use another OGRGeometry object for topology operations!' 
     284 
     285        # Calling the passed-in topology function with the other geometry 
     286        status = topo_func(self._g, other._g) 
     287 
     288        # Returning based on the status code (an integer) 
     289        if status: return True 
     290        else: return False 
     291 
     292    def intersects(self, other): 
     293        "Returns True if this geometry intersects with the other." 
     294        return self._topology(lgdal.OGR_G_Intersects, other) 
     295     
     296    def equals(self, other): 
     297        "Returns True if this geometry is equivalent to the other." 
     298        return self._topology(lgdal.OGR_G_Equals, other) 
     299 
     300    def disjoint(self, other): 
     301        "Returns True if this geometry and the other are spatially disjoint." 
     302        return self._topology(lgdal.OGR_G_Disjoint, other) 
     303 
     304    def touches(self, other): 
     305        "Returns True if this geometry touches the other." 
     306        return self._topology(lgdal.OGR_G_Touches, other) 
     307 
     308    def crosses(self, other): 
     309        "Returns True if this geometry crosses the other." 
     310        return self._topology(lgdal.OGR_G_Crosses, other) 
     311 
     312    def within(self, other): 
     313        "Returns True if this geometry is within the other." 
     314        return self._topology(lgdal.OGR_G_Within, other) 
     315 
     316    def contains(self, other): 
     317        "Returns True if this geometry contains the other." 
     318        return self._topology(lgdal.OGR_G_Contains, other) 
     319 
     320    def overlaps(self, other): 
     321        "Returns True if this geometry overlaps the other." 
     322        return self._topology(lgdal.OGR_G_Overlaps, other) 
     323 
     324    #### Geometry-generation Methods #### 
     325    def _geomgen(self, gen_func, other): 
     326        if not isinstance(other, OGRGeometry): 
     327            raise OGRException, 'Must use another OGRGeometry object for geometry-generating operations!' 
     328        return OGRGeometry(gen_func(self._g, other._g)) 
     329 
     330    def union(self, other): 
     331        """Returns a new geometry consisting of the region which is the union of 
     332        this geometry and the other.""" 
     333        return self._geomgen(lgdal.OGR_G_Union, other) 
     334         
     335    def difference(self, other): 
     336        """Returns a new geometry consisting of the region which is the difference 
     337        of this geometry and the other.""" 
     338        return self._geomgen(lgdal.OGR_G_Difference, other) 
     339 
     340    def sym_difference(self, other): 
     341        """Returns a new geometry which is the symmetric difference of this 
     342        geometry and the other.""" 
     343        return self._geomgen(lgdal.OGR_G_SymmetricDifference, other) 
     344 
     345    def intersection(self, other): 
     346        """Returns a new geometry consisting of the region of intersection of this 
     347        geometry and the other.""" 
     348        return self._geomgen(lgdal.OGR_G_Intersection, other) 
    207349 
    208350# The subclasses for OGR Geometry. 
     
    299441        return tuple(self.__getitem__(i).tuple for i in xrange(self.geom_count)) 
    300442 
     443    @property 
     444    def point_count(self): 
     445        "The number of Points in this Polygon." 
     446        # Summing up the number of points in each ring of the Polygon. 
     447        return sum([self.__getitem__(i).point_count for i in xrange(self.geom_count)]) 
     448 
     449    @property 
     450    def centroid(self): 
     451        "Returns the centroid (a Point) of this Polygon." 
     452        # The centroid is a Point, create a geometry for this. 
     453        p = OGRGeometry(OGRGeomType('Point')) 
     454        check_err(lgdal.OGR_G_Centroid(self._g, p._g)) 
     455        return p 
     456 
    301457# Geometry Collection base class. 
    302458class GeometryCollection(OGRGeometry): 
     
    321477    def add(self, geom): 
    322478        "Add the geometry to this Geometry Collection." 
    323         if not isinstance(geom, OGRGeometry): 
     479        if isinstance(geom, OGRGeometry): 
     480            ptr = geom._g 
     481        elif isinstance(geom, StringType): 
     482            tmp = OGRGeometry(geom) 
     483            ptr = tmp._g 
     484        else: 
    324485            raise OGRException, 'Must add an OGRGeometry.' 
    325         lgdal.OGR_G_AddGeometry(self._g, geom._g) 
     486        lgdal.OGR_G_AddGeometry(self._g, ptr) 
     487 
     488    @property 
     489    def point_count(self): 
     490        "The number of Points in this Geometry Collection." 
     491        # Summing up the number of points in each geometry in this collection 
     492        return sum([self.__getitem__(i).point_count for i in xrange(self.geom_count)]) 
     493 
     494    @property 
     495    def tuple(self): 
     496        "Returns a tuple representation of this Geometry Collection." 
     497        return tuple(self.__getitem__(i).tuple for i in xrange(self.geom_count))  
    326498 
    327499# Multiple Geometry types. 
  • django/branches/gis/django/contrib/gis/gdal/SpatialReference.py

    r5397 r5478  
    1111# Getting the error checking routine and exceptions 
    1212from django.contrib.gis.gdal.OGRError import check_err, OGRException, SRSException 
     13 
     14""" 
     15  The Spatial Reference class, represensents OGR Spatial Reference objects. 
     16 
     17  Example: 
     18  >>> from django.contrib.gis.gdal import SpatialReference 
     19  >>> srs = SpatialReference('WGS84') 
     20  >>> print srs 
     21  GEOGCS["WGS 84", 
     22      DATUM["WGS_1984", 
     23          SPHEROID["WGS 84",6378137,298.257223563, 
     24              AUTHORITY["EPSG","7030"]], 
     25          TOWGS84[0,0,0,0,0,0,0], 
     26          AUTHORITY["EPSG","6326"]], 
     27      PRIMEM["Greenwich",0, 
     28          AUTHORITY["EPSG","8901"]], 
     29      UNIT["degree",0.01745329251994328, 
     30          AUTHORITY["EPSG","9122"]], 
     31      AUTHORITY["EPSG","4326"]] 
     32  >>> print srs.proj 
     33  +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs 
     34  >>> print srs.ellipsoid 
     35  (6378137.0, 6356752.3142451793, 298.25722356300003) 
     36  >>> print srs.projected, srs.geographic 
     37  False True 
     38  >>> srs.import_epsg(32140) 
     39  >>> print srs.name 
     40  NAD83 / Texas South Central 
     41""" 
     42 
    1343 
    1444#### ctypes function prototypes #### 
     
    184214        return self._angular_units 
    185215 
    186     #### Spheroid/Ellipsis Properties #### 
     216    #### Spheroid/Ellipsoid Properties #### 
     217    @property 
     218    def ellipsoid(self): 
     219        """Returns a tuple of the ellipsoid parameters: 
     220        (semimajor axis, semiminor axis, and inverse flattening).""" 
     221        return (self.semi_major, self.semi_minor, self.inverse_flattening) 
     222 
    187223    @property 
    188224    def semi_major(self): 
     
    267303        check_err(lgdal.OSRExportToProj4(self._srs, byref(w))) 
    268304        return string_at(w) 
     305 
     306    def proj4(self): 
     307        "Alias for proj()." 
     308        return self.proj 
    269309 
    270310    @property 
  • django/branches/gis/django/contrib/gis/tests/geometries.py

    r5395 r5478  
    5454# Polygons 
    5555polygons = (TestGeom('POLYGON ((0 0, 0 100, 100 100, 100 0, 0 0), (10 10, 10 90, 90 90, 90 10, 10 10))', 
    56                      n_i=1, ext_ring_cs=((0, 0), (0, 100), (100, 100), (100, 0), (0, 0)), pc=10
     56                     n_i=1, ext_ring_cs=((0, 0), (0, 100), (100, 100), (100, 0), (0, 0)), n_p=10, area=3600.0, centroid=(50., 50.)
    5757                     ), 
    5858            TestGeom('POLYGON ((0 0, 0 100, 100 100, 100 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10), (80 80, 80 90, 90 90, 90 80, 80 80))', 
    59                      n_i=2, ext_ring_cs=((0, 0), (0, 100), (100, 100), (100, 0), (0, 0)), pc=15
     59                     n_i=2, ext_ring_cs=((0, 0), (0, 100), (100, 100), (100, 0), (0, 0)), n_p=15, area=9800.0, centroid=(50., 50.)
    6060                     ), 
    6161            TestGeom('POLYGON ((0 0, 0 100, 100 100, 100 0, 0 0))', 
    62                      n_i=0, ext_ring_cs=((0, 0), (0, 100), (100, 100), (100, 0), (0, 0)), pc=10
     62                     n_i=0, ext_ring_cs=((0, 0), (0, 100), (100, 100), (100, 0), (0, 0)), n_p=5, area=10000.0, centroid=(50., 50.)
    6363                     ), 
    6464            TestGeom('POLYGON ((-95.3848703124799471 29.7056021479768511, -95.3851905195191847 29.7046588196500281, -95.3859356966379011 29.7025053545605502, -95.3860723000647539 29.7020963367038391, -95.3871517697222089 29.6989779021280995, -95.3865578518265522 29.6990856888057202, -95.3862634205175226 29.6999471753441782, -95.3861991779541967 29.6999591988978615, -95.3856773799358137 29.6998323107113578, -95.3856209915427229 29.6998005235473741, -95.3855833545501639 29.6996619391729801, -95.3855776331865002 29.6996232659570047, -95.3850162731712885 29.6997236706530536, -95.3831047357410284 29.7000847603095082, -95.3829800724914776 29.7000676365023502, -95.3828084594470909 29.6999969684031200, -95.3828131504821499 29.6999090511531065, -95.3828022942979601 29.6998152117366025, -95.3827893930918833 29.6997790953076759, -95.3825174668099862 29.6998267772748825, -95.3823521544804862 29.7000451723151606, -95.3820491918785223 29.6999682034582335, -95.3817932841505893 29.6999640407204772, -95.3815438924600443 29.7005983712500630, -95.3807812390843424 29.7007538492921590, -95.3778578936435935 29.7012966201172048, -95.3770817300034679 29.7010555145969093, -95.3772763716395957 29.7004995005932031, -95.3769891024414420 29.7005797730360186, -95.3759855007185990 29.7007754783987821, -95.3759516423090474 29.7007305400669388, -95.3765252155960042 29.6989549173240874, -95.3766842746727832 29.6985134987163164, -95.3768510987262914 29.6980530300744938, -95.3769198676258014 29.6977137204527573, -95.3769616670751930 29.6973351617272172, -95.3770309229297766 29.6969821084304186, -95.3772352596880637 29.6959751305871613, -95.3776232419333354 29.6945439060847463, -95.3776849628727064 29.6943364710766069, -95.3779699491714723 29.6926548349458947, -95.3781945479573494 29.6920088336742545, -95.3785807118394189 29.6908279316076005, -95.3787441368896651 29.6908846275832197, -95.3787903214163890 29.6907152912461640, -95.3791765069353659 29.6893335376821526, -95.3794935959513026 29.6884781789101595, -95.3796592071232112 29.6880066681407619, -95.3799788182090111 29.6873687353035081, -95.3801545516183893 29.6868782380716993, -95.3801258908302145 29.6867756621337762, -95.3801104284899566 29.6867229678809572, -95.3803803523746154 29.6863753372986459, -95.3821028558287622 29.6837392961470421, -95.3827289584682205 29.6828097375216160, -95.3827494698109035 29.6790739156259278, -95.3826022014838486 29.6776502228345507, -95.3825047356438063 29.6765773006280753, -95.3823473035336917 29.6750405250369127, -95.3824540163482055 29.6750076408228587, -95.3838984230304305 29.6745679207378679, -95.3916547074937426 29.6722459226508377, -95.3926154662749468 29.6719609085105489, -95.3967246645118081 29.6707316485589736, -95.3974588054406780 29.6705065336410989, -95.3978523748756828 29.6703795547846845, -95.3988598162279970 29.6700874981900853, -95.3995628600665952 29.6698505300412414, -95.4134721665944170 29.6656841279906232, -95.4143262068232616 29.6654291174019278, -95.4159685142480214 29.6649750989232288, -95.4180067396277565 29.6643253024318021, -95.4185886692196590 29.6641482768691063, -95.4234155309609662 29.6626925393704788, -95.4287785503196346 29.6611023620959706, -95.4310287312749352 29.6604222580752648, -95.4320295629628959 29.6603361318136720, -95.4332899683975739 29.6600560661713608, -95.4342675748811047 29.6598454934599900, -95.4343110414310871 29.6598411486215490, -95.4345576779282538 29.6598147020668499, -95.4348823041721630 29.6597875803673112, -95.4352827715209457 29.6597762346946681, -95.4355290431309982 29.6597827926562374, -95.4359197997999331 29.6598014511782715, -95.4361907884752156 29.6598444333523368, -95.4364608955807228 29.6598901433108217, -95.4367250147512323 29.6599494499910712, -95.4364898759758091 29.6601880616540186, -95.4354501111810691 29.6616378572201107, -95.4381459623171224 29.6631265631655126, -95.4367852490863129 29.6642266600024023, -95.4370040894557263 29.6643425389568769, -95.4367078350812648 29.6645492592343238, -95.4366081749871285 29.6646291473027297, -95.4358539359938192 29.6652308742342932, -95.4350327668927889 29.6658995989314462, -95.4350580905272921 29.6678812477895271, -95.4349710541447536 29.6680054925936965, -95.4349500440473548 29.6671410080890006, -95.4341492724148850 29.6678790545191688, -95.4340248868274728 29.6680353198492135, -95.4333227845797438 29.6689245624945990, -95.4331325652123326 29.6691616138940901, -95.4321314741096955 29.6704473333237253, -95.4320435792664341 29.6702578985411982, -95.4320147929883547 29.6701800936425109, -95.4319764538662980 29.6683246590817085, -95.4317490976340679 29.6684974372577166, -95.4305958185342718 29.6694049049170374, -95.4296600735653016 29.6701723430938493, -95.4284928989940937 29.6710931793380972, -95.4274630532378580 29.6719378813640091, -95.4273056811974811 29.6720684984625791, -95.4260554084574864 29.6730668861566969, -95.4253558063699643 29.6736342467365724, -95.4249278826026028 29.6739557343648919, -95.4248648873821423 29.6745400910786152, -95.4260016131471929 29.6750987014005858, -95.4258567183010911 29.6753452063069929, -95.4260238081486847 29.6754322077221353, -95.4258707374502393 29.6756647377294307, -95.4257951755816691 29.6756407098663360, -95.4257701599566985 29.6761077719536068, -95.4257726684792260 29.6761711204603955, -95.4257980187195614 29.6770219651929423, -95.4252712669032519 29.6770161558853758, -95.4249234392992065 29.6770068683962300, -95.4249574272905789 29.6779707498635759, -95.4244725881033702 29.6779825646764159, -95.4222269476429545 29.6780711474441716, -95.4223032371999267 29.6796029391538809, -95.4239133706588945 29.6795331493690355, -95.4224579084327331 29.6813706893847780, -95.4224290108823965 29.6821953228763924, -95.4230916478977349 29.6822130268724109, -95.4222928279595521 29.6832041816675343, -95.4228763710016352 29.6832087677714505, -95.4223401691637179 29.6838987872753748, -95.4211655906087088 29.6838784024852984, -95.4201984153205558 29.6851319258758082, -95.4206156387716362 29.6851623398125319, -95.4213438084897660 29.6851763011334739, -95.4212071118618752 29.6853679931624974, -95.4202651399651245 29.6865313962980508, -95.4172061157659783 29.6865816431043932, -95.4182217951255183 29.6872251197301544, -95.4178664826439160 29.6876750901471631, -95.4180678442928780 29.6877960336377207, -95.4188763472917572 29.6882826379510938, -95.4185374500596311 29.6887137897831934, -95.4182121713132290 29.6885097429738813, -95.4179857231741551 29.6888118367840086, -95.4183106010563620 29.6890048676118212, -95.4179489865331334 29.6894546700979056, -95.4175581746284820 29.6892323606815438, -95.4173439957341571 29.6894990139807007, -95.4177411199311081 29.6897435034738422, -95.4175789200209721 29.6899207529979208, -95.4170598559864800 29.6896042165807508, -95.4166733682539814 29.6900891174451367, -95.4165941362704331 29.6900347214235047, -95.4163537218065301 29.6903529467753238, -95.4126843270708775 29.6881086357212780, -95.4126604121378392 29.6880942378803496, -95.4126672298953338 29.6885951670109982, -95.4126680884821923 29.6887052446594275, -95.4158080137241882 29.6906382377959339, -95.4152061403821961 29.6910871045531586, -95.4155842583188161 29.6917382915894308, -95.4157426793520358 29.6920726941677096, -95.4154520563662203 29.6922052332446427, -95.4151389936167078 29.6923261661269571, -95.4148649784384872 29.6924343866430256, -95.4144051352401590 29.6925623927348106, -95.4146792019416665 29.6926770338507744, -95.4148824479948985 29.6928117893696388, -95.4149851734360226 29.6929823719519774, -95.4140436551925291 29.6929626643100946, -95.4140465993023241 29.6926545917254892, -95.4137269186733334 29.6927395764256090, -95.4137372859685513 29.6935432485666624, -95.4135702836218655 29.6933186678088283, -95.4133925235973237 29.6930415229852152, -95.4133017035615580 29.6928685062036166, -95.4129588921634593 29.6929391128977862, -95.4125107395559695 29.6930481664661485, -95.4102647423187307 29.6935850183258019, -95.4081931340840157 29.6940907430947760, -95.4078783596459772 29.6941703429951609, -95.4049213975000043 29.6948723732981961, -95.4045944244127071 29.6949626434239207, -95.4045865139788134 29.6954109019001358, -95.4045953345484037 29.6956972800496963, -95.4038879332535146 29.6958296089365490, -95.4040366394459340 29.6964389004769842, -95.4032774779020798 29.6965643341263892, -95.4026066501239853 29.6966646227683881, -95.4024991226393837 29.6961389766619703, -95.4011781398631911 29.6963566063186377, -95.4011524097636112 29.6962596176762190, -95.4018184046368276 29.6961399466727336, -95.4016995838361908 29.6956442609415099, -95.4007100753964608 29.6958900524002978, -95.4008032469935188 29.6962639900781404, -95.3995660267125487 29.6965636449370329, -95.3996140564775601 29.6967877962763644, -95.3996364430014410 29.6968901984825280, -95.3984003269631842 29.6968679634805746, -95.3981442026887265 29.6983660679730335, -95.3980178461957706 29.6990890276252415, -95.3977097967130163 29.7008526152273049, -95.3962347157626027 29.7009697553607630, -95.3951949050136250 29.7004740386619019, -95.3957564950617183 29.6990281830553187, -95.3965927101519924 29.6968771129030706, -95.3957496517238184 29.6970800358387095, -95.3957720559467361 29.6972264611230727, -95.3957391586571788 29.6973548894558732, -95.3956286413405365 29.6974949857280883, -95.3955111053256957 29.6975661086270186, -95.3953215342724121 29.6976022763384790, -95.3951795558443365 29.6975846977491038, -95.3950369632041060 29.6975175779330200, -95.3949401089966500 29.6974269267953304, -95.3948740281415581 29.6972903308506346, -95.3946650813866910 29.6973397326847923, -95.3947654059391112 29.6974882560192022, -95.3949627316619768 29.6980355864961858, -95.3933200807862249 29.6984590863712796, -95.3932606497523494 29.6984464798710839, -95.3932983699113350 29.6983154306484352, -95.3933058014696655 29.6982165816983610, -95.3932946347785133 29.6981089778195759, -95.3931780601756287 29.6977068906794841, -95.3929928222970602 29.6977541771878180, -95.3930873169846478 29.6980676264932946, -95.3932743746374570 29.6981249406449663, -95.3929512584706316 29.6989526513922222, -95.3919850280655197 29.7014358632108646, -95.3918950918929056 29.7014169320765724, -95.3916928317890296 29.7019232352846423, -95.3915424614970959 29.7022988712928289, -95.3901530441668939 29.7058519502930061, -95.3899656322116698 29.7059156823562418, -95.3897628748670883 29.7059900058266777, -95.3896062677805787 29.7060738276384946, -95.3893941800512266 29.7061891695242046, -95.3892150365492455 29.7062641292949436, -95.3890502563035199 29.7063339729630940, -95.3888717930715586 29.7063896908080736, -95.3886925428988945 29.7064453871994978, -95.3885376849411983 29.7064797304524149, -95.3883284158984139 29.7065153575050189, -95.3881046767627794 29.7065368368267357, -95.3878809284696132 29.7065363048447537, -95.3876046356120924 29.7065288525102424, -95.3873060894974714 29.7064822806001452, -95.3869851943158409 29.7063993367575350, -95.3865967896568065 29.7062870572919202, -95.3861785624983156 29.7061492099008184, -95.3857375009733488 29.7059887337478798, -95.3854573290902152 29.7058683664514618, -95.3848703124799471 29.7056021479768511))', 
    65                      n_i=0, ext_ring_cs=False 
     65                     n_i=0, ext_ring_cs=False, n_p=264, area=0.00129917360654, centroid=(-95.403569179437341, 29.681772571690402), 
    6666                     ), 
    6767            ) 
    6868 
    6969# MultiPolygons 
    70 multipolygons = (TestGeom('MULTIPOLYGON (((100 20, 180 20, 180 100, 100 100, 100 20)), ((20 100, 100 100, 100 180, 20 180, 20 100)), ((100 180, 180 180, 180 260, 100 260, 100 180)), ((180 100, 260 100, 260 180, 180 180, 180 100)))', valid=True, n_p=4), 
     70multipolygons = (TestGeom('MULTIPOLYGON (((100 20, 180 20, 180 100, 100 100, 100 20)), ((20 100, 100 100, 100 180, 20 180, 20 100)), ((100 180, 180 180, 180 260, 100 260, 100 180)), ((180 100, 260 100, 260 180, 180 180, 180 100)))', valid=True, num_geom=4, n_p=20), 
    7171                 TestGeom('MULTIPOLYGON (((60 300, 320 220, 260 60, 60 100, 60 300)), ((60 300, 320 220, 260 60, 60 100, 60 300)))', valid=False), 
    72                  TestGeom('MULTIPOLYGON (((180 60, 240 160, 300 60, 180 60)), ((80 80, 180 60, 160 140, 240 160, 360 140, 300 60, 420 100, 320 280, 120 260, 80 80)))', valid=True, n_p=2), 
     72                 TestGeom('MULTIPOLYGON (((180 60, 240 160, 300 60, 180 60)), ((80 80, 180 60, 160 140, 240 160, 360 140, 300 60, 420 100, 320 280, 120 260, 80 80)))', valid=True, num_geom=2, n_p=14), 
    7373                 ) 
    74  
    7574 
    7675# Points 
     
    8483 
    8584# MultiPoints 
    86 multipoints = (TestGeom('MULTIPOINT(10 10, 20 20 )', points=((10., 10.), (20., 20.)), centroid=(15., 15.)), 
     85multipoints = (TestGeom('MULTIPOINT(10 10, 20 20 )', n_p=2, points=((10., 10.), (20., 20.)), centroid=(15., 15.)), 
    8786               TestGeom('MULTIPOINT(10 10, 20 20, 10 20, 20 10)', 
    88                         points=((10., 10.), (20., 20.), (10., 20.), (20., 10.)), 
     87                        n_p=4, points=((10., 10.), (20., 20.), (10., 20.), (20., 10.)), 
    8988                        centroid=(15., 15.)), 
    9089               ) 
    9190 
    9291# LineStrings 
    93 linestrings = (TestGeom('LINESTRING (60 180, 120 100, 180 180)', centroid=(120, 140)), 
    94 #               TestGeom('LINESTRING (80 0, 80 120, 120 120, 120 0))', centroid=(100, 69)), 
    95                TestGeom('LINESTRING (0 0, 5 5, 10 5, 10 10)', centroid=(6.1611652351681556, 4.6966991411008934)), 
     92linestrings = (TestGeom('LINESTRING (60 180, 120 100, 180 180)', n_p=3, centroid=(120, 140), tup=((60, 180), (120, 100), (180, 180))), 
     93               TestGeom('LINESTRING (0 0, 5 5, 10 5, 10 10)', n_p=4, centroid=(6.1611652351681556, 4.6966991411008934), tup=((0, 0), (5, 5), (10, 5), (10, 10)),) 
    9694               ) 
    9795 
    9896# MultiLineStrings 
    99 multilinestrings = (TestGeom('MULTILINESTRING ((0 0, 0 100), (100 0, 100 100))', centroid=(50, 50)), 
    100 #                    TestGeom('MULTILINESTRING ((0 0, 0 200, 200 200, 200 0, 0 0), (60 180, 20 180, 20 140, 60 140, 60 180))', centroid=(90, 100)), 
     97multilinestrings = (TestGeom('MULTILINESTRING ((0 0, 0 100), (100 0, 100 100))', n_p=4, centroid=(50, 50), tup=(((0, 0), (0, 100)), ((100, 0), (100, 100)))), 
    10198                    TestGeom('MULTILINESTRING ((20 20, 60 60), (20 -20, 60 -60), (-20 -20, -60 -60), (-20 20, -60 60), (-80 0, 0 80, 80 0, 0 -80, -80 0), (-40 20, -40 -20), (-20 40, 20 40), (40 20, 40 -20), (20 -40, -20 -40))', 
    102                              centroid=(0, 0)), 
     99                             n_p=21, centroid=(0, 0), tup=(((20., 20.), (60., 60.)), ((20., -20.), (60., -60.)), ((-20., -20.), (-60., -60.)), ((-20., 20.), (-60., 60.)), ((-80., 0.), (0., 80.), (80., 0.), (0., -80.), (-80., 0.)), ((-40., 20.), (-40., -20.)), ((-20., 40.), (20., 40.)), ((40., 20.), (40., -20.)), ((20., -40.), (-20., -40.)))) 
    103100                    ) 
    104101 
  • django/branches/gis/django/contrib/gis/tests/__init__.py

    r5397 r5478  
    11from unittest import TestSuite, makeSuite, TextTestRunner 
    2 import test_geos, test_gdal_ds, test_gdal_srs, test_gdal_geom, test_spatialrefsys 
     2import test_geos, test_gdal_ds, test_gdal_driver, test_gdal_srs, test_gdal_geom, test_spatialrefsys 
    33 
    44def suite(): 
     
    66    s.addTest(test_geos.suite()) 
    77    s.addTest(test_gdal_ds.suite()) 
     8    s.addTest(test_gdal_driver.suite()) 
    89    s.addTest(test_gdal_srs.suite()) 
    910    s.addTest(test_gdal_geom.suite()) 
     
    1112    return s 
    1213 
    13 def run(verbosity=2): 
     14def run(verbosity=1): 
    1415    TextTestRunner(verbosity=verbosity).run(suite()) 
  • django/branches/gis/django/contrib/gis/tests/test_gdal_ds.py

    r5397 r5478  
    4141 
    4242            # Making sure the driver name matches up 
    43             self.assertEqual('ESRI Shapefile', ds.driver
     43            self.assertEqual('ESRI Shapefile', str(ds.driver)
    4444 
    4545            # Making sure indexing works 
  • django/branches/gis/django/contrib/gis/tests/test_gdal_geom.py

    r5397 r5478  
    1111        # OGRGeomType should initialize on all these inputs. 
    1212        try: 
    13             g = OGRGeomType(0) 
    1413            g = OGRGeomType(1) 
    1514            g = OGRGeomType(7) 
    1615            g = OGRGeomType('point') 
    1716            g = OGRGeomType('GeometrycollectioN') 
     17            g = OGRGeomType('LINearrING') 
    1818        except: 
    1919            self.fail('Could not create an OGRGeomType object!') 
     
    4343            if not hasattr(p, 'z'): # No 3D 
    4444                pnt = OGRGeometry(p.wkt) 
    45                 self.assertEqual(pnt.geom_type, 1) 
     45                self.assertEqual(1, pnt.geom_type) 
     46                self.assertEqual('POINT', pnt.geom_name) 
    4647                self.assertEqual(p.x, pnt.x) 
    4748                self.assertEqual(p.y, pnt.y) 
    4849                self.assertEqual((p.x, p.y), pnt.tuple) 
    4950 
    50     def test03_polygons(self): 
     51    def test03_multipoints(self): 
     52        "Testing MultiPoint objects." 
     53 
     54        for mp in multipoints: 
     55            mgeom1 = OGRGeometry(mp.wkt) # First one from WKT 
     56            self.assertEqual(4, mgeom1.geom_type) 
     57            self.assertEqual('MULTIPOINT', mgeom1.geom_name) 
     58            mgeom2 = OGRGeometry('MULTIPOINT') # Creating empty multipoint 
     59            mgeom3 = OGRGeometry('MULTIPOINT') 
     60            for g in mgeom1: 
     61                mgeom2.add(g) # adding each point from the multipoints 
     62                mgeom3.add(g.wkt) # should take WKT as well 
     63            self.assertEqual(mgeom1, mgeom2) # they should equal 
     64            self.assertEqual(mgeom1, mgeom3) 
     65            self.assertEqual(mp.points, mgeom2.tuple) 
     66            self.assertEqual(mp.n_p, mgeom2.point_count) 
     67                                                                             
     68    def test04_linestring(self): 
     69        "Testing LineString objects." 
     70        for ls in linestrings: 
     71            linestr = OGRGeometry(ls.wkt) 
     72            self.assertEqual(2, linestr.geom_type) 
     73            self.assertEqual('LINESTRING', linestr.geom_name) 
     74            self.assertEqual(ls.n_p, linestr.point_count) 
     75            self.assertEqual(ls.tup, linestr.tuple) 
     76 
     77    def test05_multilinestring(self): 
     78        "Testing MultiLineString objects." 
     79        for mls in multilinestrings: 
     80            mlinestr = OGRGeometry(mls.wkt) 
     81            self.assertEqual(5, mlinestr.geom_type) 
     82            self.assertEqual('MULTILINESTRING', mlinestr.geom_name) 
     83            self.assertEqual(mls.n_p, mlinestr.point_count) 
     84            self.assertEqual(mls.tup, mlinestr.tuple) 
     85 
     86    def test06_polygons(self): 
    5187        "Testing Polygon objects." 
    5288        for p in polygons: 
    5389            poly = OGRGeometry(p.wkt) 
     90            self.assertEqual(3, poly.geom_type) 
     91            self.assertEqual('POLYGON', poly.geom_name) 
     92            self.assertEqual(p.n_p, poly.point_count) 
    5493            first = True 
    5594            for r in poly: 
     
    61100                    self.assertEqual(p.ext_ring_cs, r.tuple) 
    62101 
    63     def test04_multipoints(self): 
    64         "Testing MultiPoint objects." 
     102    def test07_closepolygons(self): 
     103        "Testing closing Polygon objects." 
    65104 
    66         for mp in multipoints: 
    67             mgeom1 = OGRGeometry(mp.wkt) # First one from WKT 
    68             mgeom2 = OGRGeometry('MULTIPOINT') # Creating empty multipoint 
    69             for g in mgeom1: 
    70                 mgeom2.add(g) # adding each point from the multipoint 
    71             self.assertEqual(mgeom1, mgeom2) # they should equal 
    72      
     105        # Both rings in this geometry are not closed. 
     106        poly = OGRGeometry('POLYGON((0 0, 5 0, 5 5, 0 5), (1 1, 2 1, 2 2, 2 1))') 
     107        self.assertEqual(8, poly.point_count) 
     108        try: 
     109            c = poly.centroid 
     110        except OGRException: 
     111            # Should raise an OGR exception, rings are not closed 
     112            pass 
     113        else: 
     114            self.fail('Should have raised an OGRException!') 
     115 
     116        # Closing the rings 
     117        poly.close_rings() 
     118        self.assertEqual(10, poly.point_count) # Two closing points should've been added 
     119        self.assertEqual(OGRGeometry('POINT(2.5 2.5)'), poly.centroid) 
     120 
     121    def test08_multipolygons(self): 
     122        "Testing MultiPolygon objects." 
     123        for mp in multipolygons: 
     124            mpoly = OGRGeometry(mp.wkt) 
     125            self.assertEqual(6, mpoly.geom_type) 
     126            self.assertEqual('MULTIPOLYGON', mpoly.geom_name) 
     127            if mp.valid: 
     128                self.assertEqual(mp.n_p, mpoly.point_count) 
     129                self.assertEqual(mp.num_geom, len(mpoly)) 
     130 
    73131def suite(): 
    74132    s = unittest.TestSuite() 
  • django/branches/gis/django/contrib/gis/tests/test_geos.py

    r5474 r5478  
    116116 
    117117            if mp.valid: 
    118                 self.assertEqual(mp.n_p, mpoly.num_geom) 
    119                 self.assertEqual(mp.n_p, len(mpoly)) 
     118                self.assertEqual(mp.num_geom, mpoly.num_geom) 
     119                self.assertEqual(mp.n_p, mpoly.num_coords) 
     120