/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

  1. import threading
  2. from ctypes import byref, c_char_p, c_int, c_char, c_size_t, Structure, POINTER
  3. from django.contrib.gis.geos.base import GEOSBase
  4. from django.contrib.gis.geos.libgeos import GEOM_PTR
  5. from django.contrib.gis.geos.prototypes.errcheck import check_geom, check_string, check_sized_string
  6. from django.contrib.gis.geos.prototypes.geom import c_uchar_p, geos_char_p
  7. from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
  8. ### The WKB/WKT Reader/Writer structures and pointers ###
  9. class WKTReader_st(Structure): pass
  10. class WKTWriter_st(Structure): pass
  11. class WKBReader_st(Structure): pass
  12. class WKBWriter_st(Structure): pass
  13. WKT_READ_PTR = POINTER(WKTReader_st)
  14. WKT_WRITE_PTR = POINTER(WKTWriter_st)
  15. WKB_READ_PTR = POINTER(WKBReader_st)
  16. WKB_WRITE_PTR = POINTER(WKBReader_st)
  17. ### WKTReader routines ###
  18. wkt_reader_create = GEOSFunc('GEOSWKTReader_create')
  19. wkt_reader_create.restype = WKT_READ_PTR
  20. wkt_reader_destroy = GEOSFunc('GEOSWKTReader_destroy')
  21. wkt_reader_destroy.argtypes = [WKT_READ_PTR]
  22. wkt_reader_read = GEOSFunc('GEOSWKTReader_read')
  23. wkt_reader_read.argtypes = [WKT_READ_PTR, c_char_p]
  24. wkt_reader_read.restype = GEOM_PTR
  25. wkt_reader_read.errcheck = check_geom
  26. ### WKTWriter routines ###
  27. wkt_writer_create = GEOSFunc('GEOSWKTWriter_create')
  28. wkt_writer_create.restype = WKT_WRITE_PTR
  29. wkt_writer_destroy = GEOSFunc('GEOSWKTWriter_destroy')
  30. wkt_writer_destroy.argtypes = [WKT_WRITE_PTR]
  31. wkt_writer_write = GEOSFunc('GEOSWKTWriter_write')
  32. wkt_writer_write.argtypes = [WKT_WRITE_PTR, GEOM_PTR]
  33. wkt_writer_write.restype = geos_char_p
  34. wkt_writer_write.errcheck = check_string
  35. ### WKBReader routines ###
  36. wkb_reader_create = GEOSFunc('GEOSWKBReader_create')
  37. wkb_reader_create.restype = WKB_READ_PTR
  38. wkb_reader_destroy = GEOSFunc('GEOSWKBReader_destroy')
  39. wkb_reader_destroy.argtypes = [WKB_READ_PTR]
  40. def wkb_read_func(func):
  41. # Although the function definitions take `const unsigned char *`
  42. # as their parameter, we use c_char_p here so the function may
  43. # take Python strings directly as parameters. Inside Python there
  44. # is not a difference between signed and unsigned characters, so
  45. # it is not a problem.
  46. func.argtypes = [WKB_READ_PTR, c_char_p, c_size_t]
  47. func.restype = GEOM_PTR
  48. func.errcheck = check_geom
  49. return func
  50. wkb_reader_read = wkb_read_func(GEOSFunc('GEOSWKBReader_read'))
  51. wkb_reader_read_hex = wkb_read_func(GEOSFunc('GEOSWKBReader_readHEX'))
  52. ### WKBWriter routines ###
  53. wkb_writer_create = GEOSFunc('GEOSWKBWriter_create')
  54. wkb_writer_create.restype = WKB_WRITE_PTR
  55. wkb_writer_destroy = GEOSFunc('GEOSWKBWriter_destroy')
  56. wkb_writer_destroy.argtypes = [WKB_WRITE_PTR]
  57. # WKB Writing prototypes.
  58. def wkb_write_func(func):
  59. func.argtypes = [WKB_WRITE_PTR, GEOM_PTR, POINTER(c_size_t)]
  60. func.restype = c_uchar_p
  61. func.errcheck = check_sized_string
  62. return func
  63. wkb_writer_write = wkb_write_func(GEOSFunc('GEOSWKBWriter_write'))
  64. wkb_writer_write_hex = wkb_write_func(GEOSFunc('GEOSWKBWriter_writeHEX'))
  65. # WKBWriter property getter/setter prototypes.
  66. def wkb_writer_get(func, restype=c_int):
  67. func.argtypes = [WKB_WRITE_PTR]
  68. func.restype = restype
  69. return func
  70. def wkb_writer_set(func, argtype=c_int):
  71. func.argtypes = [WKB_WRITE_PTR, argtype]
  72. return func
  73. wkb_writer_get_byteorder = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getByteOrder'))
  74. wkb_writer_set_byteorder = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setByteOrder'))
  75. wkb_writer_get_outdim = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getOutputDimension'))
  76. wkb_writer_set_outdim = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setOutputDimension'))
  77. wkb_writer_get_include_srid = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getIncludeSRID'), restype=c_char)
  78. wkb_writer_set_include_srid = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setIncludeSRID'), argtype=c_char)
  79. ### Base I/O Class ###
  80. class IOBase(GEOSBase):
  81. "Base class for GEOS I/O objects."
  82. def __init__(self):
  83. # Getting the pointer with the constructor.
  84. self.ptr = self._constructor()
  85. def __del__(self):
  86. # Cleaning up with the appropriate destructor.
  87. if self._ptr: self._destructor(self._ptr)
  88. ### Base WKB/WKT Reading and Writing objects ###
  89. # Non-public WKB/WKT reader classes for internal use because
  90. # their `read` methods return _pointers_ instead of GEOSGeometry
  91. # objects.
  92. class _WKTReader(IOBase):
  93. _constructor = wkt_reader_create
  94. _destructor = wkt_reader_destroy
  95. ptr_type = WKT_READ_PTR
  96. def read(self, wkt):
  97. if not isinstance(wkt, basestring): raise TypeError
  98. return wkt_reader_read(self.ptr, wkt)
  99. class _WKBReader(IOBase):
  100. _constructor = wkb_reader_create
  101. _destructor = wkb_reader_destroy
  102. ptr_type = WKB_READ_PTR
  103. def read(self, wkb):
  104. "Returns a _pointer_ to C GEOS Geometry object from the given WKB."
  105. if isinstance(wkb, buffer):
  106. wkb_s = str(wkb)
  107. return wkb_reader_read(self.ptr, wkb_s, len(wkb_s))
  108. elif isinstance(wkb, basestring):
  109. return wkb_reader_read_hex(self.ptr, wkb, len(wkb))
  110. else:
  111. raise TypeError
  112. ### WKB/WKT Writer Classes ###
  113. class WKTWriter(IOBase):
  114. _constructor = wkt_writer_create
  115. _destructor = wkt_writer_destroy
  116. ptr_type = WKT_WRITE_PTR
  117. def write(self, geom):
  118. "Returns the WKT representation of the given geometry."
  119. return wkt_writer_write(self.ptr, geom.ptr)
  120. class WKBWriter(IOBase):
  121. _constructor = wkb_writer_create
  122. _destructor = wkb_writer_destroy
  123. ptr_type = WKB_WRITE_PTR
  124. def write(self, geom):
  125. "Returns the WKB representation of the given geometry."
  126. return buffer(wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t())))
  127. def write_hex(self, geom):
  128. "Returns the HEXEWKB representation of the given geometry."
  129. return wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t()))
  130. ### WKBWriter Properties ###
  131. # Property for getting/setting the byteorder.
  132. def _get_byteorder(self):
  133. return wkb_writer_get_byteorder(self.ptr)
  134. def _set_byteorder(self, order):
  135. if not order in (0, 1): raise ValueError('Byte order parameter must be 0 (Big Endian) or 1 (Little Endian).')
  136. wkb_writer_set_byteorder(self.ptr, order)
  137. byteorder = property(_get_byteorder, _set_byteorder)
  138. # Property for getting/setting the output dimension.
  139. def _get_outdim(self):
  140. return wkb_writer_get_outdim(self.ptr)
  141. def _set_outdim(self, new_dim):
  142. if not new_dim in (2, 3): raise ValueError('WKB output dimension must be 2 or 3')
  143. wkb_writer_set_outdim(self.ptr, new_dim)
  144. outdim = property(_get_outdim, _set_outdim)
  145. # Property for getting/setting the include srid flag.
  146. def _get_include_srid(self):
  147. return bool(ord(wkb_writer_get_include_srid(self.ptr)))
  148. def _set_include_srid(self, include):
  149. if bool(include): flag = chr(1)
  150. else: flag = chr(0)
  151. wkb_writer_set_include_srid(self.ptr, flag)
  152. srid = property(_get_include_srid, _set_include_srid)
  153. # `ThreadLocalIO` object holds instances of the WKT and WKB reader/writer
  154. # objects that are local to the thread. The `GEOSGeometry` internals
  155. # access these instances by calling the module-level functions, defined
  156. # below.
  157. class ThreadLocalIO(threading.local):
  158. wkt_r = None
  159. wkt_w = None
  160. wkb_r = None
  161. wkb_w = None
  162. ewkb_w = None
  163. ewkb_w3d = None
  164. thread_context = ThreadLocalIO()
  165. # These module-level routines return the I/O object that is local to the
  166. # the thread. If the I/O object does not exist yet it will be initialized.
  167. def wkt_r():
  168. if not thread_context.wkt_r:
  169. thread_context.wkt_r = _WKTReader()
  170. return thread_context.wkt_r
  171. def wkt_w():
  172. if not thread_context.wkt_w:
  173. thread_context.wkt_w = WKTWriter()
  174. return thread_context.wkt_w
  175. def wkb_r():
  176. if not thread_context.wkb_r:
  177. thread_context.wkb_r = _WKBReader()
  178. return thread_context.wkb_r
  179. def wkb_w():
  180. if not thread_context.wkb_w:
  181. thread_context.wkb_w = WKBWriter()
  182. return thread_context.wkb_w
  183. def ewkb_w():
  184. if not thread_context.ewkb_w:
  185. thread_context.ewkb_w = WKBWriter()
  186. thread_context.ewkb_w.srid = True
  187. return thread_context.ewkb_w
  188. def ewkb_w3d():
  189. if not thread_context.ewkb_w3d:
  190. thread_context.ewkb_w3d = WKBWriter()
  191. thread_context.ewkb_w3d.srid = True
  192. thread_context.ewkb_w3d.outdim = 3
  193. return thread_context.ewkb_w3d