From 2d5cd5a15aae5b8e41d0fd4cde257fc5aaa3302c Mon Sep 17 00:00:00 2001 From: Michal Migurski Date: Sat, 2 Apr 2011 16:44:49 +0000 Subject: [PATCH] Moved Vector provider into a new submodule to better isolate Arc-specific parts --- Makefile | 1 + TileStache/Vector/Arc.py | 68 ++++++++++++++++++ TileStache/{Vector.py => Vector/__init__.py} | 72 ++------------------ 3 files changed, 73 insertions(+), 68 deletions(-) create mode 100644 TileStache/Vector/Arc.py rename TileStache/{Vector.py => Vector/__init__.py} (87%) diff --git a/Makefile b/Makefile index b2e908a5..5a80a4ba 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,7 @@ doc: pydoc -w TileStache.Caches pydoc -w TileStache.Config pydoc -w TileStache.Vector + pydoc -w TileStache.Vector.Arc pydoc -w TileStache.Geography pydoc -w TileStache.Providers pydoc -w TileStache.Goodies diff --git a/TileStache/Vector/Arc.py b/TileStache/Vector/Arc.py new file mode 100644 index 00000000..373e5938 --- /dev/null +++ b/TileStache/Vector/Arc.py @@ -0,0 +1,68 @@ +""" Arc-specific Vector provider helpers. +""" +from TileStache.Core import KnownUnknown + +geometry_types = { + 'Point': 'esriGeometryPoint', + 'LineString': 'esriGeometryPolyline', + 'Polygon': 'esriGeometryPolygon', + 'MultiPoint': 'esriGeometryMultipoint', + 'MultiLineString': 'esriGeometryPolyline', + 'MultiPolygon': 'esriGeometryPolygon' + } + +def reserialize_to_arc(content): + """ Convert from "geo" (GeoJSON) to ESRI's GeoServices REST serialization. + + Much of this cribbed from sample server queries and page 191+ of: + http://www.esri.com/library/whitepapers/pdfs/geoservices-rest-spec.pdf + """ + found_geometry_types = set([feat['geometry']['type'] for feat in content['features']]) + found_geometry_types = set([geometry_types.get(type) for type in found_geometry_types]) + + if len(found_geometry_types) > 1: + raise KnownUnknown('Arc serialization needs a single geometry type, not ' + ', '.join(found_geometry_types)) + + response = {'spatialReference': {'wkid': 4326}, 'features': []} + + if 'wkid' in content['crs']: + response['spatialReference'] = {'wkid': content['crs']['wkid']} + + elif 'wkt' in content['crs']: + response['spatialReference'] = {'wkt': content['crs']['wkt']} + + for feature in content['features']: + geometry = feature['geometry'] + + if geometry['type'] == 'Point': + x, y = geometry['coordinates'] + arc_geometry = {'x': x, 'y': y} + + elif geometry['type'] == 'LineString': + path = geometry['coordinates'] + arc_geometry = {'paths': [path]} + + elif geometry['type'] == 'Polygon': + rings = geometry['coordinates'] + arc_geometry = {'rings': rings} + + elif geometry['type'] == 'MultiPoint': + points = geometry['coordinates'] + arc_geometry = {'points': points} + + elif geometry['type'] == 'MultiLineString': + paths = geometry['coordinates'] + arc_geometry = {'paths': paths} + + elif geometry['type'] == 'MultiPolygon': + rings = reduce(add, geometry['coordinates']) + arc_geometry = {'rings': rings} + + else: + raise Exception(geometry['type']) + + arc_feature = {'attributes': feature['properties'], 'geometry': arc_geometry} + response['geometryType'] = geometry_types[geometry['type']] + response['features'].append(arc_feature) + + return response diff --git a/TileStache/Vector.py b/TileStache/Vector/__init__.py similarity index 87% rename from TileStache/Vector.py rename to TileStache/Vector/__init__.py index 264bc8c3..1dc96cc2 100644 --- a/TileStache/Vector.py +++ b/TileStache/Vector/__init__.py @@ -151,8 +151,9 @@ # At least we'll be able to build the documentation. pass -from Core import KnownUnknown -from Geography import getProjectionByName +from TileStache.Core import KnownUnknown +from TileStache.Geography import getProjectionByName +from Arc import reserialize_to_arc class VectorResponse: """ Wrapper class for Vector response that makes it behave like a PIL.Image object. @@ -190,7 +191,7 @@ def save(self, out, format): del content['crs'] elif format in ('ArcJSON', 'ArcBSON', 'ArcAMF'): - content = _reserialize_to_arc(self.content) + content = reserialize_to_arc(self.content) else: raise KnownUnknown('Vector response only saves .geojson, .arcjson, .geobson, .arcbson, .geoamf, .arcamf and .wkt tiles, not "%s"' % format) @@ -231,71 +232,6 @@ def _sref_4326(): return sref -def _reserialize_to_arc(content): - """ Convert from "geo" (GeoJSON) to ESRI's GeoServices REST serialization. - - Much of this cribbed from sample server queries and page 191+ of: - http://www.esri.com/library/whitepapers/pdfs/geoservices-rest-spec.pdf - """ - arc_geometry_types = { - 'Point': 'esriGeometryPoint', - 'LineString': 'esriGeometryPolyline', - 'Polygon': 'esriGeometryPolygon', - 'MultiPoint': 'esriGeometryMultipoint', - 'MultiLineString': 'esriGeometryPolyline', - 'MultiPolygon': 'esriGeometryPolygon' - } - - found_geometry_types = set([feat['geometry']['type'] for feat in content['features']]) - found_geometry_types = set([arc_geometry_types.get(type) for type in found_geometry_types]) - - if len(found_geometry_types) > 1: - raise KnownUnknown('Arc serialization needs a single geometry type, not ' + ', '.join(found_geometry_types)) - - response = {'spatialReference': {'wkid': 4326}, 'features': []} - - if 'wkid' in content['crs']: - response['spatialReference'] = {'wkid': content['crs']['wkid']} - - elif 'wkt' in content['crs']: - response['spatialReference'] = {'wkt': content['crs']['wkt']} - - for feature in content['features']: - geometry = feature['geometry'] - - if geometry['type'] == 'Point': - x, y = geometry['coordinates'] - arc_geometry = {'x': x, 'y': y} - - elif geometry['type'] == 'LineString': - path = geometry['coordinates'] - arc_geometry = {'paths': [path]} - - elif geometry['type'] == 'Polygon': - rings = geometry['coordinates'] - arc_geometry = {'rings': rings} - - elif geometry['type'] == 'MultiPoint': - points = geometry['coordinates'] - arc_geometry = {'points': points} - - elif geometry['type'] == 'MultiLineString': - paths = geometry['coordinates'] - arc_geometry = {'paths': paths} - - elif geometry['type'] == 'MultiPolygon': - rings = reduce(add, geometry['coordinates']) - arc_geometry = {'rings': rings} - - else: - raise Exception(geometry['type']) - - arc_feature = {'attributes': feature['properties'], 'geometry': arc_geometry} - response['geometryType'] = arc_geometry_types[geometry['type']] - response['features'].append(arc_feature) - - return response - def _tile_perimeter(coord, projection): """ Get a tile's outer edge for a coordinate and a projection.