web/lib/django/contrib/gis/geos/libgeos.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     4  when an error occurs in GEOS).
     4  when an error occurs in GEOS).
     5 
     5 
     6  This module also houses GEOS Pointer utilities, including
     6  This module also houses GEOS Pointer utilities, including
     7  get_pointer_arr(), and GEOM_PTR.
     7  get_pointer_arr(), and GEOM_PTR.
     8 """
     8 """
     9 import atexit, os, re, sys
     9 import os, re, sys
    10 from ctypes import c_char_p, Structure, CDLL, CFUNCTYPE, POINTER
    10 from ctypes import c_char_p, Structure, CDLL, CFUNCTYPE, POINTER
    11 from ctypes.util import find_library
    11 from ctypes.util import find_library
    12 from django.contrib.gis.geos.error import GEOSException
    12 from django.contrib.gis.geos.error import GEOSException
    13 
    13 
    14 # Custom library path set?
    14 # Custom library path set?
    43     raise ImportError('Could not find the GEOS library (tried "%s"). '
    43     raise ImportError('Could not find the GEOS library (tried "%s"). '
    44                         'Try setting GEOS_LIBRARY_PATH in your settings.' %
    44                         'Try setting GEOS_LIBRARY_PATH in your settings.' %
    45                         '", "'.join(lib_names))
    45                         '", "'.join(lib_names))
    46 
    46 
    47 # Getting the GEOS C library.  The C interface (CDLL) is used for
    47 # Getting the GEOS C library.  The C interface (CDLL) is used for
    48 #  both *NIX and Windows.
    48 # both *NIX and Windows.
    49 # See the GEOS C API source code for more details on the library function calls:
    49 # See the GEOS C API source code for more details on the library function calls:
    50 #  http://geos.refractions.net/ro/doxygen_docs/html/geos__c_8h-source.html
    50 #  http://geos.refractions.net/ro/doxygen_docs/html/geos__c_8h-source.html
    51 lgeos = CDLL(lib_path)
    51 lgeos = CDLL(lib_path)
    52 
    52 
    53 # The notice and error handler C function callback definitions.
    53 # The notice and error handler C function callback definitions.
    54 #  Supposed to mimic the GEOS message handler (C below):
    54 # Supposed to mimic the GEOS message handler (C below):
    55 #  "typedef void (*GEOSMessageHandler)(const char *fmt, ...);"
    55 #  typedef void (*GEOSMessageHandler)(const char *fmt, ...);
    56 NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
    56 NOTICEFUNC = CFUNCTYPE(None, c_char_p, c_char_p)
    57 def notice_h(fmt, lst, output_h=sys.stdout):
    57 def notice_h(fmt, lst, output_h=sys.stdout):
    58     try:
    58     try:
    59         warn_msg = fmt % lst
    59         warn_msg = fmt % lst
    60     except:
    60     except:
    69     except:
    69     except:
    70         err_msg = fmt
    70         err_msg = fmt
    71     output_h.write('GEOS_ERROR: %s\n' % err_msg)
    71     output_h.write('GEOS_ERROR: %s\n' % err_msg)
    72 error_h = ERRORFUNC(error_h)
    72 error_h = ERRORFUNC(error_h)
    73 
    73 
    74 # The initGEOS routine should be called first, however, that routine takes
       
    75 #  the notice and error functions as parameters.  Here is the C code that
       
    76 #  is wrapped:
       
    77 #  "extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function, GEOSMessageHandler error_function);"
       
    78 lgeos.initGEOS(notice_h, error_h)
       
    79 
       
    80 #### GEOS Geometry C data structures, and utility functions. ####
    74 #### GEOS Geometry C data structures, and utility functions. ####
    81 
    75 
    82 # Opaque GEOS geometry structures, used for GEOM_PTR and CS_PTR
    76 # Opaque GEOS geometry structures, used for GEOM_PTR and CS_PTR
    83 class GEOSGeom_t(Structure): pass
    77 class GEOSGeom_t(Structure): pass
    84 class GEOSPrepGeom_t(Structure): pass
    78 class GEOSPrepGeom_t(Structure): pass
    85 class GEOSCoordSeq_t(Structure): pass
    79 class GEOSCoordSeq_t(Structure): pass
       
    80 class GEOSContextHandle_t(Structure): pass
    86 
    81 
    87 # Pointers to opaque GEOS geometry structures.
    82 # Pointers to opaque GEOS geometry structures.
    88 GEOM_PTR = POINTER(GEOSGeom_t)
    83 GEOM_PTR = POINTER(GEOSGeom_t)
    89 PREPGEOM_PTR = POINTER(GEOSPrepGeom_t)
    84 PREPGEOM_PTR = POINTER(GEOSPrepGeom_t)
    90 CS_PTR = POINTER(GEOSCoordSeq_t)
    85 CS_PTR = POINTER(GEOSCoordSeq_t)
       
    86 CONTEXT_PTR  = POINTER(GEOSContextHandle_t)
    91 
    87 
    92 # Used specifically by the GEOSGeom_createPolygon and GEOSGeom_createCollection
    88 # Used specifically by the GEOSGeom_createPolygon and GEOSGeom_createCollection
    93 #  GEOS routines
    89 #  GEOS routines
    94 def get_pointer_arr(n):
    90 def get_pointer_arr(n):
    95     "Gets a ctypes pointer array (of length `n`) for GEOSGeom_t opaque pointer."
    91     "Gets a ctypes pointer array (of length `n`) for GEOSGeom_t opaque pointer."
   102 geos_version.argtypes = None
    98 geos_version.argtypes = None
   103 geos_version.restype = c_char_p
    99 geos_version.restype = c_char_p
   104 
   100 
   105 # Regular expression should be able to parse version strings such as
   101 # Regular expression should be able to parse version strings such as
   106 # '3.0.0rc4-CAPI-1.3.3', or '3.0.0-CAPI-1.4.1'
   102 # '3.0.0rc4-CAPI-1.3.3', or '3.0.0-CAPI-1.4.1'
   107 version_regex = re.compile(r'^(?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.\d+)(rc(?P<release_candidate>\d+))?-CAPI-(?P<capi_version>\d+\.\d+\.\d+)$')
   103 version_regex = re.compile(r'^(?P<version>(?P<major>\d+)\.(?P<minor>\d+)\.(?P<subminor>\d+))(rc(?P<release_candidate>\d+))?-CAPI-(?P<capi_version>\d+\.\d+\.\d+)$')
   108 def geos_version_info():
   104 def geos_version_info():
   109     """
   105     """
   110     Returns a dictionary containing the various version metadata parsed from
   106     Returns a dictionary containing the various version metadata parsed from
   111     the GEOS version string, including the version number, whether the version
   107     the GEOS version string, including the version number, whether the version
   112     is a release candidate (and what number release candidate), and the C API
   108     is a release candidate (and what number release candidate), and the C API
   113     version.
   109     version.
   114     """
   110     """
   115     ver = geos_version()
   111     ver = geos_version()
   116     m = version_regex.match(ver)
   112     m = version_regex.match(ver)
   117     if not m: raise GEOSException('Could not parse version info string "%s"' % ver)
   113     if not m: raise GEOSException('Could not parse version info string "%s"' % ver)
   118     return dict((key, m.group(key)) for key in ('version', 'release_candidate', 'capi_version', 'major', 'minor'))
   114     return dict((key, m.group(key)) for key in ('version', 'release_candidate', 'capi_version', 'major', 'minor', 'subminor'))
   119 
   115 
   120 # Version numbers and whether or not prepared geometry support is available.
   116 # Version numbers and whether or not prepared geometry support is available.
   121 _verinfo = geos_version_info()
   117 _verinfo = geos_version_info()
   122 GEOS_MAJOR_VERSION = int(_verinfo['major'])
   118 GEOS_MAJOR_VERSION = int(_verinfo['major'])
   123 GEOS_MINOR_VERSION = int(_verinfo['minor'])
   119 GEOS_MINOR_VERSION = int(_verinfo['minor'])
       
   120 GEOS_SUBMINOR_VERSION = int(_verinfo['subminor'])
   124 del _verinfo
   121 del _verinfo
   125 GEOS_PREPARE = GEOS_MAJOR_VERSION > 3 or GEOS_MAJOR_VERSION == 3 and GEOS_MINOR_VERSION >= 1
   122 GEOS_VERSION = (GEOS_MAJOR_VERSION, GEOS_MINOR_VERSION, GEOS_SUBMINOR_VERSION)
       
   123 GEOS_PREPARE = GEOS_VERSION >= (3, 1, 0)
   126 
   124 
   127 # Calling the finishGEOS() upon exit of the interpreter.
   125 if GEOS_PREPARE:
   128 atexit.register(lgeos.finishGEOS)
   126     # Here we set up the prototypes for the initGEOS_r and finishGEOS_r
       
   127     # routines.  These functions aren't actually called until they are
       
   128     # attached to a GEOS context handle -- this actually occurs in
       
   129     # geos/prototypes/threadsafe.py.
       
   130     lgeos.initGEOS_r.restype = CONTEXT_PTR
       
   131     lgeos.finishGEOS_r.argtypes = [CONTEXT_PTR]
       
   132 else:
       
   133     # When thread-safety isn't available, the initGEOS routine must be called
       
   134     # first.  This function takes the notice and error functions, defined
       
   135     # as Python callbacks above, as parameters. Here is the C code that is
       
   136     # wrapped:
       
   137     #  extern void GEOS_DLL initGEOS(GEOSMessageHandler notice_function, GEOSMessageHandler error_function);
       
   138     lgeos.initGEOS(notice_h, error_h)
       
   139     # Calling finishGEOS() upon exit of the interpreter.
       
   140     import atexit
       
   141     atexit.register(lgeos.finishGEOS)