2008-08-06 02:13:06 +08:00
|
|
|
"""
|
|
|
|
This module houses the ctypes initialization procedures, as well
|
|
|
|
as the notice and error handler function callbacks (get called
|
|
|
|
when an error occurs in GEOS).
|
|
|
|
|
|
|
|
This module also houses GEOS Pointer utilities, including
|
|
|
|
get_pointer_arr(), and GEOM_PTR.
|
|
|
|
"""
|
2011-07-13 17:35:51 +08:00
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
2008-08-06 02:13:06 +08:00
|
|
|
from ctypes import c_char_p, Structure, CDLL, CFUNCTYPE, POINTER
|
|
|
|
from ctypes.util import find_library
|
|
|
|
from django.contrib.gis.geos.error import GEOSException
|
|
|
|
|
|
|
|
# Custom library path set?
|
|
|
|
try:
|
|
|
|
from django.conf import settings
|
|
|
|
lib_path = settings.GEOS_LIBRARY_PATH
|
|
|
|
except (AttributeError, EnvironmentError, ImportError):
|
|
|
|
lib_path = None
|
|
|
|
|
|
|
|
# Setting the appropriate names for the GEOS-C library.
|
|
|
|
if lib_path:
|
|
|
|
lib_names = None
|
|
|
|
elif os.name == 'nt':
|
|
|
|
# Windows NT libraries
|
2011-03-16 12:44:26 +08:00
|
|
|
lib_names = ['geos_c', 'libgeos_c-1']
|
2008-08-06 02:13:06 +08:00
|
|
|
elif os.name == 'posix':
|
|
|
|
# *NIX libraries
|
2008-12-27 00:02:45 +08:00
|
|
|
lib_names = ['geos_c', 'GEOS']
|
2008-08-06 02:13:06 +08:00
|
|
|
else:
|
2008-08-30 07:03:12 +08:00
|
|
|
raise ImportError('Unsupported OS "%s"' % os.name)
|
2008-08-06 02:13:06 +08:00
|
|
|
|
2009-05-18 00:45:28 +08:00
|
|
|
# Using the ctypes `find_library` utility to find the path to the GEOS
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
# shared library. This is better than manually specifiying each library name
|
2008-08-06 02:13:06 +08:00
|
|
|
# and extension (e.g., libgeos_c.[so|so.1|dylib].).
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
if lib_names:
|
2008-08-06 02:13:06 +08:00
|
|
|
for lib_name in lib_names:
|
|
|
|
lib_path = find_library(lib_name)
|
|
|
|
if not lib_path is None: break
|
|
|
|
|
|
|
|
# No GEOS library could be found.
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
if lib_path is None:
|
2008-08-30 07:03:12 +08:00
|
|
|
raise ImportError('Could not find the GEOS library (tried "%s"). '
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
'Try setting GEOS_LIBRARY_PATH in your settings.' %
|
2008-08-06 02:13:06 +08:00
|
|
|
'", "'.join(lib_names))
|
|
|
|
|
|
|
|
# Getting the GEOS C library. The C interface (CDLL) is used for
|
2010-01-13 02:40:54 +08:00
|
|
|
# both *NIX and Windows.
|
2008-08-06 02:13:06 +08:00
|
|
|
# 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.
|
2010-01-13 02:40:54 +08:00
|
|
|
# Supposed to mimic the GEOS message handler (C below):
|
|
|
|
# typedef void (*GEOSMessageHandler)(const char *fmt, ...);
|
2008-08-06 02:13:06 +08:00
|
|
|
NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
|
|
|
|
def notice_h(fmt, lst, output_h=sys.stdout):
|
2012-09-24 01:59:27 +08:00
|
|
|
fmt, lst = fmt.decode(), lst.decode()
|
2008-08-06 02:13:06 +08:00
|
|
|
try:
|
|
|
|
warn_msg = fmt % lst
|
|
|
|
except:
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
warn_msg = fmt
|
2008-08-06 02:13:06 +08:00
|
|
|
output_h.write('GEOS_NOTICE: %s\n' % warn_msg)
|
|
|
|
notice_h = NOTICEFUNC(notice_h)
|
|
|
|
|
|
|
|
ERRORFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
|
|
|
|
def error_h(fmt, lst, output_h=sys.stderr):
|
2012-09-24 01:59:27 +08:00
|
|
|
fmt, lst = fmt.decode(), lst.decode()
|
2008-08-06 02:13:06 +08:00
|
|
|
try:
|
|
|
|
err_msg = fmt % lst
|
|
|
|
except:
|
|
|
|
err_msg = fmt
|
|
|
|
output_h.write('GEOS_ERROR: %s\n' % err_msg)
|
|
|
|
error_h = ERRORFUNC(error_h)
|
|
|
|
|
|
|
|
#### GEOS Geometry C data structures, and utility functions. ####
|
|
|
|
|
|
|
|
# Opaque GEOS geometry structures, used for GEOM_PTR and CS_PTR
|
|
|
|
class GEOSGeom_t(Structure): pass
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
class GEOSPrepGeom_t(Structure): pass
|
2008-08-06 02:13:06 +08:00
|
|
|
class GEOSCoordSeq_t(Structure): pass
|
2010-01-13 02:40:54 +08:00
|
|
|
class GEOSContextHandle_t(Structure): pass
|
2008-08-06 02:13:06 +08:00
|
|
|
|
|
|
|
# Pointers to opaque GEOS geometry structures.
|
|
|
|
GEOM_PTR = POINTER(GEOSGeom_t)
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
PREPGEOM_PTR = POINTER(GEOSPrepGeom_t)
|
2008-08-06 02:13:06 +08:00
|
|
|
CS_PTR = POINTER(GEOSCoordSeq_t)
|
2010-01-13 02:40:54 +08:00
|
|
|
CONTEXT_PTR = POINTER(GEOSContextHandle_t)
|
2008-08-06 02:13:06 +08:00
|
|
|
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
# Used specifically by the GEOSGeom_createPolygon and GEOSGeom_createCollection
|
2008-08-06 02:13:06 +08:00
|
|
|
# GEOS routines
|
|
|
|
def get_pointer_arr(n):
|
|
|
|
"Gets a ctypes pointer array (of length `n`) for GEOSGeom_t opaque pointer."
|
|
|
|
GeomArr = GEOM_PTR * n
|
|
|
|
return GeomArr()
|
|
|
|
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
# Returns the string version of the GEOS library. Have to set the restype
|
2008-08-06 02:13:06 +08:00
|
|
|
# explicitly to c_char_p to ensure compatibility accross 32 and 64-bit platforms.
|
|
|
|
geos_version = lgeos.GEOSversion
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
geos_version.argtypes = None
|
2008-08-06 02:13:06 +08:00
|
|
|
geos_version.restype = c_char_p
|
|
|
|
|
|
|
|
# Regular expression should be able to parse version strings such as
|
2012-03-13 01:09:18 +08:00
|
|
|
# '3.0.0rc4-CAPI-1.3.3', '3.0.0-CAPI-1.4.1' or '3.4.0dev-CAPI-1.8.0'
|
|
|
|
version_regex = re.compile(r'^(?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<subminor>\d+))((rc(?P<release_candidate>\d+))|dev)?-CAPI-(?P<capi_version>\d+\.\d+\.\d+)$')
|
2008-08-06 02:13:06 +08:00
|
|
|
def geos_version_info():
|
|
|
|
"""
|
|
|
|
Returns a dictionary containing the various version metadata parsed from
|
|
|
|
the GEOS version string, including the version number, whether the version
|
|
|
|
is a release candidate (and what number release candidate), and the C API
|
|
|
|
version.
|
|
|
|
"""
|
2012-09-12 20:50:16 +08:00
|
|
|
ver = geos_version().decode()
|
2008-08-06 02:13:06 +08:00
|
|
|
m = version_regex.match(ver)
|
|
|
|
if not m: raise GEOSException('Could not parse version info string "%s"' % ver)
|
2009-12-24 22:53:51 +08:00
|
|
|
return dict((key, m.group(key)) for key in ('version', 'release_candidate', 'capi_version', 'major', 'minor', 'subminor'))
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
|
|
|
|
# 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'])
|
2009-12-24 22:53:51 +08:00
|
|
|
GEOS_SUBMINOR_VERSION = int(_verinfo['subminor'])
|
Refactored the GEOS interface. Improvements include:
* Geometries now allow list-like manipulation, e.g., can add, insert, delete vertexes (or other geometries in collections) like Python lists. Thanks, Aryeh Leib Taurog.
* Added support for GEOS prepared geometries via `prepared` property. Prepared geometries significantly speed up certain operations.
* Added support for GEOS cascaded union as `MultiPolygon.cascaded_union` property.
* Added support for GEOS line merge as `merged` property on `LineString`, and `MultiLineString` geometries. Thanks, Paul Smith.
* No longer use the deprecated C API for serialization to/from WKB and WKT. Now use the GEOS I/O classes, which are now exposed as `WKTReader`, `WKTWriter`, `WKBReader`, and `WKBWriter` (which supports 3D and SRID inclusion)
* Moved each type of geometry to their own module, eliminating the cluttered `geometries.py`.
* Internally, all C API methods are explicitly called from a module rather than a star import.
Fixed #9557, #9877, #10222
git-svn-id: http://code.djangoproject.com/svn/django/trunk@10131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2009-03-24 08:12:21 +08:00
|
|
|
del _verinfo
|
2009-12-24 22:53:51 +08:00
|
|
|
GEOS_VERSION = (GEOS_MAJOR_VERSION, GEOS_MINOR_VERSION, GEOS_SUBMINOR_VERSION)
|
|
|
|
GEOS_PREPARE = GEOS_VERSION >= (3, 1, 0)
|
2008-08-06 02:13:06 +08:00
|
|
|
|
2010-01-13 02:40:54 +08:00
|
|
|
if GEOS_PREPARE:
|
|
|
|
# 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]
|
|
|
|
else:
|
|
|
|
# When thread-safety isn't available, the initGEOS routine must be called
|
|
|
|
# first. This function takes the notice and error functions, defined
|
|
|
|
# as Python callbacks above, as parameters. Here is the C code that is
|
|
|
|
# wrapped:
|
|
|
|
# extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function, GEOSMessageHandler error_function);
|
|
|
|
lgeos.initGEOS(notice_h, error_h)
|
|
|
|
# Calling finishGEOS() upon exit of the interpreter.
|
|
|
|
import atexit
|
|
|
|
atexit.register(lgeos.finishGEOS)
|