summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Bronn <jbronn@gmail.com>2008-02-13 00:38:36 +0000
committerJustin Bronn <jbronn@gmail.com>2008-02-13 00:38:36 +0000
commitd88c9ac6449c272d8df0023fc0736b9794c43fed (patch)
treee03fc58fb987f33c68955b74327bfc36cda75698
parent21a019681c4ef2cfe486beb5d43ba068b3247d24 (diff)
gis: gdal: Added support for GeoJSON input/output in `OGRGeometry`.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@7107 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/contrib/gis/gdal/geometries.py52
-rw-r--r--django/contrib/gis/gdal/libgdal.py15
-rw-r--r--django/contrib/gis/gdal/prototypes/geom.py18
-rw-r--r--django/contrib/gis/tests/geometries.py3
-rw-r--r--django/contrib/gis/tests/test_gdal_geom.py10
5 files changed, 73 insertions, 25 deletions
diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py
index 37bb65d3fa..7c01ce10e9 100644
--- a/django/contrib/gis/gdal/geometries.py
+++ b/django/contrib/gis/gdal/geometries.py
@@ -42,7 +42,7 @@
import re, sys
from binascii import a2b_hex
from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p
-from types import BufferType, IntType, StringType, UnicodeType
+from types import UnicodeType
# Getting GDAL prerequisites
from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
@@ -62,6 +62,7 @@ from django.contrib.gis.gdal.prototypes.srs import clone_srs
# Regular expressions for recognizing HEXEWKB and WKT.
hex_regex = re.compile(r'^[0-9A-F]+$', re.I)
wkt_regex = re.compile(r'^(?P<type>POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+$', re.I)
+json_regex = re.compile(r'^\{.+\}$')
#### OGRGeometry Class ####
class OGRGeometry(object):
@@ -71,32 +72,41 @@ class OGRGeometry(object):
"Initializes Geometry on either WKT or an OGR pointer as input."
self._ptr = c_void_p(None) # Initially NULL
-
- # Checking if unicode
- if isinstance(geom_input, UnicodeType):
- # Encoding to ASCII, WKT or HEX doesn't need any more.
- geo_input = geo_input.encode('ascii')
+ str_instance = isinstance(geom_input, basestring)
# If HEX, unpack input to to a binary buffer.
- if isinstance(geom_input, StringType) and hex_regex.match(geom_input):
+ if str_instance and hex_regex.match(geom_input):
geom_input = buffer(a2b_hex(geom_input.upper()))
+ str_instance = False
+
+ # Constructing the geometry,
+ if str_instance:
+ # Checking if unicode
+ if isinstance(geom_input, UnicodeType):
+ # Encoding to ASCII, WKT or HEX doesn't need any more.
+ geo_input = geo_input.encode('ascii')
- if isinstance(geom_input, StringType):
- m = wkt_regex.match(geom_input)
- if m:
- if m.group('type').upper() == 'LINEARRING':
+ wkt_m = wkt_regex.match(geom_input)
+ json_m = json_regex.match(geom_input)
+ if wkt_m:
+ if wkt_m.group('type').upper() == 'LINEARRING':
# OGR_G_CreateFromWkt doesn't work with LINEARRING WKT.
# See http://trac.osgeo.org/gdal/ticket/1992.
- g = create_geom(OGRGeomType(m.group('type')).num)
+ g = create_geom(OGRGeomType(wkt_m.group('type')).num)
import_wkt(g, byref(c_char_p(geom_input)))
else:
g = from_wkt(byref(c_char_p(geom_input)), None, byref(c_void_p()))
+ elif json_m:
+ if GEOJSON:
+ g = from_json(geom_input)
+ else:
+ raise NotImplementedError('GeoJSON input only supported on GDAL 1.5+.')
else:
# Seeing if the input is a valid short-hand string
# (e.g., 'Point', 'POLYGON').
ogr_t = OGRGeomType(geom_input)
g = create_geom(OGRGeomType(geom_input).num)
- elif isinstance(geom_input, BufferType):
+ elif isinstance(geom_input, buffer):
# WKB was passed in
g = from_wkb(str(geom_input), None, byref(c_void_p()), len(geom_input))
elif isinstance(geom_input, OGRGeomType):
@@ -223,7 +233,7 @@ class OGRGeometry(object):
"Sets the SpatialReference for this geometry."
if isinstance(srs, SpatialReference):
srs_ptr = clone_srs(srs._ptr)
- elif isinstance(srs, (StringType, UnicodeType, IntType)):
+ elif isinstance(srs, (int, long, basestring)):
sr = SpatialReference(srs)
srs_ptr = clone_srs(sr._ptr)
else:
@@ -238,7 +248,7 @@ class OGRGeometry(object):
else: return None
def set_srid(self, srid):
- if isinstance(srid, IntType):
+ if isinstance(srid, (int, long)):
self.srs = srid
else:
raise TypeError('SRID must be set with an integer.')
@@ -264,6 +274,14 @@ class OGRGeometry(object):
#return b2a_hex(self.wkb).upper()
@property
+ def json(self):
+ if GEOJSON:
+ return to_json(self._ptr)
+ else:
+ raise NotImplementedError('GeoJSON output only supported on GDAL 1.5+.')
+ geojson = json
+
+ @property
def wkb_size(self):
"Returns the size of the WKB buffer."
return get_wkbsize(self._ptr)
@@ -310,7 +328,7 @@ class OGRGeometry(object):
geom_transform(self._ptr, coord_trans._ptr)
elif isinstance(coord_trans, SpatialReference):
geom_transform_to(self._ptr, coord_trans._ptr)
- elif isinstance(coord_trans, (int, basestring)):
+ elif isinstance(coord_trans, (int, long, basestring)):
sr = SpatialReference(coord_trans)
geom_transform_to(self._ptr, sr._ptr)
else:
@@ -542,7 +560,7 @@ class GeometryCollection(OGRGeometry):
for g in geom: add_geom(self._ptr, g._ptr)
else:
add_geom(self._ptr, geom._ptr)
- elif isinstance(geom, (StringType, UnicodeType)):
+ elif isinstance(geom, basestring):
tmp = OGRGeometry(geom)
add_geom(self._ptr, tmp._ptr)
else:
diff --git a/django/contrib/gis/gdal/libgdal.py b/django/contrib/gis/gdal/libgdal.py
index 4330209f52..28d2d49907 100644
--- a/django/contrib/gis/gdal/libgdal.py
+++ b/django/contrib/gis/gdal/libgdal.py
@@ -1,5 +1,5 @@
import os, sys
-from ctypes import CDLL, string_at
+from ctypes import c_char_p, CDLL
from ctypes.util import find_library
from django.contrib.gis.gdal.error import OGRException
@@ -48,10 +48,11 @@ def std_call(func):
return lgdal[func]
#### Version-information functions. ####
-def _version_info(key):
- "Returns GDAL library version information with the given key."
- buf = lgdal.GDALVersionInfo(key)
- if buf: return string_at(buf)
+
+# Returns GDAL library version information with the given key.
+_version_info = lgdal.GDALVersionInfo
+_version_info.argtypes = [c_char_p]
+_version_info.restype = c_char_p
def gdal_version():
"Returns only the GDAL version number information."
@@ -67,9 +68,9 @@ def gdal_release_date(date=False):
If the date keyword argument is set to True, a Python datetime object
will be returned instead.
"""
- from datetime import datetime
+ from datetime import date as date_type
rel = _version_info('RELEASE_DATE')
yy, mm, dd = map(int, (rel[0:4], rel[4:6], rel[6:8]))
- d = datetime(yy, mm, dd)
+ d = date_type(yy, mm, dd)
if date: return d
else: return d.strftime('%Y/%m/%d')
diff --git a/django/contrib/gis/gdal/prototypes/geom.py b/django/contrib/gis/gdal/prototypes/geom.py
index dd449ae024..6ec55ec938 100644
--- a/django/contrib/gis/gdal/prototypes/geom.py
+++ b/django/contrib/gis/gdal/prototypes/geom.py
@@ -1,11 +1,19 @@
+from datetime import date
from ctypes import c_char, c_char_p, c_double, c_int, c_ubyte, c_void_p, POINTER
from django.contrib.gis.gdal.envelope import OGREnvelope
-from django.contrib.gis.gdal.libgdal import lgdal
+from django.contrib.gis.gdal.libgdal import lgdal, gdal_version
from django.contrib.gis.gdal.prototypes.errcheck import check_bool, check_envelope
from django.contrib.gis.gdal.prototypes.generation import \
const_string_output, double_output, geom_output, int_output, \
srs_output, string_output, void_output
+# Some prototypes need to be aware of what version GDAL we have.
+major, minor1, minor2 = map(int, gdal_version().split('.'))
+if major <= 1 and minor1 <= 4:
+ GEOJSON = False
+else:
+ GEOJSON = True
+
### Generation routines specific to this module ###
def env_func(f, argtypes):
"For getting OGREnvelopes."
@@ -26,6 +34,14 @@ def topology_func(f):
### OGR_G ctypes function prototypes ###
+# GeoJSON routines, if supported.
+if GEOJSON:
+ from_json = geom_output(lgdal.OGR_G_CreateGeometryFromJson, [c_char_p])
+ to_json = string_output(lgdal.OGR_G_ExportToJson, [c_void_p], str_result=True)
+else:
+ from_json = False
+ to_json = False
+
# GetX, GetY, GetZ all return doubles.
getx = pnt_func(lgdal.OGR_G_GetX)
gety = pnt_func(lgdal.OGR_G_GetY)
diff --git a/django/contrib/gis/tests/geometries.py b/django/contrib/gis/tests/geometries.py
index ab2ecea3bf..0001a765a1 100644
--- a/django/contrib/gis/tests/geometries.py
+++ b/django/contrib/gis/tests/geometries.py
@@ -151,3 +151,6 @@ buffer_geoms = ( (TestGeom('POINT(0 0)'),
2.0, 8),
)
+json_geoms = (TestGeom('POINT(100 0)', json='{ "type": "Point", "coordinates": [ 100.000000, 0.000000 ] }'),
+ TestGeom('MULTIPOLYGON(((102 2, 103 2, 103 3, 102 3, 102 2)), ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8, 100.2 0.2)))', json='{ "type": "MultiPolygon", "coordinates": [ [ [ [ 102.000000, 2.000000 ], [ 103.000000, 2.000000 ], [ 103.000000, 3.000000 ], [ 102.000000, 3.000000 ], [ 102.000000, 2.000000 ] ] ], [ [ [ 100.000000, 0.000000 ], [ 101.000000, 0.000000 ], [ 101.000000, 1.000000 ], [ 100.000000, 1.000000 ], [ 100.000000, 0.000000 ] ], [ [ 100.200000, 0.200000 ], [ 100.800000, 0.200000 ], [ 100.800000, 0.800000 ], [ 100.200000, 0.800000 ], [ 100.200000, 0.200000 ] ] ] ] }'),
+ )
diff --git a/django/contrib/gis/tests/test_gdal_geom.py b/django/contrib/gis/tests/test_gdal_geom.py
index 06c2eb769e..9e52a7ce57 100644
--- a/django/contrib/gis/tests/test_gdal_geom.py
+++ b/django/contrib/gis/tests/test_gdal_geom.py
@@ -63,6 +63,16 @@ class OGRGeomTest(unittest.TestCase):
geom2 = OGRGeometry(wkb)
self.assertEqual(geom1, geom2)
+ def test01e_json(self):
+ "Testing GeoJSON input/output."
+ from django.contrib.gis.gdal.prototypes.geom import GEOJSON
+ if not GEOJSON: return
+ for g in json_geoms:
+ geom = OGRGeometry(g.wkt)
+ self.assertEqual(g.json, geom.json)
+ self.assertEqual(g.json, geom.geojson)
+ self.assertEqual(OGRGeometry(g.wkt), OGRGeometry(geom.json))
+
def test02_points(self):
"Testing Point objects."