diff --git a/django/contrib/gis/utils/__init__.py b/django/contrib/gis/utils/__init__.py index 1dca849718..234c6e998e 100644 --- a/django/contrib/gis/utils/__init__.py +++ b/django/contrib/gis/utils/__init__.py @@ -21,3 +21,5 @@ except: HAS_GEOIP = False from django.contrib.gis.utils.srs import add_postgis_srs +from django.contrib.gis.utils.wkt import precision_wkt + diff --git a/django/contrib/gis/utils/srs.py b/django/contrib/gis/utils/srs.py index f9783b94ac..0b17e42f8b 100644 --- a/django/contrib/gis/utils/srs.py +++ b/django/contrib/gis/utils/srs.py @@ -1,3 +1,5 @@ +from django.contrib.gis.gdal import SpatialReference + def add_postgis_srs(srs): """ This function takes a GDAL SpatialReference system and adds its @@ -14,6 +16,9 @@ def add_postgis_srs(srs): """ from django.contrib.gis.models import SpatialRefSys + if not isinstance(srs, SpatialReference): + srs = SpatialReference(srs) + if srs.srid is None: raise Exception('Spatial reference requires an SRID to be compatible with PostGIS.') diff --git a/django/contrib/gis/utils/wkt.py b/django/contrib/gis/utils/wkt.py new file mode 100644 index 0000000000..4aecc6247d --- /dev/null +++ b/django/contrib/gis/utils/wkt.py @@ -0,0 +1,55 @@ +""" + Utilities for manipulating Geometry WKT. +""" + +def precision_wkt(geom, prec): + """ + Returns WKT text of the geometry according to the given precision (an + integer or a string). If the precision is an integer, then the decimal + places of coordinates WKT will be truncated to that number: + + >>> pnt = Point(5, 23) + >>> pnt.wkt + 'POINT (5.0000000000000000 23.0000000000000000)' + >>> precision(geom, 1) + 'POINT (5.0 23.0)' + + If the precision is a string, it must be valid Python format string + (e.g., '%20.7f') -- thus, you should know what you're doing. + """ + if isinstance(prec, int): + num_fmt = '%%.%df' % prec + elif isinstance(prec, basestring): + num_fmt = prec + else: + raise TypeError + + # TODO: Support 3D geometries. + coord_fmt = ' '.join([num_fmt, num_fmt]) + + def formatted_coords(coords): + return ','.join([coord_fmt % c[:2] for c in coords]) + + def formatted_poly(poly): + return ','.join(['(%s)' % formatted_coords(r) for r in poly]) + + def formatted_geom(g): + gtype = str(g.geom_type).upper() + yield '%s(' % gtype + if gtype == 'POINT': + yield formatted_coords((g.coords,)) + elif gtype in ('LINESTRING', 'LINEARRING'): + yield formatted_coords(g.coords) + elif gtype in ('POLYGON', 'MULTILINESTRING'): + yield formatted_poly(g) + elif gtype == 'MULTIPOINT': + yield formatted_coords(g.coords) + elif gtype == 'MULTIPOLYGON': + yield ','.join(['(%s)' % formatted_poly(p) for p in g]) + elif gtype == 'GEOMETRYCOLLECTION': + yield ','.join([''.join([wkt for wkt in formatted_geom(child)]) for child in g]) + else: + raise TypeError + yield ')' + + return ''.join([wkt for wkt in formatted_geom(geom)])