Django

Code

Changeset 5023

Show
Ignore:
Timestamp:
04/17/07 19:13:25 (2 years ago)
Author:
jbronn
Message:

gis: fixed bugs in GEOSCoordSeq (and added a test case). added preliminary support for Mac OSX compiled GEOS libraries.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/geos/GEOSGeometry.py

    r5008 r5023  
    3131from ctypes import \ 
    3232     CDLL, CFUNCTYPE, byref, string_at, create_string_buffer, \ 
    33      c_char_p, c_double, c_float, c_int, c_uint, c_size_t, c_ubyte 
     33     c_char_p, c_double, c_float, c_int, c_uint, c_size_t 
    3434import os, sys 
    3535 
     
    4444    (2) The PCL implementation is over 2K+ lines of C and would make 
    4545        PCL a requisite package for the GeoDjango application stack. 
    46     (3) Windows compatibility becomes substantially easier, and does not require the 
    47         additional compilation of PCL or GEOS and SWIG -- all that is needed is 
    48         a Win32 compiled GEOS C library (dll) in a location that Python can read 
    49         (e.g. C:\Python25). 
     46    (3) Windows and Mac compatibility becomes substantially easier, and does not 
     47        require the additional compilation of PCL or GEOS and SWIG -- all that 
     48        is needed is a Win32 or Mac compiled GEOS C library (dll or dylib) 
     49        in a location that Python can read (e.g. 'C:\Python25'). 
    5050 
    5151  In summary, I wanted to wrap GEOS in a more maintainable and portable way using 
     
    6666 
    6767# Setting the appropriate name for the GEOS-C library, depending on which 
    68 # platform we're running. 
     68# OS and POSIX platform we're running. 
    6969if os.name == 'nt': 
    7070    # Windows NT library 
    7171    lib_name = 'libgeos_c-1.dll' 
     72elif os.name == 'posix': 
     73    platform = os.uname()[0] # Using os.uname() 
     74    if platform == 'Linux': 
     75        # Linux shared library 
     76        lib_name = 'libgeos_c.so' 
     77    elif platform == 'Darwin': 
     78        # Mac OSX Shared Library (Thanks Matt!) 
     79        lib_name = 'libgeos_c.dylib' 
     80    else: 
     81        raise GEOSException, 'Unknown POSIX platform "%s"' % platform 
    7282else: 
    73     # Linux shared library 
    74     lib_name = 'libgeos_c.so' 
     83    raise GEOSException, 'Unsupported OS "%s"' % os.name 
    7584 
    7685# Getting the GEOS C library.  The C interface (CDLL) is used for 
     
    8089lgeos = CDLL(lib_name) 
    8190 
    82 # The notice and error handlers 
     91# The notice and error handler C function callback definitions. 
    8392#  Supposed to mimic the GEOS message handler (C below): 
    8493#  "typedef void (*GEOSMessageHandler)(const char *fmt, ...);" 
     
    9099ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p) 
    91100def error_h(fmt, list): 
     101    # TODO: Figure out why improper format code given w/some GEOS errors 
    92102    if not list: 
    93103        sys.stderr.write(fmt) 
     
    103113 
    104114class GEOSException: 
     115    "Exception class for any GEOS-related errors." 
    105116    def __init__(self, msg): 
    106117        self.msg = msg 
     
    290301            return None 
    291302        else: 
    292             return lgeos.GEOSGetSRID(self._g) 
     303            return s 
    293304 
    294305    def set_srid(self, srid): 
     
    409420 
    410421    def __len__(self): 
    411         return self.size 
     422        return int(self.size) 
    412423 
    413424    def __str__(self): 
    414425        "The string representation of the coordinate sequence." 
    415         rep = [] 
    416         for i in xrange(self.size): 
    417             rep.append(self.__getitem__(i)) 
    418         return str(tuple(rep)) 
     426        return str(self.tuple) 
    419427 
    420428    def _checkindex(self, index): 
     
    446454        if len(value) != n_args: 
    447455            raise GEOSException, 'Improper value given!' 
    448         self.setX(index, value
    449         self.setY(index, value
    450         if set_3d: self.setZ(index, value
     456        self.setX(index, value[0]
     457        self.setY(index, value[1]
     458        if set_3d: self.setZ(index, value[2]
    451459         
    452460    # Getting and setting the X coordinate for the given index. 
     
    461469        return self.getOrdinate(1, index) 
    462470 
    463     def setY(self, index): 
    464         self.setOrdinate(1, index
     471    def setY(self, index, value): 
     472        self.setOrdinate(1, index, value
    465473 
    466474    # Getting and setting the Z coordinate for the given index 
     
    468476        return self.getOrdinate(2, index) 
    469477 
    470     def setZ(self, index): 
    471         self.setOrdinate(2, index
     478    def setZ(self, index, value): 
     479        self.setOrdinate(2, index, value
    472480 
    473481    def getOrdinate(self, dimension, index): 
     
    489497    def setOrdinate(self, dimension, index, value): 
    490498        "Sets the value for the given dimension and index." 
    491         self._checkindex(idnex) 
     499        self._checkindex(index) 
    492500        self._checkdim(dimension) 
    493501 
     
    496504        idx = c_uint(index) 
    497505 
    498         # 'd' is the value of the point 
    499         d = c_double(value) 
    500         status = lgeos.GEOSCoordSeq_getOrdinate(self._cs, idx, dim, byref(d)) 
     506        # Setting the ordinate 
     507        status = lgeos.GEOSCoordSeq_setOrdinate(self._cs, idx, dim, c_double(value)) 
    501508        if status == 0: 
    502509            raise GEOSException, 'Could not set the ordinate for (dim, index): (%d, %d)' % (dimension, index) 
  • django/branches/gis/django/contrib/gis/tests/test_geos.py

    r5008 r5023  
    150150    #    pass 
    151151 
     152    def test08_coord_seq(self): 
     153        "Testing Coordinate Sequence objects." 
     154        for p in polygons: 
     155            if p.ext_ring_cs: 
     156                poly = GEOSGeometry(p.wkt) 
     157                cs = poly.exterior_ring.coord_seq 
     158 
     159                self.assertEqual(p.ext_ring_cs, cs.tuple) # done in the Polygon test too. 
     160                self.assertEqual(len(p.ext_ring_cs), len(cs)) # Making sure __len__ works 
     161 
     162                # Checks __getitem__ and __setitem__ 
     163                for i in xrange(len(p.ext_ring_cs)): 
     164                    c1 = p.ext_ring_cs[i] 
     165                    c2 = cs[i] 
     166                    self.assertEqual(c1, c2) 
     167                    if len(c1) == 2: tset = (5, 23) 
     168                    else: tset = (5, 23, 8) 
     169                    cs[i] = tset 
     170                    for j in range(len(tset)): 
     171                        cs[i] = tset 
     172                        self.assertEqual(tset, cs[i]) 
     173 
    152174    def test09_relate_pattern(self): 
    153175        "Testing relate() and relate_pattern()."