Lazy loading of GEOS functions
This commit is contained in:
parent
143255c8bb
commit
61d09e61f5
|
@ -1,8 +1,7 @@
|
||||||
from django.contrib.gis.db.backends.base.features import BaseSpatialFeatures
|
from django.contrib.gis.db.backends.base.features import BaseSpatialFeatures
|
||||||
from django.contrib.gis.geos import geos_version
|
from django.contrib.gis.geos import geos_version_info
|
||||||
from django.db.backends.sqlite3.features import \
|
from django.db.backends.sqlite3.features import \
|
||||||
DatabaseFeatures as SQLiteDatabaseFeatures
|
DatabaseFeatures as SQLiteDatabaseFeatures
|
||||||
from django.utils.encoding import force_text
|
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,4 +19,4 @@ class DatabaseFeatures(BaseSpatialFeatures, SQLiteDatabaseFeatures):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def supports_3d_storage(self):
|
def supports_3d_storage(self):
|
||||||
return force_text(geos_version()) >= '3.3'
|
return geos_version_info()['version'] >= '3.3'
|
||||||
|
|
|
@ -14,51 +14,61 @@ from ctypes.util import find_library
|
||||||
|
|
||||||
from django.contrib.gis.geos.error import GEOSException
|
from django.contrib.gis.geos.error import GEOSException
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.utils.functional import SimpleLazyObject
|
||||||
|
|
||||||
logger = logging.getLogger('django.contrib.gis')
|
logger = logging.getLogger('django.contrib.gis')
|
||||||
|
|
||||||
# Custom library path set?
|
|
||||||
try:
|
|
||||||
from django.conf import settings
|
|
||||||
lib_path = settings.GEOS_LIBRARY_PATH
|
|
||||||
except (AttributeError, EnvironmentError,
|
|
||||||
ImportError, ImproperlyConfigured):
|
|
||||||
lib_path = None
|
|
||||||
|
|
||||||
# Setting the appropriate names for the GEOS-C library.
|
def load_geos():
|
||||||
if lib_path:
|
# Custom library path set?
|
||||||
lib_names = None
|
try:
|
||||||
elif os.name == 'nt':
|
from django.conf import settings
|
||||||
# Windows NT libraries
|
lib_path = settings.GEOS_LIBRARY_PATH
|
||||||
lib_names = ['geos_c', 'libgeos_c-1']
|
except (AttributeError, EnvironmentError,
|
||||||
elif os.name == 'posix':
|
ImportError, ImproperlyConfigured):
|
||||||
# *NIX libraries
|
lib_path = None
|
||||||
lib_names = ['geos_c', 'GEOS']
|
|
||||||
else:
|
|
||||||
raise ImportError('Unsupported OS "%s"' % os.name)
|
|
||||||
|
|
||||||
# Using the ctypes `find_library` utility to find the path to the GEOS
|
# Setting the appropriate names for the GEOS-C library.
|
||||||
# shared library. This is better than manually specifying each library name
|
if lib_path:
|
||||||
# and extension (e.g., libgeos_c.[so|so.1|dylib].).
|
lib_names = None
|
||||||
if lib_names:
|
elif os.name == 'nt':
|
||||||
for lib_name in lib_names:
|
# Windows NT libraries
|
||||||
lib_path = find_library(lib_name)
|
lib_names = ['geos_c', 'libgeos_c-1']
|
||||||
if lib_path is not None:
|
elif os.name == 'posix':
|
||||||
break
|
# *NIX libraries
|
||||||
|
lib_names = ['geos_c', 'GEOS']
|
||||||
|
else:
|
||||||
|
raise ImportError('Unsupported OS "%s"' % os.name)
|
||||||
|
|
||||||
# No GEOS library could be found.
|
# Using the ctypes `find_library` utility to find the path to the GEOS
|
||||||
if lib_path is None:
|
# shared library. This is better than manually specifying each library name
|
||||||
raise ImportError(
|
# and extension (e.g., libgeos_c.[so|so.1|dylib].).
|
||||||
'Could not find the GEOS library (tried "%s"). '
|
if lib_names:
|
||||||
'Try setting GEOS_LIBRARY_PATH in your settings.' %
|
for lib_name in lib_names:
|
||||||
'", "'.join(lib_names)
|
lib_path = find_library(lib_name)
|
||||||
)
|
if lib_path is not None:
|
||||||
|
break
|
||||||
|
|
||||||
|
# No GEOS library could be found.
|
||||||
|
if lib_path is None:
|
||||||
|
raise ImportError(
|
||||||
|
'Could not find the GEOS library (tried "%s"). '
|
||||||
|
'Try setting GEOS_LIBRARY_PATH in your settings.' %
|
||||||
|
'", "'.join(lib_names)
|
||||||
|
)
|
||||||
|
# Getting the GEOS C library. The C interface (CDLL) is used for
|
||||||
|
# both *NIX and Windows.
|
||||||
|
# See the GEOS C API source code for more details on the library function calls:
|
||||||
|
# http://geos.refractions.net/ro/doxygen_docs/html/geos__c_8h-source.html
|
||||||
|
_lgeos = CDLL(lib_path)
|
||||||
|
# Here we set up the prototypes for the initGEOS_r and finishGEOS_r
|
||||||
|
# routines. These functions aren't actually called until they are
|
||||||
|
# attached to a GEOS context handle -- this actually occurs in
|
||||||
|
# geos/prototypes/threadsafe.py.
|
||||||
|
_lgeos.initGEOS_r.restype = CONTEXT_PTR
|
||||||
|
_lgeos.finishGEOS_r.argtypes = [CONTEXT_PTR]
|
||||||
|
return _lgeos
|
||||||
|
|
||||||
# Getting the GEOS C library. The C interface (CDLL) is used for
|
|
||||||
# both *NIX and Windows.
|
|
||||||
# See the GEOS C API source code for more details on the library function calls:
|
|
||||||
# http://geos.refractions.net/ro/doxygen_docs/html/geos__c_8h-source.html
|
|
||||||
lgeos = CDLL(lib_path)
|
|
||||||
|
|
||||||
# The notice and error handler C function callback definitions.
|
# The notice and error handler C function callback definitions.
|
||||||
# Supposed to mimic the GEOS message handler (C below):
|
# Supposed to mimic the GEOS message handler (C below):
|
||||||
|
@ -120,11 +130,42 @@ def get_pointer_arr(n):
|
||||||
GeomArr = GEOM_PTR * n
|
GeomArr = GEOM_PTR * n
|
||||||
return GeomArr()
|
return GeomArr()
|
||||||
|
|
||||||
|
|
||||||
|
lgeos = SimpleLazyObject(load_geos)
|
||||||
|
|
||||||
|
|
||||||
|
class GEOSFuncFactory(object):
|
||||||
|
argtypes = None
|
||||||
|
restype = None
|
||||||
|
errcheck = None
|
||||||
|
|
||||||
|
def __init__(self, func_name, *args, **kwargs):
|
||||||
|
self.func_name = func_name
|
||||||
|
self.restype = kwargs.pop('restype', self.restype)
|
||||||
|
self.errcheck = kwargs.pop('errcheck', self.errcheck)
|
||||||
|
self.argtypes = kwargs.pop('argtypes', self.argtypes)
|
||||||
|
self.args = args
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.func = None
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
if self.func is None:
|
||||||
|
self.func = self.get_func(*self.args, **self.kwargs)
|
||||||
|
return self.func(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_func(self, *args, **kwargs):
|
||||||
|
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
||||||
|
func = GEOSFunc(self.func_name)
|
||||||
|
func.argtypes = self.argtypes or []
|
||||||
|
func.restype = self.restype
|
||||||
|
if self.errcheck:
|
||||||
|
func.errcheck = self.errcheck
|
||||||
|
return func
|
||||||
|
|
||||||
|
|
||||||
# Returns the string version of the GEOS library. Have to set the restype
|
# Returns the string version of the GEOS library. Have to set the restype
|
||||||
# explicitly to c_char_p to ensure compatibility across 32 and 64-bit platforms.
|
# explicitly to c_char_p to ensure compatibility across 32 and 64-bit platforms.
|
||||||
geos_version = lgeos.GEOSversion
|
geos_version = GEOSFuncFactory('GEOSversion', restype=c_char_p)
|
||||||
geos_version.argtypes = None
|
|
||||||
geos_version.restype = c_char_p
|
|
||||||
|
|
||||||
# Regular expression should be able to parse version strings such as
|
# Regular expression should be able to parse version strings such as
|
||||||
# '3.0.0rc4-CAPI-1.3.3', '3.0.0-CAPI-1.4.1', '3.4.0dev-CAPI-1.8.0' or '3.4.0dev-CAPI-1.8.0 r0'
|
# '3.0.0rc4-CAPI-1.3.3', '3.0.0-CAPI-1.4.1', '3.4.0dev-CAPI-1.8.0' or '3.4.0dev-CAPI-1.8.0 r0'
|
||||||
|
@ -147,18 +188,3 @@ def geos_version_info():
|
||||||
raise GEOSException('Could not parse version info string "%s"' % ver)
|
raise GEOSException('Could not parse version info string "%s"' % ver)
|
||||||
return {key: m.group(key) for key in (
|
return {key: m.group(key) for key in (
|
||||||
'version', 'release_candidate', 'capi_version', 'major', 'minor', 'subminor')}
|
'version', 'release_candidate', 'capi_version', 'major', 'minor', 'subminor')}
|
||||||
|
|
||||||
# Version numbers and whether or not prepared geometry support is available.
|
|
||||||
_verinfo = geos_version_info()
|
|
||||||
GEOS_MAJOR_VERSION = int(_verinfo['major'])
|
|
||||||
GEOS_MINOR_VERSION = int(_verinfo['minor'])
|
|
||||||
GEOS_SUBMINOR_VERSION = int(_verinfo['subminor'])
|
|
||||||
del _verinfo
|
|
||||||
GEOS_VERSION = (GEOS_MAJOR_VERSION, GEOS_MINOR_VERSION, GEOS_SUBMINOR_VERSION)
|
|
||||||
|
|
||||||
# Here we set up the prototypes for the initGEOS_r and finishGEOS_r
|
|
||||||
# routines. These functions aren't actually called until they are
|
|
||||||
# attached to a GEOS context handle -- this actually occurs in
|
|
||||||
# geos/prototypes/threadsafe.py.
|
|
||||||
lgeos.initGEOS_r.restype = CONTEXT_PTR
|
|
||||||
lgeos.finishGEOS_r.argtypes = [CONTEXT_PTR]
|
|
||||||
|
|
|
@ -1,23 +1,12 @@
|
||||||
from ctypes import POINTER, c_double, c_int, c_uint
|
from ctypes import POINTER, c_double, c_int, c_uint
|
||||||
|
|
||||||
from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR
|
from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, GEOSFuncFactory
|
||||||
from django.contrib.gis.geos.prototypes.errcheck import (
|
from django.contrib.gis.geos.prototypes.errcheck import (
|
||||||
GEOSException, last_arg_byref,
|
GEOSException, last_arg_byref,
|
||||||
)
|
)
|
||||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
|
||||||
|
|
||||||
|
|
||||||
# ## Error-checking routines specific to coordinate sequences. ##
|
# ## Error-checking routines specific to coordinate sequences. ##
|
||||||
def check_cs_ptr(result, func, cargs):
|
|
||||||
"Error checking on routines that return Geometries."
|
|
||||||
if not result:
|
|
||||||
raise GEOSException(
|
|
||||||
'Error encountered checking Coordinate Sequence returned from GEOS '
|
|
||||||
'C function "%s".' % func.__name__
|
|
||||||
)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def check_cs_op(result, func, cargs):
|
def check_cs_op(result, func, cargs):
|
||||||
"Checks the status code of a coordinate sequence operation."
|
"Checks the status code of a coordinate sequence operation."
|
||||||
if result == 0:
|
if result == 0:
|
||||||
|
@ -33,63 +22,73 @@ def check_cs_get(result, func, cargs):
|
||||||
return last_arg_byref(cargs)
|
return last_arg_byref(cargs)
|
||||||
|
|
||||||
|
|
||||||
# ## Coordinate sequence prototype generation functions. ##
|
# ## Coordinate sequence prototype factory classes. ##
|
||||||
def cs_int(func):
|
class CsInt(GEOSFuncFactory):
|
||||||
"For coordinate sequence routines that return an integer."
|
"For coordinate sequence routines that return an integer."
|
||||||
func.argtypes = [CS_PTR, POINTER(c_uint)]
|
argtypes = [CS_PTR, POINTER(c_uint)]
|
||||||
func.restype = c_int
|
restype = c_int
|
||||||
func.errcheck = check_cs_get
|
errcheck = staticmethod(check_cs_get)
|
||||||
return func
|
|
||||||
|
|
||||||
|
|
||||||
def cs_operation(func, ordinate=False, get=False):
|
class CsOperation(GEOSFuncFactory):
|
||||||
"For coordinate sequence operations."
|
"For coordinate sequence operations."
|
||||||
if get:
|
restype = c_int
|
||||||
# Get routines get double parameter passed-in by reference.
|
|
||||||
func.errcheck = check_cs_get
|
|
||||||
dbl_param = POINTER(c_double)
|
|
||||||
else:
|
|
||||||
func.errcheck = check_cs_op
|
|
||||||
dbl_param = c_double
|
|
||||||
|
|
||||||
if ordinate:
|
def get_func(self, ordinate=False, get=False):
|
||||||
# Get/Set ordinate routines have an extra uint parameter.
|
if get:
|
||||||
func.argtypes = [CS_PTR, c_uint, c_uint, dbl_param]
|
# Get routines have double parameter passed-in by reference.
|
||||||
else:
|
self.errcheck = check_cs_get
|
||||||
func.argtypes = [CS_PTR, c_uint, dbl_param]
|
dbl_param = POINTER(c_double)
|
||||||
|
else:
|
||||||
|
self.errcheck = check_cs_op
|
||||||
|
dbl_param = c_double
|
||||||
|
|
||||||
func.restype = c_int
|
if ordinate:
|
||||||
return func
|
# Get/Set ordinate routines have an extra uint parameter.
|
||||||
|
self.argtypes = [CS_PTR, c_uint, c_uint, dbl_param]
|
||||||
|
else:
|
||||||
|
self.argtypes = [CS_PTR, c_uint, dbl_param]
|
||||||
|
return super(CsOperation, self).get_func()
|
||||||
|
|
||||||
|
|
||||||
def cs_output(func, argtypes):
|
class CsOutput(GEOSFuncFactory):
|
||||||
"For routines that return a coordinate sequence."
|
restype = CS_PTR
|
||||||
func.argtypes = argtypes
|
|
||||||
func.restype = CS_PTR
|
def get_func(self, argtypes):
|
||||||
func.errcheck = check_cs_ptr
|
self.argtypes = argtypes
|
||||||
return func
|
return super(CsOutput, self).get_func()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def errcheck(result, func, cargs):
|
||||||
|
if not result:
|
||||||
|
raise GEOSException(
|
||||||
|
'Error encountered checking Coordinate Sequence returned from GEOS '
|
||||||
|
'C function "%s".' % func.__name__
|
||||||
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
# ## Coordinate Sequence ctypes prototypes ##
|
# ## Coordinate Sequence ctypes prototypes ##
|
||||||
|
|
||||||
# Coordinate Sequence constructors & cloning.
|
# Coordinate Sequence constructors & cloning.
|
||||||
cs_clone = cs_output(GEOSFunc('GEOSCoordSeq_clone'), [CS_PTR])
|
cs_clone = CsOutput('GEOSCoordSeq_clone', [CS_PTR])
|
||||||
create_cs = cs_output(GEOSFunc('GEOSCoordSeq_create'), [c_uint, c_uint])
|
create_cs = CsOutput('GEOSCoordSeq_create', [c_uint, c_uint])
|
||||||
get_cs = cs_output(GEOSFunc('GEOSGeom_getCoordSeq'), [GEOM_PTR])
|
get_cs = CsOutput('GEOSGeom_getCoordSeq', [GEOM_PTR])
|
||||||
|
|
||||||
# Getting, setting ordinate
|
# Getting, setting ordinate
|
||||||
cs_getordinate = cs_operation(GEOSFunc('GEOSCoordSeq_getOrdinate'), ordinate=True, get=True)
|
cs_getordinate = CsOperation('GEOSCoordSeq_getOrdinate', ordinate=True, get=True)
|
||||||
cs_setordinate = cs_operation(GEOSFunc('GEOSCoordSeq_setOrdinate'), ordinate=True)
|
cs_setordinate = CsOperation('GEOSCoordSeq_setOrdinate', ordinate=True)
|
||||||
|
|
||||||
# For getting, x, y, z
|
# For getting, x, y, z
|
||||||
cs_getx = cs_operation(GEOSFunc('GEOSCoordSeq_getX'), get=True)
|
cs_getx = CsOperation('GEOSCoordSeq_getX', get=True)
|
||||||
cs_gety = cs_operation(GEOSFunc('GEOSCoordSeq_getY'), get=True)
|
cs_gety = CsOperation('GEOSCoordSeq_getY', get=True)
|
||||||
cs_getz = cs_operation(GEOSFunc('GEOSCoordSeq_getZ'), get=True)
|
cs_getz = CsOperation('GEOSCoordSeq_getZ', get=True)
|
||||||
|
|
||||||
# For setting, x, y, z
|
# For setting, x, y, z
|
||||||
cs_setx = cs_operation(GEOSFunc('GEOSCoordSeq_setX'))
|
cs_setx = CsOperation('GEOSCoordSeq_setX')
|
||||||
cs_sety = cs_operation(GEOSFunc('GEOSCoordSeq_setY'))
|
cs_sety = CsOperation('GEOSCoordSeq_setY')
|
||||||
cs_setz = cs_operation(GEOSFunc('GEOSCoordSeq_setZ'))
|
cs_setz = CsOperation('GEOSCoordSeq_setZ')
|
||||||
|
|
||||||
# These routines return size & dimensions.
|
# These routines return size & dimensions.
|
||||||
cs_getsize = cs_int(GEOSFunc('GEOSCoordSeq_getSize'))
|
cs_getsize = CsInt('GEOSCoordSeq_getSize')
|
||||||
cs_getdims = cs_int(GEOSFunc('GEOSCoordSeq_getDimensions'))
|
cs_getdims = CsInt('GEOSCoordSeq_getDimensions')
|
||||||
|
|
|
@ -4,13 +4,12 @@
|
||||||
from ctypes import c_void_p, string_at
|
from ctypes import c_void_p, string_at
|
||||||
|
|
||||||
from django.contrib.gis.geos.error import GEOSException
|
from django.contrib.gis.geos.error import GEOSException
|
||||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
from django.contrib.gis.geos.libgeos import GEOSFuncFactory
|
||||||
|
|
||||||
# Getting the `free` routine used to free the memory allocated for
|
# Getting the `free` routine used to free the memory allocated for
|
||||||
# string pointers returned by GEOS.
|
# string pointers returned by GEOS.
|
||||||
free = GEOSFunc('GEOSFree')
|
free = GEOSFuncFactory('GEOSFree')
|
||||||
free.argtypes = [c_void_p]
|
free.argtypes = [c_void_p]
|
||||||
free.restype = None
|
|
||||||
|
|
||||||
|
|
||||||
def last_arg_byref(args):
|
def last_arg_byref(args):
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
from ctypes import POINTER, c_char_p, c_int, c_size_t, c_ubyte
|
from ctypes import POINTER, c_char_p, c_int, c_size_t, c_ubyte
|
||||||
|
|
||||||
from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR
|
from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, GEOSFuncFactory
|
||||||
from django.contrib.gis.geos.prototypes.errcheck import (
|
from django.contrib.gis.geos.prototypes.errcheck import (
|
||||||
check_geom, check_minus_one, check_sized_string, check_string, check_zero,
|
check_geom, check_minus_one, check_sized_string, check_string, check_zero,
|
||||||
)
|
)
|
||||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
|
||||||
|
|
||||||
# This is the return type used by binary output (WKB, HEX) routines.
|
# This is the return type used by binary output (WKB, HEX) routines.
|
||||||
c_uchar_p = POINTER(c_ubyte)
|
c_uchar_p = POINTER(c_ubyte)
|
||||||
|
@ -21,109 +20,96 @@ class geos_char_p(c_char_p):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# ### ctypes generation functions ###
|
# ### ctypes factory classes ###
|
||||||
def bin_constructor(func):
|
class BinConstructor(GEOSFuncFactory):
|
||||||
"Generates a prototype for binary construction (HEX, WKB) GEOS routines."
|
"Generates a prototype for binary construction (HEX, WKB) GEOS routines."
|
||||||
func.argtypes = [c_char_p, c_size_t]
|
argtypes = [c_char_p, c_size_t]
|
||||||
func.restype = GEOM_PTR
|
restype = GEOM_PTR
|
||||||
func.errcheck = check_geom
|
errcheck = staticmethod(check_geom)
|
||||||
return func
|
|
||||||
|
|
||||||
|
|
||||||
# HEX & WKB output
|
# HEX & WKB output
|
||||||
def bin_output(func):
|
class BinOutput(GEOSFuncFactory):
|
||||||
"Generates a prototype for the routines that return a sized string."
|
"Generates a prototype for the routines that return a sized string."
|
||||||
func.argtypes = [GEOM_PTR, POINTER(c_size_t)]
|
argtypes = [GEOM_PTR, POINTER(c_size_t)]
|
||||||
func.errcheck = check_sized_string
|
restype = c_uchar_p
|
||||||
func.restype = c_uchar_p
|
errcheck = staticmethod(check_sized_string)
|
||||||
return func
|
|
||||||
|
|
||||||
|
|
||||||
def geom_output(func, argtypes):
|
class GeomOutput(GEOSFuncFactory):
|
||||||
"For GEOS routines that return a geometry."
|
"For GEOS routines that return a geometry."
|
||||||
if argtypes:
|
restype = GEOM_PTR
|
||||||
func.argtypes = argtypes
|
errcheck = staticmethod(check_geom)
|
||||||
func.restype = GEOM_PTR
|
|
||||||
func.errcheck = check_geom
|
def get_func(self, argtypes):
|
||||||
return func
|
self.argtypes = argtypes
|
||||||
|
return super(GeomOutput, self).get_func()
|
||||||
|
|
||||||
|
|
||||||
def geom_index(func):
|
class IntFromGeom(GEOSFuncFactory):
|
||||||
"For GEOS routines that return geometries from an index."
|
|
||||||
return geom_output(func, [GEOM_PTR, c_int])
|
|
||||||
|
|
||||||
|
|
||||||
def int_from_geom(func, zero=False):
|
|
||||||
"Argument is a geometry, return type is an integer."
|
"Argument is a geometry, return type is an integer."
|
||||||
func.argtypes = [GEOM_PTR]
|
argtypes = [GEOM_PTR]
|
||||||
func.restype = c_int
|
restype = c_int
|
||||||
if zero:
|
|
||||||
func.errcheck = check_zero
|
def get_func(self, zero=False):
|
||||||
else:
|
if zero:
|
||||||
func.errcheck = check_minus_one
|
self.errcheck = check_zero
|
||||||
return func
|
else:
|
||||||
|
self.errcheck = check_minus_one
|
||||||
|
return super(IntFromGeom, self).get_func()
|
||||||
|
|
||||||
|
|
||||||
def string_from_geom(func):
|
class StringFromGeom(GEOSFuncFactory):
|
||||||
"Argument is a Geometry, return type is a string."
|
"Argument is a Geometry, return type is a string."
|
||||||
func.argtypes = [GEOM_PTR]
|
argtypes = [GEOM_PTR]
|
||||||
func.restype = geos_char_p
|
restype = geos_char_p
|
||||||
func.errcheck = check_string
|
errcheck = staticmethod(check_string)
|
||||||
return func
|
|
||||||
|
|
||||||
# ### ctypes prototypes ###
|
# ### ctypes prototypes ###
|
||||||
|
|
||||||
# Deprecated creation routines from WKB, HEX, WKT
|
# Deprecated creation routines from WKB, HEX, WKT
|
||||||
from_hex = bin_constructor(GEOSFunc('GEOSGeomFromHEX_buf'))
|
from_hex = BinConstructor('GEOSGeomFromHEX_buf')
|
||||||
from_wkb = bin_constructor(GEOSFunc('GEOSGeomFromWKB_buf'))
|
from_wkb = BinConstructor('GEOSGeomFromWKB_buf')
|
||||||
from_wkt = geom_output(GEOSFunc('GEOSGeomFromWKT'), [c_char_p])
|
from_wkt = GeomOutput('GEOSGeomFromWKT', [c_char_p])
|
||||||
|
|
||||||
# Deprecated output routines
|
# Deprecated output routines
|
||||||
to_hex = bin_output(GEOSFunc('GEOSGeomToHEX_buf'))
|
to_hex = BinOutput('GEOSGeomToHEX_buf')
|
||||||
to_wkb = bin_output(GEOSFunc('GEOSGeomToWKB_buf'))
|
to_wkb = BinOutput('GEOSGeomToWKB_buf')
|
||||||
to_wkt = string_from_geom(GEOSFunc('GEOSGeomToWKT'))
|
to_wkt = StringFromGeom('GEOSGeomToWKT')
|
||||||
|
|
||||||
# The GEOS geometry type, typeid, num_coordites and number of geometries
|
# The GEOS geometry type, typeid, num_coordites and number of geometries
|
||||||
geos_normalize = int_from_geom(GEOSFunc('GEOSNormalize'))
|
geos_normalize = IntFromGeom('GEOSNormalize')
|
||||||
geos_type = string_from_geom(GEOSFunc('GEOSGeomType'))
|
geos_type = StringFromGeom('GEOSGeomType')
|
||||||
geos_typeid = int_from_geom(GEOSFunc('GEOSGeomTypeId'))
|
geos_typeid = IntFromGeom('GEOSGeomTypeId')
|
||||||
get_dims = int_from_geom(GEOSFunc('GEOSGeom_getDimensions'), zero=True)
|
get_dims = IntFromGeom('GEOSGeom_getDimensions', zero=True)
|
||||||
get_num_coords = int_from_geom(GEOSFunc('GEOSGetNumCoordinates'))
|
get_num_coords = IntFromGeom('GEOSGetNumCoordinates')
|
||||||
get_num_geoms = int_from_geom(GEOSFunc('GEOSGetNumGeometries'))
|
get_num_geoms = IntFromGeom('GEOSGetNumGeometries')
|
||||||
|
|
||||||
# Geometry creation factories
|
# Geometry creation factories
|
||||||
create_point = geom_output(GEOSFunc('GEOSGeom_createPoint'), [CS_PTR])
|
create_point = GeomOutput('GEOSGeom_createPoint', [CS_PTR])
|
||||||
create_linestring = geom_output(GEOSFunc('GEOSGeom_createLineString'), [CS_PTR])
|
create_linestring = GeomOutput('GEOSGeom_createLineString', [CS_PTR])
|
||||||
create_linearring = geom_output(GEOSFunc('GEOSGeom_createLinearRing'), [CS_PTR])
|
create_linearring = GeomOutput('GEOSGeom_createLinearRing', [CS_PTR])
|
||||||
|
|
||||||
# Polygon and collection creation routines are special and will not
|
# Polygon and collection creation routines are special and will not
|
||||||
# have their argument types defined.
|
# have their argument types defined.
|
||||||
create_polygon = geom_output(GEOSFunc('GEOSGeom_createPolygon'), None)
|
create_polygon = GeomOutput('GEOSGeom_createPolygon', None)
|
||||||
create_collection = geom_output(GEOSFunc('GEOSGeom_createCollection'), None)
|
create_collection = GeomOutput('GEOSGeom_createCollection', None)
|
||||||
|
|
||||||
# Ring routines
|
# Ring routines
|
||||||
get_extring = geom_output(GEOSFunc('GEOSGetExteriorRing'), [GEOM_PTR])
|
get_extring = GeomOutput('GEOSGetExteriorRing', [GEOM_PTR])
|
||||||
get_intring = geom_index(GEOSFunc('GEOSGetInteriorRingN'))
|
get_intring = GeomOutput('GEOSGetInteriorRingN', [GEOM_PTR, c_int])
|
||||||
get_nrings = int_from_geom(GEOSFunc('GEOSGetNumInteriorRings'))
|
get_nrings = IntFromGeom('GEOSGetNumInteriorRings')
|
||||||
|
|
||||||
# Collection Routines
|
# Collection Routines
|
||||||
get_geomn = geom_index(GEOSFunc('GEOSGetGeometryN'))
|
get_geomn = GeomOutput('GEOSGetGeometryN', [GEOM_PTR, c_int])
|
||||||
|
|
||||||
# Cloning
|
# Cloning
|
||||||
geom_clone = GEOSFunc('GEOSGeom_clone')
|
geom_clone = GEOSFuncFactory('GEOSGeom_clone', argtypes=[GEOM_PTR], restype=GEOM_PTR)
|
||||||
geom_clone.argtypes = [GEOM_PTR]
|
|
||||||
geom_clone.restype = GEOM_PTR
|
|
||||||
|
|
||||||
# Destruction routine.
|
# Destruction routine.
|
||||||
destroy_geom = GEOSFunc('GEOSGeom_destroy')
|
destroy_geom = GEOSFuncFactory('GEOSGeom_destroy', argtypes=[GEOM_PTR])
|
||||||
destroy_geom.argtypes = [GEOM_PTR]
|
|
||||||
destroy_geom.restype = None
|
|
||||||
|
|
||||||
# SRID routines
|
# SRID routines
|
||||||
geos_get_srid = GEOSFunc('GEOSGetSRID')
|
geos_get_srid = GEOSFuncFactory('GEOSGetSRID', argtypes=[GEOM_PTR], restype=c_int)
|
||||||
geos_get_srid.argtypes = [GEOM_PTR]
|
geos_set_srid = GEOSFuncFactory('GEOSSetSRID', argtypes=[GEOM_PTR, c_int])
|
||||||
geos_get_srid.restype = c_int
|
|
||||||
|
|
||||||
geos_set_srid = GEOSFunc('GEOSSetSRID')
|
|
||||||
geos_set_srid.argtypes = [GEOM_PTR, c_int]
|
|
||||||
geos_set_srid.restype = None
|
|
||||||
|
|
|
@ -2,12 +2,11 @@ import threading
|
||||||
from ctypes import POINTER, Structure, byref, c_char, c_char_p, c_int, c_size_t
|
from ctypes import POINTER, Structure, byref, c_char, c_char_p, c_int, c_size_t
|
||||||
|
|
||||||
from django.contrib.gis.geos.base import GEOSBase
|
from django.contrib.gis.geos.base import GEOSBase
|
||||||
from django.contrib.gis.geos.libgeos import GEOM_PTR
|
from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory
|
||||||
from django.contrib.gis.geos.prototypes.errcheck import (
|
from django.contrib.gis.geos.prototypes.errcheck import (
|
||||||
check_geom, check_sized_string, check_string,
|
check_geom, check_sized_string, check_string,
|
||||||
)
|
)
|
||||||
from django.contrib.gis.geos.prototypes.geom import c_uchar_p, geos_char_p
|
from django.contrib.gis.geos.prototypes.geom import c_uchar_p, geos_char_p
|
||||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.encoding import force_bytes
|
from django.utils.encoding import force_bytes
|
||||||
|
|
||||||
|
@ -34,99 +33,90 @@ WKB_READ_PTR = POINTER(WKBReader_st)
|
||||||
WKB_WRITE_PTR = POINTER(WKBReader_st)
|
WKB_WRITE_PTR = POINTER(WKBReader_st)
|
||||||
|
|
||||||
# WKTReader routines
|
# WKTReader routines
|
||||||
wkt_reader_create = GEOSFunc('GEOSWKTReader_create')
|
wkt_reader_create = GEOSFuncFactory('GEOSWKTReader_create', restype=WKT_READ_PTR)
|
||||||
wkt_reader_create.restype = WKT_READ_PTR
|
wkt_reader_destroy = GEOSFuncFactory('GEOSWKTReader_destroy', argtypes=[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
|
|
||||||
|
|
||||||
|
wkt_reader_read = GEOSFuncFactory(
|
||||||
|
'GEOSWKTReader_read', argtypes=[WKT_READ_PTR, c_char_p], restype=GEOM_PTR, errcheck=check_geom
|
||||||
|
)
|
||||||
# WKTWriter routines
|
# WKTWriter routines
|
||||||
wkt_writer_create = GEOSFunc('GEOSWKTWriter_create')
|
wkt_writer_create = GEOSFuncFactory('GEOSWKTWriter_create', restype=WKT_WRITE_PTR)
|
||||||
wkt_writer_create.restype = WKT_WRITE_PTR
|
wkt_writer_destroy = GEOSFuncFactory('GEOSWKTWriter_destroy', argtypes=[WKT_WRITE_PTR])
|
||||||
|
|
||||||
wkt_writer_destroy = GEOSFunc('GEOSWKTWriter_destroy')
|
wkt_writer_write = GEOSFuncFactory(
|
||||||
wkt_writer_destroy.argtypes = [WKT_WRITE_PTR]
|
'GEOSWKTWriter_write', argtypes=[WKT_WRITE_PTR, GEOM_PTR], restype=geos_char_p, errcheck=check_string
|
||||||
|
)
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
try:
|
class WKTOutputDim(GEOSFuncFactory):
|
||||||
wkt_writer_get_outdim = GEOSFunc('GEOSWKTWriter_getOutputDimension')
|
def get_func(self, *args, **kwargs):
|
||||||
wkt_writer_get_outdim.argtypes = [WKT_WRITE_PTR]
|
try:
|
||||||
wkt_writer_get_outdim.restype = c_int
|
return super(WKTOutputDim, self).get_func(*args, **kwargs)
|
||||||
wkt_writer_set_outdim = GEOSFunc('GEOSWKTWriter_setOutputDimension')
|
except AttributeError:
|
||||||
wkt_writer_set_outdim.argtypes = [WKT_WRITE_PTR, c_int]
|
# GEOSWKTWriter_get/setOutputDimension has been introduced in GEOS 3.3.0
|
||||||
except AttributeError:
|
# Always return 2 if not available
|
||||||
# GEOSWKTWriter_get/setOutputDimension has been introduced in GEOS 3.3.0
|
return {
|
||||||
# Always return 2 if not available
|
'GEOSWKTWriter_getOutputDimension': lambda ptr: 2,
|
||||||
wkt_writer_get_outdim = lambda ptr: 2
|
'GEOSWKTWriter_setOutputDimension': lambda ptr, dim: None,
|
||||||
wkt_writer_set_outdim = lambda ptr, dim: None
|
}.get(self.func_name)
|
||||||
|
|
||||||
|
wkt_writer_get_outdim = WKTOutputDim(
|
||||||
|
'GEOSWKTWriter_getOutputDimension', argtypes=[WKT_WRITE_PTR], restype=c_int
|
||||||
|
)
|
||||||
|
wkt_writer_set_outdim = WKTOutputDim(
|
||||||
|
'GEOSWKTWriter_setOutputDimension', argtypes=[WKT_WRITE_PTR, c_int]
|
||||||
|
)
|
||||||
|
|
||||||
# WKBReader routines
|
# WKBReader routines
|
||||||
wkb_reader_create = GEOSFunc('GEOSWKBReader_create')
|
wkb_reader_create = GEOSFuncFactory('GEOSWKBReader_create', restype=WKB_READ_PTR)
|
||||||
wkb_reader_create.restype = WKB_READ_PTR
|
wkb_reader_destroy = GEOSFuncFactory('GEOSWKBReader_destroy', argtypes=[WKB_READ_PTR])
|
||||||
|
|
||||||
wkb_reader_destroy = GEOSFunc('GEOSWKBReader_destroy')
|
|
||||||
wkb_reader_destroy.argtypes = [WKB_READ_PTR]
|
|
||||||
|
|
||||||
|
|
||||||
def wkb_read_func(func):
|
class WKBReadFunc(GEOSFuncFactory):
|
||||||
# Although the function definitions take `const unsigned char *`
|
# Although the function definitions take `const unsigned char *`
|
||||||
# as their parameter, we use c_char_p here so the function may
|
# as their parameter, we use c_char_p here so the function may
|
||||||
# take Python strings directly as parameters. Inside Python there
|
# take Python strings directly as parameters. Inside Python there
|
||||||
# is not a difference between signed and unsigned characters, so
|
# is not a difference between signed and unsigned characters, so
|
||||||
# it is not a problem.
|
# it is not a problem.
|
||||||
func.argtypes = [WKB_READ_PTR, c_char_p, c_size_t]
|
argtypes = [WKB_READ_PTR, c_char_p, c_size_t]
|
||||||
func.restype = GEOM_PTR
|
restype = GEOM_PTR
|
||||||
func.errcheck = check_geom
|
errcheck = staticmethod(check_geom)
|
||||||
return func
|
|
||||||
|
|
||||||
wkb_reader_read = wkb_read_func(GEOSFunc('GEOSWKBReader_read'))
|
|
||||||
wkb_reader_read_hex = wkb_read_func(GEOSFunc('GEOSWKBReader_readHEX'))
|
wkb_reader_read = WKBReadFunc('GEOSWKBReader_read')
|
||||||
|
wkb_reader_read_hex = WKBReadFunc('GEOSWKBReader_readHEX')
|
||||||
|
|
||||||
# WKBWriter routines
|
# WKBWriter routines
|
||||||
wkb_writer_create = GEOSFunc('GEOSWKBWriter_create')
|
wkb_writer_create = GEOSFuncFactory('GEOSWKBWriter_create', restype=WKB_WRITE_PTR)
|
||||||
wkb_writer_create.restype = WKB_WRITE_PTR
|
wkb_writer_destroy = GEOSFuncFactory('GEOSWKBWriter_destroy', argtypes=[WKB_WRITE_PTR])
|
||||||
|
|
||||||
wkb_writer_destroy = GEOSFunc('GEOSWKBWriter_destroy')
|
|
||||||
wkb_writer_destroy.argtypes = [WKB_WRITE_PTR]
|
|
||||||
|
|
||||||
|
|
||||||
# WKB Writing prototypes.
|
# WKB Writing prototypes.
|
||||||
def wkb_write_func(func):
|
class WKBWriteFunc(GEOSFuncFactory):
|
||||||
func.argtypes = [WKB_WRITE_PTR, GEOM_PTR, POINTER(c_size_t)]
|
argtypes = [WKB_WRITE_PTR, GEOM_PTR, POINTER(c_size_t)]
|
||||||
func.restype = c_uchar_p
|
restype = c_uchar_p
|
||||||
func.errcheck = check_sized_string
|
errcheck = staticmethod(check_sized_string)
|
||||||
return func
|
|
||||||
|
|
||||||
wkb_writer_write = wkb_write_func(GEOSFunc('GEOSWKBWriter_write'))
|
|
||||||
wkb_writer_write_hex = wkb_write_func(GEOSFunc('GEOSWKBWriter_writeHEX'))
|
wkb_writer_write = WKBWriteFunc('GEOSWKBWriter_write')
|
||||||
|
wkb_writer_write_hex = WKBWriteFunc('GEOSWKBWriter_writeHEX')
|
||||||
|
|
||||||
|
|
||||||
# WKBWriter property getter/setter prototypes.
|
# WKBWriter property getter/setter prototypes.
|
||||||
def wkb_writer_get(func, restype=c_int):
|
class WKBWriterGet(GEOSFuncFactory):
|
||||||
func.argtypes = [WKB_WRITE_PTR]
|
argtypes = [WKB_WRITE_PTR]
|
||||||
func.restype = restype
|
restype = c_int
|
||||||
return func
|
|
||||||
|
|
||||||
|
|
||||||
def wkb_writer_set(func, argtype=c_int):
|
class WKBWriterSet(GEOSFuncFactory):
|
||||||
func.argtypes = [WKB_WRITE_PTR, argtype]
|
argtypes = [WKB_WRITE_PTR, c_int]
|
||||||
return func
|
|
||||||
|
|
||||||
wkb_writer_get_byteorder = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getByteOrder'))
|
wkb_writer_get_byteorder = WKBWriterGet('GEOSWKBWriter_getByteOrder')
|
||||||
wkb_writer_set_byteorder = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setByteOrder'))
|
wkb_writer_set_byteorder = WKBWriterSet('GEOSWKBWriter_setByteOrder')
|
||||||
wkb_writer_get_outdim = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getOutputDimension'))
|
wkb_writer_get_outdim = WKBWriterGet('GEOSWKBWriter_getOutputDimension')
|
||||||
wkb_writer_set_outdim = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setOutputDimension'))
|
wkb_writer_set_outdim = WKBWriterSet('GEOSWKBWriter_setOutputDimension')
|
||||||
wkb_writer_get_include_srid = wkb_writer_get(GEOSFunc('GEOSWKBWriter_getIncludeSRID'), restype=c_char)
|
wkb_writer_get_include_srid = WKBWriterGet('GEOSWKBWriter_getIncludeSRID', restype=c_char)
|
||||||
wkb_writer_set_include_srid = wkb_writer_set(GEOSFunc('GEOSWKBWriter_setIncludeSRID'), argtype=c_char)
|
wkb_writer_set_include_srid = WKBWriterSet('GEOSWKBWriter_setIncludeSRID', argtypes=[WKB_WRITE_PTR, c_char])
|
||||||
|
|
||||||
|
|
||||||
# ### Base I/O Class ###
|
# ### Base I/O Class ###
|
||||||
|
|
|
@ -4,35 +4,35 @@
|
||||||
"""
|
"""
|
||||||
from ctypes import POINTER, c_double, c_int
|
from ctypes import POINTER, c_double, c_int
|
||||||
|
|
||||||
from django.contrib.gis.geos.libgeos import GEOM_PTR
|
from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory
|
||||||
from django.contrib.gis.geos.prototypes.errcheck import check_dbl, check_string
|
from django.contrib.gis.geos.prototypes.errcheck import check_dbl, check_string
|
||||||
from django.contrib.gis.geos.prototypes.geom import geos_char_p
|
from django.contrib.gis.geos.prototypes.geom import geos_char_p
|
||||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
|
||||||
from django.utils.six.moves import range
|
from django.utils.six.moves import range
|
||||||
|
|
||||||
__all__ = ['geos_area', 'geos_distance', 'geos_length', 'geos_isvalidreason']
|
__all__ = ['geos_area', 'geos_distance', 'geos_length', 'geos_isvalidreason']
|
||||||
|
|
||||||
|
|
||||||
# ### ctypes generator function ###
|
class DblFromGeom(GEOSFuncFactory):
|
||||||
def dbl_from_geom(func, num_geom=1):
|
|
||||||
"""
|
"""
|
||||||
Argument is a Geometry, return type is double that is passed
|
Argument is a Geometry, return type is double that is passed
|
||||||
in by reference as the last argument.
|
in by reference as the last argument.
|
||||||
"""
|
"""
|
||||||
argtypes = [GEOM_PTR for i in range(num_geom)]
|
restype = c_int # Status code returned
|
||||||
argtypes += [POINTER(c_double)]
|
errcheck = staticmethod(check_dbl)
|
||||||
func.argtypes = argtypes
|
|
||||||
func.restype = c_int # Status code returned
|
def get_func(self, num_geom=1):
|
||||||
func.errcheck = check_dbl
|
argtypes = [GEOM_PTR for i in range(num_geom)]
|
||||||
return func
|
argtypes += [POINTER(c_double)]
|
||||||
|
self.argtypes = argtypes
|
||||||
|
return super(DblFromGeom, self).get_func()
|
||||||
|
|
||||||
|
|
||||||
# ### ctypes prototypes ###
|
# ### ctypes prototypes ###
|
||||||
|
|
||||||
# Area, distance, and length prototypes.
|
# Area, distance, and length prototypes.
|
||||||
geos_area = dbl_from_geom(GEOSFunc('GEOSArea'))
|
geos_area = DblFromGeom('GEOSArea')
|
||||||
geos_distance = dbl_from_geom(GEOSFunc('GEOSDistance'), num_geom=2)
|
geos_distance = DblFromGeom('GEOSDistance', num_geom=2)
|
||||||
geos_length = dbl_from_geom(GEOSFunc('GEOSLength'))
|
geos_length = DblFromGeom('GEOSLength')
|
||||||
geos_isvalidreason = GEOSFunc('GEOSisValidReason')
|
geos_isvalidreason = GEOSFuncFactory(
|
||||||
geos_isvalidreason.argtypes = [GEOM_PTR]
|
'GEOSisValidReason', restype=geos_char_p, errcheck=check_string, argtypes=[GEOM_PTR]
|
||||||
geos_isvalidreason.restype = geos_char_p
|
)
|
||||||
geos_isvalidreason.errcheck = check_string
|
|
||||||
|
|
|
@ -4,45 +4,38 @@
|
||||||
"""
|
"""
|
||||||
from ctypes import c_char, c_char_p, c_double
|
from ctypes import c_char, c_char_p, c_double
|
||||||
|
|
||||||
from django.contrib.gis.geos.libgeos import GEOM_PTR
|
from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory
|
||||||
from django.contrib.gis.geos.prototypes.errcheck import check_predicate
|
from django.contrib.gis.geos.prototypes.errcheck import check_predicate
|
||||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
|
||||||
|
|
||||||
|
|
||||||
# ## Binary & unary predicate functions ##
|
# ## Binary & unary predicate factories ##
|
||||||
def binary_predicate(func, *args):
|
class UnaryPredicate(GEOSFuncFactory):
|
||||||
|
"For GEOS unary predicate functions."
|
||||||
|
argtypes = [GEOM_PTR]
|
||||||
|
restype = c_char
|
||||||
|
errcheck = staticmethod(check_predicate)
|
||||||
|
|
||||||
|
|
||||||
|
class BinaryPredicate(UnaryPredicate):
|
||||||
"For GEOS binary predicate functions."
|
"For GEOS binary predicate functions."
|
||||||
argtypes = [GEOM_PTR, GEOM_PTR]
|
argtypes = [GEOM_PTR, GEOM_PTR]
|
||||||
if args:
|
|
||||||
argtypes += args
|
|
||||||
func.argtypes = argtypes
|
|
||||||
func.restype = c_char
|
|
||||||
func.errcheck = check_predicate
|
|
||||||
return func
|
|
||||||
|
|
||||||
|
|
||||||
def unary_predicate(func):
|
|
||||||
"For GEOS unary predicate functions."
|
|
||||||
func.argtypes = [GEOM_PTR]
|
|
||||||
func.restype = c_char
|
|
||||||
func.errcheck = check_predicate
|
|
||||||
return func
|
|
||||||
|
|
||||||
# ## Unary Predicates ##
|
# ## Unary Predicates ##
|
||||||
geos_hasz = unary_predicate(GEOSFunc('GEOSHasZ'))
|
geos_hasz = UnaryPredicate('GEOSHasZ')
|
||||||
geos_isempty = unary_predicate(GEOSFunc('GEOSisEmpty'))
|
geos_isempty = UnaryPredicate('GEOSisEmpty')
|
||||||
geos_isring = unary_predicate(GEOSFunc('GEOSisRing'))
|
geos_isring = UnaryPredicate('GEOSisRing')
|
||||||
geos_issimple = unary_predicate(GEOSFunc('GEOSisSimple'))
|
geos_issimple = UnaryPredicate('GEOSisSimple')
|
||||||
geos_isvalid = unary_predicate(GEOSFunc('GEOSisValid'))
|
geos_isvalid = UnaryPredicate('GEOSisValid')
|
||||||
|
|
||||||
# ## Binary Predicates ##
|
# ## Binary Predicates ##
|
||||||
geos_contains = binary_predicate(GEOSFunc('GEOSContains'))
|
geos_contains = BinaryPredicate('GEOSContains')
|
||||||
geos_crosses = binary_predicate(GEOSFunc('GEOSCrosses'))
|
geos_crosses = BinaryPredicate('GEOSCrosses')
|
||||||
geos_disjoint = binary_predicate(GEOSFunc('GEOSDisjoint'))
|
geos_disjoint = BinaryPredicate('GEOSDisjoint')
|
||||||
geos_equals = binary_predicate(GEOSFunc('GEOSEquals'))
|
geos_equals = BinaryPredicate('GEOSEquals')
|
||||||
geos_equalsexact = binary_predicate(GEOSFunc('GEOSEqualsExact'), c_double)
|
geos_equalsexact = BinaryPredicate('GEOSEqualsExact', argtypes=[GEOM_PTR, GEOM_PTR, c_double])
|
||||||
geos_intersects = binary_predicate(GEOSFunc('GEOSIntersects'))
|
geos_intersects = BinaryPredicate('GEOSIntersects')
|
||||||
geos_overlaps = binary_predicate(GEOSFunc('GEOSOverlaps'))
|
geos_overlaps = BinaryPredicate('GEOSOverlaps')
|
||||||
geos_relatepattern = binary_predicate(GEOSFunc('GEOSRelatePattern'), c_char_p)
|
geos_relatepattern = BinaryPredicate('GEOSRelatePattern', argtypes=[GEOM_PTR, GEOM_PTR, c_char_p])
|
||||||
geos_touches = binary_predicate(GEOSFunc('GEOSTouches'))
|
geos_touches = BinaryPredicate('GEOSTouches')
|
||||||
geos_within = binary_predicate(GEOSFunc('GEOSWithin'))
|
geos_within = BinaryPredicate('GEOSWithin')
|
||||||
|
|
|
@ -1,36 +1,30 @@
|
||||||
from ctypes import c_char
|
from ctypes import c_char
|
||||||
|
|
||||||
from django.contrib.gis.geos.libgeos import (
|
from django.contrib.gis.geos.libgeos import (
|
||||||
GEOM_PTR, PREPGEOM_PTR, geos_version_info,
|
GEOM_PTR, PREPGEOM_PTR, GEOSFuncFactory,
|
||||||
)
|
)
|
||||||
from django.contrib.gis.geos.prototypes.errcheck import check_predicate
|
from django.contrib.gis.geos.prototypes.errcheck import check_predicate
|
||||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
|
||||||
|
|
||||||
# Prepared geometry constructor and destructors.
|
# Prepared geometry constructor and destructors.
|
||||||
geos_prepare = GEOSFunc('GEOSPrepare')
|
geos_prepare = GEOSFuncFactory('GEOSPrepare', argtypes=[GEOM_PTR], restype=PREPGEOM_PTR)
|
||||||
geos_prepare.argtypes = [GEOM_PTR]
|
prepared_destroy = GEOSFuncFactory('GEOSPreparedGeom_destroy', argtpes=[PREPGEOM_PTR])
|
||||||
geos_prepare.restype = PREPGEOM_PTR
|
|
||||||
|
|
||||||
prepared_destroy = GEOSFunc('GEOSPreparedGeom_destroy')
|
|
||||||
prepared_destroy.argtpes = [PREPGEOM_PTR]
|
|
||||||
prepared_destroy.restype = None
|
|
||||||
|
|
||||||
|
|
||||||
# Prepared geometry binary predicate support.
|
# Prepared geometry binary predicate support.
|
||||||
def prepared_predicate(func):
|
class PreparedPredicate(GEOSFuncFactory):
|
||||||
func.argtypes = [PREPGEOM_PTR, GEOM_PTR]
|
argtypes = [PREPGEOM_PTR, GEOM_PTR]
|
||||||
func.restype = c_char
|
restype = c_char
|
||||||
func.errcheck = check_predicate
|
errcheck = staticmethod(check_predicate)
|
||||||
return func
|
|
||||||
|
|
||||||
prepared_contains = prepared_predicate(GEOSFunc('GEOSPreparedContains'))
|
|
||||||
prepared_contains_properly = prepared_predicate(GEOSFunc('GEOSPreparedContainsProperly'))
|
|
||||||
prepared_covers = prepared_predicate(GEOSFunc('GEOSPreparedCovers'))
|
|
||||||
prepared_intersects = prepared_predicate(GEOSFunc('GEOSPreparedIntersects'))
|
|
||||||
|
|
||||||
if geos_version_info()['version'] > '3.3.0':
|
prepared_contains = PreparedPredicate('GEOSPreparedContains')
|
||||||
prepared_crosses = prepared_predicate(GEOSFunc('GEOSPreparedCrosses'))
|
prepared_contains_properly = PreparedPredicate('GEOSPreparedContainsProperly')
|
||||||
prepared_disjoint = prepared_predicate(GEOSFunc('GEOSPreparedDisjoint'))
|
prepared_covers = PreparedPredicate('GEOSPreparedCovers')
|
||||||
prepared_overlaps = prepared_predicate(GEOSFunc('GEOSPreparedOverlaps'))
|
prepared_intersects = PreparedPredicate('GEOSPreparedIntersects')
|
||||||
prepared_touches = prepared_predicate(GEOSFunc('GEOSPreparedTouches'))
|
|
||||||
prepared_within = prepared_predicate(GEOSFunc('GEOSPreparedWithin'))
|
# Functions added in GEOS 3.3
|
||||||
|
prepared_crosses = PreparedPredicate('GEOSPreparedCrosses')
|
||||||
|
prepared_disjoint = PreparedPredicate('GEOSPreparedDisjoint')
|
||||||
|
prepared_overlaps = PreparedPredicate('GEOSPreparedOverlaps')
|
||||||
|
prepared_touches = PreparedPredicate('GEOSPreparedTouches')
|
||||||
|
prepared_within = PreparedPredicate('GEOSPreparedWithin')
|
||||||
|
|
|
@ -2,64 +2,51 @@
|
||||||
This module houses the GEOS ctypes prototype functions for the
|
This module houses the GEOS ctypes prototype functions for the
|
||||||
topological operations on geometries.
|
topological operations on geometries.
|
||||||
"""
|
"""
|
||||||
__all__ = ['geos_boundary', 'geos_buffer', 'geos_cascaded_union',
|
|
||||||
'geos_centroid', 'geos_convexhull', 'geos_difference',
|
|
||||||
'geos_envelope', 'geos_intersection', 'geos_linemerge',
|
|
||||||
'geos_pointonsurface', 'geos_preservesimplify', 'geos_simplify',
|
|
||||||
'geos_symdifference', 'geos_union', 'geos_relate',
|
|
||||||
'geos_project', 'geos_interpolate', 'geos_project_normalized',
|
|
||||||
'geos_interpolate_normalized']
|
|
||||||
|
|
||||||
from ctypes import c_double, c_int
|
from ctypes import c_double, c_int
|
||||||
|
|
||||||
from django.contrib.gis.geos.libgeos import GEOM_PTR
|
from django.contrib.gis.geos.libgeos import GEOM_PTR, GEOSFuncFactory
|
||||||
from django.contrib.gis.geos.prototypes.errcheck import (
|
from django.contrib.gis.geos.prototypes.errcheck import (
|
||||||
check_geom, check_minus_one, check_string,
|
check_geom, check_minus_one, check_string,
|
||||||
)
|
)
|
||||||
from django.contrib.gis.geos.prototypes.geom import geos_char_p
|
from django.contrib.gis.geos.prototypes.geom import geos_char_p
|
||||||
from django.contrib.gis.geos.prototypes.threadsafe import GEOSFunc
|
|
||||||
|
|
||||||
|
|
||||||
def topology(func, *args, **kwargs):
|
class Topology(GEOSFuncFactory):
|
||||||
"For GEOS unary topology functions."
|
"For GEOS unary topology functions."
|
||||||
argtypes = [GEOM_PTR]
|
argtypes = [GEOM_PTR]
|
||||||
if args:
|
restype = GEOM_PTR
|
||||||
argtypes += args
|
errcheck = staticmethod(check_geom)
|
||||||
func.argtypes = argtypes
|
|
||||||
func.restype = kwargs.get('restype', GEOM_PTR)
|
|
||||||
func.errcheck = kwargs.get('errcheck', check_geom)
|
|
||||||
return func
|
|
||||||
|
|
||||||
# Topology Routines
|
# Topology Routines
|
||||||
geos_boundary = topology(GEOSFunc('GEOSBoundary'))
|
geos_boundary = Topology('GEOSBoundary')
|
||||||
geos_buffer = topology(GEOSFunc('GEOSBuffer'), c_double, c_int)
|
geos_buffer = Topology('GEOSBuffer', argtypes=[GEOM_PTR, c_double, c_int])
|
||||||
geos_centroid = topology(GEOSFunc('GEOSGetCentroid'))
|
geos_centroid = Topology('GEOSGetCentroid')
|
||||||
geos_convexhull = topology(GEOSFunc('GEOSConvexHull'))
|
geos_convexhull = Topology('GEOSConvexHull')
|
||||||
geos_difference = topology(GEOSFunc('GEOSDifference'), GEOM_PTR)
|
geos_difference = Topology('GEOSDifference', argtypes=[GEOM_PTR, GEOM_PTR])
|
||||||
geos_envelope = topology(GEOSFunc('GEOSEnvelope'))
|
geos_envelope = Topology('GEOSEnvelope')
|
||||||
geos_intersection = topology(GEOSFunc('GEOSIntersection'), GEOM_PTR)
|
geos_intersection = Topology('GEOSIntersection', argtypes=[GEOM_PTR, GEOM_PTR])
|
||||||
geos_linemerge = topology(GEOSFunc('GEOSLineMerge'))
|
geos_linemerge = Topology('GEOSLineMerge')
|
||||||
geos_pointonsurface = topology(GEOSFunc('GEOSPointOnSurface'))
|
geos_pointonsurface = Topology('GEOSPointOnSurface')
|
||||||
geos_preservesimplify = topology(GEOSFunc('GEOSTopologyPreserveSimplify'), c_double)
|
geos_preservesimplify = Topology('GEOSTopologyPreserveSimplify', argtypes=[GEOM_PTR, c_double])
|
||||||
geos_simplify = topology(GEOSFunc('GEOSSimplify'), c_double)
|
geos_simplify = Topology('GEOSSimplify', argtypes=[GEOM_PTR, c_double])
|
||||||
geos_symdifference = topology(GEOSFunc('GEOSSymDifference'), GEOM_PTR)
|
geos_symdifference = Topology('GEOSSymDifference', argtypes=[GEOM_PTR, GEOM_PTR])
|
||||||
geos_union = topology(GEOSFunc('GEOSUnion'), GEOM_PTR)
|
geos_union = Topology('GEOSUnion', argtypes=[GEOM_PTR, GEOM_PTR])
|
||||||
|
|
||||||
geos_cascaded_union = GEOSFunc('GEOSUnionCascaded')
|
geos_cascaded_union = GEOSFuncFactory('GEOSUnionCascaded', argtypes=[GEOM_PTR], restype=GEOM_PTR)
|
||||||
geos_cascaded_union.argtypes = [GEOM_PTR]
|
|
||||||
geos_cascaded_union.restype = GEOM_PTR
|
|
||||||
|
|
||||||
# GEOSRelate returns a string, not a geometry.
|
# GEOSRelate returns a string, not a geometry.
|
||||||
geos_relate = GEOSFunc('GEOSRelate')
|
geos_relate = GEOSFuncFactory(
|
||||||
geos_relate.argtypes = [GEOM_PTR, GEOM_PTR]
|
'GEOSRelate', argtypes=[GEOM_PTR, GEOM_PTR], restype=geos_char_p, errcheck=check_string
|
||||||
geos_relate.restype = geos_char_p
|
)
|
||||||
geos_relate.errcheck = check_string
|
|
||||||
|
|
||||||
# Linear referencing routines
|
# Linear referencing routines
|
||||||
geos_project = topology(GEOSFunc('GEOSProject'), GEOM_PTR,
|
geos_project = GEOSFuncFactory(
|
||||||
restype=c_double, errcheck=check_minus_one)
|
'GEOSProject', argtypes=[GEOM_PTR, GEOM_PTR], restype=c_double, errcheck=check_minus_one
|
||||||
geos_interpolate = topology(GEOSFunc('GEOSInterpolate'), c_double)
|
)
|
||||||
|
geos_interpolate = Topology('GEOSInterpolate', argtypes=[GEOM_PTR, c_double])
|
||||||
|
|
||||||
geos_project_normalized = topology(GEOSFunc('GEOSProjectNormalized'),
|
geos_project_normalized = GEOSFuncFactory(
|
||||||
GEOM_PTR, restype=c_double, errcheck=check_minus_one)
|
'GEOSProjectNormalized', argtypes=[GEOM_PTR, GEOM_PTR], restype=c_double, errcheck=check_minus_one
|
||||||
geos_interpolate_normalized = topology(GEOSFunc('GEOSInterpolateNormalized'), c_double)
|
)
|
||||||
|
geos_interpolate_normalized = Topology('GEOSInterpolateNormalized', argtypes=[GEOM_PTR, c_double])
|
||||||
|
|
|
@ -23,14 +23,14 @@ if HAS_GEOS:
|
||||||
class DistanceTest(TestCase):
|
class DistanceTest(TestCase):
|
||||||
fixtures = ['initial']
|
fixtures = ['initial']
|
||||||
|
|
||||||
if HAS_GEOS:
|
def setUp(self):
|
||||||
# A point we are testing distances with -- using a WGS84
|
# A point we are testing distances with -- using a WGS84
|
||||||
# coordinate that'll be implicitly transformed to that to
|
# coordinate that'll be implicitly transformed to that to
|
||||||
# the coordinate system of the field, EPSG:32140 (Texas South Central
|
# the coordinate system of the field, EPSG:32140 (Texas South Central
|
||||||
# w/units in meters)
|
# w/units in meters)
|
||||||
stx_pnt = GEOSGeometry('POINT (-95.370401017314293 29.704867409475465)', 4326)
|
self.stx_pnt = GEOSGeometry('POINT (-95.370401017314293 29.704867409475465)', 4326)
|
||||||
# Another one for Australia
|
# Another one for Australia
|
||||||
au_pnt = GEOSGeometry('POINT (150.791 -34.4919)', 4326)
|
self.au_pnt = GEOSGeometry('POINT (150.791 -34.4919)', 4326)
|
||||||
|
|
||||||
def get_names(self, qs):
|
def get_names(self, qs):
|
||||||
cities = [c.name for c in qs]
|
cities = [c.name for c in qs]
|
||||||
|
|
Loading…
Reference in New Issue