| from ctypes import c_char_p, c_int, c_size_t, c_ubyte, c_uint, POINTER |
| from django.contrib.gis.geos.libgeos import CS_PTR, GEOM_PTR, PREPGEOM_PTR, GEOS_PREPARE |
| from django.contrib.gis.geos.prototypes.errcheck import \ |
| 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. |
| c_uchar_p = POINTER(c_ubyte) |
| |
| # We create a simple subclass of c_char_p here because when the response |
| # type is set to c_char_p, you get a _Python_ string and there's no way |
| # to access the string's address inside the error checking function. |
| # In other words, you can't free the memory allocated inside GEOS. Previously, |
| # the return type would just be omitted and the integer address would be |
| # used -- but this allows us to be specific in the function definition and |
| # keeps the reference so it may be free'd. |
| class geos_char_p(c_char_p): |
| pass |
| |
| ### ctypes generation functions ### |
| def bin_constructor(func): |
| "Generates a prototype for binary construction (HEX, WKB) GEOS routines." |
| func.argtypes = [c_char_p, c_size_t] |
| func.restype = GEOM_PTR |
| func.errcheck = check_geom |
| return func |
| |
| # HEX & WKB output |
| def bin_output(func): |
| "Generates a prototype for the routines that return a a sized string." |
| func.argtypes = [GEOM_PTR, POINTER(c_size_t)] |
| func.errcheck = check_sized_string |
| func.restype = c_uchar_p |
| return func |
| |
| def geom_output(func, argtypes): |
| "For GEOS routines that return a geometry." |
| if argtypes: func.argtypes = argtypes |
| func.restype = GEOM_PTR |
| func.errcheck = check_geom |
| return func |
| |
| def geom_index(func): |
| "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." |
| func.argtypes = [GEOM_PTR] |
| func.restype = c_int |
| if zero: |
| func.errcheck = check_zero |
| else: |
| func.errcheck = check_minus_one |
| return func |
| |
| def string_from_geom(func): |
| "Argument is a Geometry, return type is a string." |
| func.argtypes = [GEOM_PTR] |
| func.restype = geos_char_p |
| func.errcheck = check_string |
| return func |
| |
| ### ctypes prototypes ### |
| |
| # Deprecated creation routines from WKB, HEX, WKT |
| from_hex = bin_constructor(GEOSFunc('GEOSGeomFromHEX_buf')) |
| from_wkb = bin_constructor(GEOSFunc('GEOSGeomFromWKB_buf')) |
| from_wkt = geom_output(GEOSFunc('GEOSGeomFromWKT'), [c_char_p]) |
| |
| # Deprecated output routines |
| to_hex = bin_output(GEOSFunc('GEOSGeomToHEX_buf')) |
| to_wkb = bin_output(GEOSFunc('GEOSGeomToWKB_buf')) |
| to_wkt = string_from_geom(GEOSFunc('GEOSGeomToWKT')) |
| |
| # The GEOS geometry type, typeid, num_coordites and number of geometries |
| geos_normalize = int_from_geom(GEOSFunc('GEOSNormalize')) |
| geos_type = string_from_geom(GEOSFunc('GEOSGeomType')) |
| geos_typeid = int_from_geom(GEOSFunc('GEOSGeomTypeId')) |
| get_dims = int_from_geom(GEOSFunc('GEOSGeom_getDimensions'), zero=True) |
| get_num_coords = int_from_geom(GEOSFunc('GEOSGetNumCoordinates')) |
| get_num_geoms = int_from_geom(GEOSFunc('GEOSGetNumGeometries')) |
| |
| # Geometry creation factories |
| create_point = geom_output(GEOSFunc('GEOSGeom_createPoint'), [CS_PTR]) |
| create_linestring = geom_output(GEOSFunc('GEOSGeom_createLineString'), [CS_PTR]) |
| create_linearring = geom_output(GEOSFunc('GEOSGeom_createLinearRing'), [CS_PTR]) |
| |
| # Polygon and collection creation routines are special and will not |
| # have their argument types defined. |
| create_polygon = geom_output(GEOSFunc('GEOSGeom_createPolygon'), None) |
| create_collection = geom_output(GEOSFunc('GEOSGeom_createCollection'), None) |
| |
| # Ring routines |
| get_extring = geom_output(GEOSFunc('GEOSGetExteriorRing'), [GEOM_PTR]) |
| get_intring = geom_index(GEOSFunc('GEOSGetInteriorRingN')) |
| get_nrings = int_from_geom(GEOSFunc('GEOSGetNumInteriorRings')) |
| |
| # Collection Routines |
| get_geomn = geom_index(GEOSFunc('GEOSGetGeometryN')) |
| |
| # Cloning |
| geom_clone = GEOSFunc('GEOSGeom_clone') |
| geom_clone.argtypes = [GEOM_PTR] |
| geom_clone.restype = GEOM_PTR |
| |
| # Destruction routine. |
| destroy_geom = GEOSFunc('GEOSGeom_destroy') |
| destroy_geom.argtypes = [GEOM_PTR] |
| destroy_geom.restype = None |
| |
| # SRID routines |
| geos_get_srid = GEOSFunc('GEOSGetSRID') |
| geos_get_srid.argtypes = [GEOM_PTR] |
| geos_get_srid.restype = c_int |
| |
| geos_set_srid = GEOSFunc('GEOSSetSRID') |
| geos_set_srid.argtypes = [GEOM_PTR, c_int] |
| geos_set_srid.restype = None |