/django/contrib/gis/geos/prototypes/io.py
https://code.google.com/p/mango-py/ · Python · 242 lines · 163 code · 49 blank · 30 comment · 15 complexity · 082269179f4c931d33d1c442e3afeb50 MD5 · raw file
- import threading
- from ctypes import byref, c_char_p, c_int, c_char, c_size_t, Structure, POINTER
- from django.contrib.gis.geos.base import GEOSBase
- from django.contrib.gis.geos.libgeos import GEOM_PTR
- from django.contrib.gis.geos.prototypes.errcheck import check_geom, check_string, check_sized_string
- from django.contrib.gis.geos.prototypes.geom import c_uchar_p, geos_char_p
- from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
- ### The WKB/WKT Reader/Writer structures and pointers ###
- class WKTReader_st(Structure): pass
- class WKTWriter_st(Structure): pass
- class WKBReader_st(Structure): pass
- class WKBWriter_st(Structure): pass
- WKT_READ_PTR = POINTER(WKTReader_st)
- WKT_WRITE_PTR = POINTER(WKTWriter_st)
- WKB_READ_PTR = POINTER(WKBReader_st)
- WKB_WRITE_PTR = POINTER(WKBReader_st)
- ### WKTReader routines ###
- wkt_reader_create = GEOSFunc('GEOSWKTReader_create')
- wkt_reader_create.restype = WKT_READ_PTR
- wkt_reader_destroy = GEOSFunc('GEOSWKTReader_destroy')
- wkt_reader_destroy.argtypes = [WKT_READ_PTR]
- wkt_reader_read = GEOSFunc('GEOSWKTReader_read')
- wkt_reader_read.argtypes = [WKT_READ_PTR, c_char_p]
- wkt_reader_read.restype = GEOM_PTR
- wkt_reader_read.errcheck = check_geom
- ### WKTWriter routines ###
- wkt_writer_create = GEOSFunc('GEOSWKTWriter_create')
- wkt_writer_create.restype = WKT_WRITE_PTR
- wkt_writer_destroy = GEOSFunc('GEOSWKTWriter_destroy')
- wkt_writer_destroy.argtypes = [WKT_WRITE_PTR]
- wkt_writer_write = GEOSFunc('GEOSWKTWriter_write')
- wkt_writer_write.argtypes = [WKT_WRITE_PTR, GEOM_PTR]
- wkt_writer_write.restype = geos_char_p
- wkt_writer_write.errcheck = check_string
- ### WKBReader routines ###
- wkb_reader_create = GEOSFunc('GEOSWKBReader_create')
- wkb_reader_create.restype = WKB_READ_PTR
- wkb_reader_destroy = GEOSFunc('GEOSWKBReader_destroy')
- wkb_reader_destroy.argtypes = [WKB_READ_PTR]
- def wkb_read_func(func):
- # Although the function definitions take `const unsigned char *`
- # as their parameter, we use c_char_p here so the function may
- # take Python strings directly as parameters. Inside Python there
- # is not a difference between signed and unsigned characters, so
- # it is not a problem.
- func.argtypes = [WKB_READ_PTR, c_char_p, c_size_t]
- func.restype = GEOM_PTR
- func.errcheck = check_geom
- return func
- wkb_reader_read = wkb_read_func(GEOSFunc('GEOSWKBReader_read'))
- wkb_reader_read_hex = wkb_read_func(GEOSFunc('GEOSWKBReader_readHEX'))
- ### WKBWriter routines ###
- wkb_writer_create = GEOSFunc('GEOSWKBWriter_create')
- wkb_writer_create.restype = WKB_WRITE_PTR
- wkb_writer_destroy = GEOSFunc('GEOSWKBWriter_destroy')
- wkb_writer_destroy.argtypes = [WKB_WRITE_PTR]
- # WKB Writing prototypes.
- def wkb_write_func(func):
- func.argtypes = [WKB_WRITE_PTR, GEOM_PTR, POINTER(c_size_t)]
- func.restype = c_uchar_p
- func.errcheck = check_sized_string
- return func
- wkb_writer_write = wkb_write_func(GEOSFunc('GEOSWKBWriter_write'))
- wkb_writer_write_hex = wkb_write_func(GEOSFunc('GEOSWKBWriter_writeHEX'))
- # WKBWriter property getter/setter prototypes.
- def wkb_writer_get(func, restype=c_int):
- func.argtypes = [WKB_WRITE_PTR]
- func.restype = restype
- return func
- def wkb_writer_set(func, argtype=c_int):
- func.argtypes = [WKB_WRITE_PTR, argtype]
- return func
- wkb_writer_get_byteorder = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getByteOrder'))
- wkb_writer_set_byteorder = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setByteOrder'))
- wkb_writer_get_outdim = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getOutputDimension'))
- wkb_writer_set_outdim = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setOutputDimension'))
- wkb_writer_get_include_srid = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getIncludeSRID'), restype=c_char)
- wkb_writer_set_include_srid = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setIncludeSRID'), argtype=c_char)
- ### Base I/O Class ###
- class IOBase(GEOSBase):
- "Base class for GEOS I/O objects."
- def __init__(self):
- # Getting the pointer with the constructor.
- self.ptr = self._constructor()
- def __del__(self):
- # Cleaning up with the appropriate destructor.
- if self._ptr: self._destructor(self._ptr)
- ### Base WKB/WKT Reading and Writing objects ###
- # Non-public WKB/WKT reader classes for internal use because
- # their `read` methods return _pointers_ instead of GEOSGeometry
- # objects.
- class _WKTReader(IOBase):
- _constructor = wkt_reader_create
- _destructor = wkt_reader_destroy
- ptr_type = WKT_READ_PTR
- def read(self, wkt):
- if not isinstance(wkt, basestring): raise TypeError
- return wkt_reader_read(self.ptr, wkt)
- class _WKBReader(IOBase):
- _constructor = wkb_reader_create
- _destructor = wkb_reader_destroy
- ptr_type = WKB_READ_PTR
- def read(self, wkb):
- "Returns a _pointer_ to C GEOS Geometry object from the given WKB."
- if isinstance(wkb, buffer):
- wkb_s = str(wkb)
- return wkb_reader_read(self.ptr, wkb_s, len(wkb_s))
- elif isinstance(wkb, basestring):
- return wkb_reader_read_hex(self.ptr, wkb, len(wkb))
- else:
- raise TypeError
- ### WKB/WKT Writer Classes ###
- class WKTWriter(IOBase):
- _constructor = wkt_writer_create
- _destructor = wkt_writer_destroy
- ptr_type = WKT_WRITE_PTR
- def write(self, geom):
- "Returns the WKT representation of the given geometry."
- return wkt_writer_write(self.ptr, geom.ptr)
- class WKBWriter(IOBase):
- _constructor = wkb_writer_create
- _destructor = wkb_writer_destroy
- ptr_type = WKB_WRITE_PTR
- def write(self, geom):
- "Returns the WKB representation of the given geometry."
- return buffer(wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t())))
- def write_hex(self, geom):
- "Returns the HEXEWKB representation of the given geometry."
- return wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t()))
- ### WKBWriter Properties ###
- # Property for getting/setting the byteorder.
- def _get_byteorder(self):
- return wkb_writer_get_byteorder(self.ptr)
- def _set_byteorder(self, order):
- if not order in (0, 1): raise ValueError('Byte order parameter must be 0 (Big Endian) or 1 (Little Endian).')
- wkb_writer_set_byteorder(self.ptr, order)
- byteorder = property(_get_byteorder, _set_byteorder)
- # Property for getting/setting the output dimension.
- def _get_outdim(self):
- return wkb_writer_get_outdim(self.ptr)
- def _set_outdim(self, new_dim):
- if not new_dim in (2, 3): raise ValueError('WKB output dimension must be 2 or 3')
- wkb_writer_set_outdim(self.ptr, new_dim)
- outdim = property(_get_outdim, _set_outdim)
- # Property for getting/setting the include srid flag.
- def _get_include_srid(self):
- return bool(ord(wkb_writer_get_include_srid(self.ptr)))
- def _set_include_srid(self, include):
- if bool(include): flag = chr(1)
- else: flag = chr(0)
- wkb_writer_set_include_srid(self.ptr, flag)
- srid = property(_get_include_srid, _set_include_srid)
- # `ThreadLocalIO` object holds instances of the WKT and WKB reader/writer
- # objects that are local to the thread. The `GEOSGeometry` internals
- # access these instances by calling the module-level functions, defined
- # below.
- class ThreadLocalIO(threading.local):
- wkt_r = None
- wkt_w = None
- wkb_r = None
- wkb_w = None
- ewkb_w = None
- ewkb_w3d = None
- thread_context = ThreadLocalIO()
- # These module-level routines return the I/O object that is local to the
- # the thread. If the I/O object does not exist yet it will be initialized.
- def wkt_r():
- if not thread_context.wkt_r:
- thread_context.wkt_r = _WKTReader()
- return thread_context.wkt_r
- def wkt_w():
- if not thread_context.wkt_w:
- thread_context.wkt_w = WKTWriter()
- return thread_context.wkt_w
- def wkb_r():
- if not thread_context.wkb_r:
- thread_context.wkb_r = _WKBReader()
- return thread_context.wkb_r
- def wkb_w():
- if not thread_context.wkb_w:
- thread_context.wkb_w = WKBWriter()
- return thread_context.wkb_w
- def ewkb_w():
- if not thread_context.ewkb_w:
- thread_context.ewkb_w = WKBWriter()
- thread_context.ewkb_w.srid = True
- return thread_context.ewkb_w
- def ewkb_w3d():
- if not thread_context.ewkb_w3d:
- thread_context.ewkb_w3d = WKBWriter()
- thread_context.ewkb_w3d.srid = True
- thread_context.ewkb_w3d.outdim = 3
- return thread_context.ewkb_w3d