app/django/contrib/gis/geos/libgeos.py
changeset 323 ff1a9aa48cfd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/contrib/gis/geos/libgeos.py	Tue Oct 14 16:00:59 2008 +0000
@@ -0,0 +1,126 @@
+"""
+ 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.
+"""
+import atexit, os, re, sys
+from ctypes import c_char_p, Structure, CDLL, CFUNCTYPE, POINTER
+from ctypes.util import find_library
+from django.contrib.gis.geos.error import GEOSException
+
+# NumPy supported?
+try:
+    from numpy import array, ndarray
+    HAS_NUMPY = True
+except ImportError:
+    HAS_NUMPY = False
+
+# 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
+    lib_names = ['libgeos_c-1']
+elif os.name == 'posix':
+    # *NIX libraries
+    lib_names = ['geos_c']
+else:
+    raise ImportError('Unsupported OS "%s"' % os.name)
+
+# Using the ctypes `find_library` utility to find the the path to the GEOS 
+# shared library.  This is better than manually specifiying each library name 
+# and extension (e.g., libgeos_c.[so|so.1|dylib].).
+if lib_names: 
+    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.
+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)
+
+# The notice and error handler C function callback definitions.
+#  Supposed to mimic the GEOS message handler (C below):
+#  "typedef void (*GEOSMessageHandler)(const char *fmt, ...);"
+NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
+def notice_h(fmt, lst, output_h=sys.stdout):
+    try:
+        warn_msg = fmt % lst
+    except:
+        warn_msg = fmt 
+    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):
+    try:
+        err_msg = fmt % lst
+    except:
+        err_msg = fmt
+    output_h.write('GEOS_ERROR: %s\n' % err_msg)
+error_h = ERRORFUNC(error_h)
+
+# The initGEOS routine should be called first, however, that routine takes
+#  the notice and error functions 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)
+
+#### GEOS Geometry C data structures, and utility functions. ####
+
+# Opaque GEOS geometry structures, used for GEOM_PTR and CS_PTR
+class GEOSGeom_t(Structure): pass
+class GEOSCoordSeq_t(Structure): pass
+
+# Pointers to opaque GEOS geometry structures.
+GEOM_PTR = POINTER(GEOSGeom_t)
+CS_PTR = POINTER(GEOSCoordSeq_t)
+
+# Used specifically by the GEOSGeom_createPolygon and GEOSGeom_createCollection 
+#  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()
+
+# Returns the string version of the GEOS library. Have to set the restype 
+# explicitly to c_char_p to ensure compatibility accross 32 and 64-bit platforms.
+geos_version = lgeos.GEOSversion
+geos_version.argtypes = None   
+geos_version.restype = c_char_p
+
+# Regular expression should be able to parse version strings such as
+# '3.0.0rc4-CAPI-1.3.3', or '3.0.0-CAPI-1.4.1'
+version_regex = re.compile(r'^(?P<version>\d+\.\d+\.\d+)(rc(?P<release_candidate>\d+))?-CAPI-(?P<capi_version>\d+\.\d+\.\d+)$')
+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.
+    """
+    ver = geos_version()
+    m = version_regex.match(ver)
+    if not m: raise GEOSException('Could not parse version info string "%s"' % ver)
+    return dict((key, m.group(key)) for key in ('version', 'release_candidate', 'capi_version'))
+
+# Calling the finishGEOS() upon exit of the interpreter.
+atexit.register(lgeos.finishGEOS)