Changeset 1221
- Timestamp:
- 11/05/07 15:06:43 (1 year ago)
- Files:
-
- PleiadesGeocoder/trunk/CHANGES.txt (modified) (1 diff)
- PleiadesGeocoder/trunk/HISTORY.txt (modified) (1 diff)
- PleiadesGeocoder/trunk/browser/info.py (modified) (5 diffs)
- PleiadesGeocoder/trunk/geo.py (modified) (6 diffs)
- PleiadesGeocoder/trunk/makerelease (deleted)
- PleiadesGeocoder/trunk/skins/PleiadesGeocoder/georss.pt (modified) (2 diffs)
- PleiadesGeocoder/trunk/tests/FolderGeoViews.txt (modified) (2 diffs)
- PleiadesGeocoder/trunk/tests/test_simple.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
PleiadesGeocoder/trunk/CHANGES.txt
r1218 r1221 4 4 All ticket numbers are relative to http://icon.stoa.org/trac/pleiades/tickets. 5 5 6 1.0b1 7 ----- 6 1.0b1: 5 November 2007 7 ---------------------- 8 8 9 - IGeoserializeable and IGeoreferenceable are now markers for viewables only. 9 10 - Interfaces consolidated in interfaces.py. 11 - Removed hasPoint/Line/Polygon from IGeoItemSimple. 12 - Removed spatial reference system from IGeoItemSimple. 13 - Removed older pre-GeoJSON geometry type and coordinate accessors from 14 IGeoItemSimple. 10 15 11 1.0a112 -----13 - Added a content georeferencing event.14 - New content georeferencing form, with event notification.15 - GML geometry serialization used in GeoRSS view.16 - Added support for LineString and Polygon geometry types.17 18 0.6.2 - 20 February, 200719 -------------------------20 - Update to KML 2.1.21 - Add name and description to network link and folders.22 PleiadesGeocoder/trunk/HISTORY.txt
r630 r1221 3 3 4 4 All ticket numbers are relative to http://icon.stoa.org/trac/pleiades/tickets. 5 6 1.0a1 7 ----- 8 - Added a content georeferencing event. 9 - New content georeferencing form, with event notification. 10 - GML geometry serialization used in GeoRSS view. 11 - Added support for LineString and Polygon geometry types. 12 13 0.6.2 - 20 February, 2007 14 ------------------------- 15 - Update to KML 2.1. 16 - Add name and description to network link and folders. 5 17 6 18 0.6.1 - 9 Ocober 2006 PleiadesGeocoder/trunk/browser/info.py
r1185 r1221 36 36 class IGeoInfosetView(Interface): 37 37 38 def forRSS(): 39 """Process into an infoset for export to GeoRSS.""" 38 def forRSS(maxitems): 39 """Returns an iterator over GeoRSS compatible data. 40 41 Arguments 42 --------- 43 maxitems : int (optional) 44 Iteration will be truncated at specified number. 45 """ 40 46 41 47 def forKML(): 42 """Process into an infoset for export to KML.""" 48 """Returns an iterator over KML compatible data.""" 49 50 51 def coords_to_kml(geom): 52 gtype = geom['type'] 53 if gtype == 'Point': 54 coords = (geom['coordinates'],) 55 elif gtype == 'Polygon': 56 coords = geom['coordinates'][0] 57 else: 58 coords = geom['coordinates'] 59 if len(coords[0]) == 2: 60 tuples = ('%f,%f,0.0' % c for c in coords) 61 elif len(coords[0]) == 3: 62 tuples = ('%f,%f,%f' % c for c in coords) 63 else: 64 raise ValueError, "Invalid dimensions" 65 return ' '.join(tuples) 66 67 def coords_to_georss(geom): 68 gtype = geom['type'] 69 if gtype == 'Point': 70 coords = (geom['coordinates'],) 71 elif gtype == 'Polygon': 72 coords = geom['coordinates'][0] 73 else: 74 coords = geom['coordinates'] 75 tuples = ('%f %f' % (c[1], c[0]) for c in coords) 76 return ' '.join(tuples) 77 78 79 class GeoInfosetView(BrowserView): 80 81 """View of content that supports GeoRSS and KML output. 82 """ 83 implements(IGeoInfosetView) 84 85 def __init__(self, context, request): 86 self.context = context 87 self.request = request 88 self.collection = IGeoCollectionSimple(self.context) 89 90 def forRSS(self, maxitems=-1): 91 """Get a sequence of informative dicts""" 92 collection = self.collection 93 if maxitems < 0: 94 for item in collection.geoItems(): 95 info = item.__geo_interface__ 96 info.update({ 97 'hasPoint': int(item.geom_type == 'Point') , 98 'hasLineString': int(item.geom_type == 'LineString'), 99 'hasPolygon': int(item.geom_type == 'Polygon'), 100 'coords_georss': coords_to_georss(info['geometry']), 101 }) 102 yield info 103 else: 104 i = 0 105 for item in collection.geoItems(): 106 if i >= maxitems: 107 raise StopIteration 108 info = item.__geo_interface__ 109 info.update({ 110 'hasPoint': int(item.geom_type == 'Point') , 111 'hasLineString': int(item.geom_type == 'LineString'), 112 'hasPolygon': int(item.geom_type == 'Polygon'), 113 'coords_georss': coords_to_georss(info['geometry']), 114 }) 115 yield info 116 i += 1 117 118 def forKML(self): 119 """Get a sequence of informative dicts""" 120 collection = self.collection 121 for item in collection.geoItems(): 122 info = item.__geo_interface__ 123 info.update({ 124 'hasPoint': int(item.geom_type == 'Point') , 125 'hasLineString': int(item.geom_type == 'LineString'), 126 'hasPolygon': int(item.geom_type == 'Polygon'), 127 'coords_kml': coords_to_kml(info['geometry']) 128 }) 129 yield info 130 43 131 44 132 def get_coords(coord_string, geomtype='point'): … … 56 144 return (tuple(coords),) 57 145 58 def coords_to_kml(geom): 59 gtype = geom['type'] 60 if gtype == 'Point': 61 coords = (geom['coordinates'],) 62 elif gtype == 'Polygon': 63 coords = geom['coordinates'][0] 64 else: 65 coords = geom['coordinates'] 66 tuples = ('%f,%f,%f' % c for c in coords) 67 return ' '.join(tuples) 68 69 70 class GeoInfosetView(BrowserView): 146 147 class GeoMembersInfosetView(BrowserView): 71 148 72 149 """View of content that supports GeoRSS and KML output. … … 74 151 implements(IGeoInfosetView) 75 152 76 def __init__(self, context, request): 77 self.context = context 78 self.request = request 79 self.collection = IGeoCollectionSimple(self.context) 80 81 def forRSS(self): 82 """Get a sequence of informative dicts""" 83 collection = self.collection 84 infos = [] 85 for item in collection.geoItems(): 86 info = item.__geo_interface__ 87 info.update({ 88 'hasPoint': item.hasPoint(), 89 'hasLineString': item.hasLineString(), 90 'hasPolygon': item.hasPolygon(), 91 'coords_georss': item.spatialCoordinates, 92 }) 93 infos.append(info) 94 return infos 95 96 def forKML(self): 97 """Get a sequence of informative dicts""" 98 collection = self.collection 99 infos = [] 100 for item in collection.geoItems(): 101 info = item.__geo_interface__ 102 info.update({ 103 'hasPoint': item.hasPoint(), 104 'hasLineString': item.hasLineString(), 105 'hasPolygon': item.hasPolygon(), 106 'coords_kml': coords_to_kml(info['geometry']) 107 }) 108 infos.append(info) 109 return infos 110 111 112 class GeoMembersInfosetView(BrowserView): 113 114 """View of content that supports GeoRSS and KML output. 115 """ 116 implements(IGeoInfosetView) 117 118 def forRSS(self): 153 def forRSS(self, maxitems=-1): 119 154 """Get a sequence of informative dicts""" 120 155 folder = self.context … … 166 201 if len(info['properties']['title']) < 1: 167 202 info['properties']['title'] = 'No title' 168 169 infos.append(info) 170 return infos 203 yield info 171 204 172 205 def forKML(self): … … 216 249 if len(info['properties']['title']) < 1: 217 250 info['properties']['title'] = 'No title' 218 219 infos.append(info) 220 return infos 221 251 yield info 252 PleiadesGeocoder/trunk/geo.py
r1218 r1221 65 65 annotations[ANNO_KEY] = PersistentDict() 66 66 self.georef = annotations[ANNO_KEY] 67 self.georef['srs'] = 'EPSG:4326'68 67 self.georef['geometryType'] = None 69 68 self.georef['spatialCoordinates'] = None 70 69 71 def getSRS(self): 72 return self.georef['srs'] 73 74 def setSRS(self, srs): 75 try: 76 assert (srs.startswith('EPSG') or srs.find('proj') >= 0) 77 except AssertionError: 78 raise ValueError, \ 79 "%s is invalid. Spatial reference system definition must be in EPSG or PROJ.4 form" % (srs) 80 self.georef['srs'] = srs 81 82 def getGeometryType(self): 83 return self.georef['geometryType'] 70 def isGeoreferenced(self): 71 """Return True if the object is "on the map".""" 72 g = self.georef 73 return bool(g['geometryType']) and bool(g['spatialCoordinates']) 84 74 85 75 @property … … 95 85 return None 96 86 97 def setGeometryType(self, geomtype):98 if geomtype not in ['point', 'line', 'polygon', 'box']:99 raise ValueError, \100 """%s is invalid. Supported geometry types are: 'point', 'line', 'polygon', 'box'""" % (geomtype)101 self.georef['geometryType'] = geomtype102 103 def getSpatialCoordinates(self):104 values = [float(v) for v in self.georef['spatialCoordinates'].split()]105 nvalues = len(values)106 npoints = nvalues/3107 coords = []108 for i in range(npoints):109 coords.append(tuple(values[3*i:3*i+3]))110 return tuple(coords)111 112 @property113 def spatialCoordinates(self):114 """GeoRSS Simple coordinate string."""115 values = self.georef['spatialCoordinates'].split()116 nvalues = len(values)117 npoints = nvalues/3118 coords = []119 for i in range(npoints):120 coords.extend(values[3*i:3*i+2])121 return ' '.join(coords)122 123 87 @property 124 88 def coords(self): 125 if not self. georef['spatialCoordinates']:89 if not self.isGeoreferenced(): 126 90 return None 127 91 values = [float(v) for v in self.georef['spatialCoordinates'].split()] … … 131 95 for i in range(npoints): 132 96 coords.append((values[3*i+1], values[3*i], values[3*i+2])) 133 geomtype = self.ge tGeometryType()97 geomtype = self.georef['geometryType'] 134 98 if geomtype == 'point': 135 99 return coords[0] … … 138 102 elif geomtype == 'polygon': 139 103 return (tuple(coords),) 140 141 def setGeometry(self, geomtype, coords):142 # set geometry type143 if geomtype not in ['point', 'line', 'polygon', 'box']:144 raise ValueError, \145 """%s is invalid. Supported geometry types are: 'point', 'line', 'polygon', 'box'""" % (geomtype)146 self.georef['geometryType'] = geomtype147 148 # check number of points against geometry type149 try:150 if geomtype == 'point': assert len(coords) == 1151 if geomtype == 'line': assert len(coords) >= 2152 if geomtype == 'polygon': assert len(coords) >= 4153 if geomtype == 'box': assert len(coords) == 2154 except AssertionError:155 raise ValueError, \156 "Number of coordinates %d is inconsistent with geometry type %s" \157 % (len(coords), geomtype)158 159 value = ''160 for point in coords:161 if len(point) == 3:162 value = ' '.join([value, "%f %f %f" % tuple(point)])163 elif len(point) == 2:164 value = ' '.join([value, "%f %f 0.0" % tuple(point)])165 else:166 raise ValueError, \167 "Insufficient number of ordinates: %s" % str(point)168 self.georef['spatialCoordinates'] = value.lstrip()169 104 170 105 def setGeoInterface(self, geomtype, coordinates): … … 195 130 "Insufficient number of ordinates: %s" % str(point) 196 131 self.georef['spatialCoordinates'] = value.lstrip() 197 198 def isGeoreferenced(self):199 """Return True if the object is "on the map"."""200 g = self.georef201 return bool(g['geometryType']) and bool(g['spatialCoordinates'])202 203 def hasPoint(self):204 if self.getGeometryType() == 'point':205 return 1206 else:207 return 0208 209 def hasLineString(self):210 if self.getGeometryType() == 'line':211 return 1212 else:213 return 0214 215 def hasPolygon(self):216 if self.getGeometryType() == 'polygon':217 return 1218 else:219 return 0220 221 def getInfo(self, dims=3):222 """Return an informative dict."""223 g = self.georef224 context = self.context225 info = {'srs': g['srs'],226 'geometryType': g['geometryType']227 }228 if dims == 3:229 info['spatialCoordinates'] = g['spatialCoordinates']230 values = g['spatialCoordinates'].split()231 nvalues = len(values)232 npoints = nvalues/3233 coords = []234 for i in range(npoints):235 coords.append(tuple(values[3*i:3*i+3]))236 elif dims == 2:237 values = g['spatialCoordinates'].split()238 nvalues = len(values)239 npoints = nvalues/3240 coords = []241 for i in range(npoints):242 coords.extend(values[3*i:3*i+2])243 info['spatialCoordinates'] = ' '.join(coords)244 else:245 raise ValueError, "Invalid dims: %d" % (dims)246 247 # Content objects248 info.update(249 {'id': context.getId(),250 'title': context.title_or_id(),251 'description': context.getProperty('description',252 'No description'),253 'url': context.absolute_url(),254 }255 )256 return info257 132 258 133 @property … … 305 180 yield item 306 181 307 def getItemsInfo(self):308 infos = []309 for item in self.geoItems():310 infos.append(item.getInfo())311 return infos312 182 313 def getBoundingBox(self):314 raise NotImplementedError315 316 317 PleiadesGeocoder/trunk/skins/PleiadesGeocoder/georss.pt
r1161 r1221 5 5 xmlns:gml="http://www.opengis.net/gml" 6 6 xmlns:tal="http://xml.zope.org/namespaces/tal" 7 tal:define=" items context/@@geo/forRSS;8 furl context/absolute_url;9 maxitems request/maxitems | python:len(items)"7 tal:define="furl context/absolute_url; 8 maxitems python:int(request.form.get('maxitems', -1)); 9 item_iterator nocall:context/@@geo/forRSS" 10 10 > 11 11 <tal:b … … 19 19 <author/> 20 20 <id tal:content="furl">ID</id> 21 22 <entry 23 tal:repeat="item python:item s[:int(maxitems)]"21 22 <entry 23 tal:repeat="item python:item_iterator(maxitems)" 24 24 > 25 25 <title tal:content="item/properties/title">TITLE</title> PleiadesGeocoder/trunk/tests/FolderGeoViews.txt
r1174 r1221 23 23 >>> member = mt.getMemberById('test_user_1_') 24 24 >>> member.setMemberProperties( 25 ... {' srs':'EPSG:4326', 'geometryType':'point',25 ... {'geometryType':'point', 26 26 ... 'spatialCoordinates':'40.585609 -105.083733 0.0', 27 27 ... 'fullname': 'Test User', … … 34 34 >>> document = folder.document 35 35 >>> item = IGeoItemSimple(document) 36 >>> item.setSRS('EPSG:4326') 37 >>> item.setGeometry('point', ((40.585609, -105.083733),)) 36 >>> item.setGeoInterface('Point', (-105.083733, 40.585609)) 38 37 >>> item.isGeoreferenced() 39 38 True PleiadesGeocoder/trunk/tests/test_simple.py
r1218 r1221 38 38 39 39 item = IGeoItemSimple(self.document) 40 item.setSRS('EPSG:4326') 41 item.setGeometry('point', ((40.585609, -105.083733),)) 40 item.setGeoInterface('Point', (-105.083733, 40.585609)) 42 41 43 42 def testInterfaces(self): … … 51 50 def testGetValues(self): 52 51 item = IGeoItemSimple(self.document) 53 self.failUnlessEqual(item.getSRS(), 'EPSG:4326') 54 self.failUnlessEqual(item.getGeometryType(), 'point') 55 self.failUnlessEqual(item.getSpatialCoordinates(), 56 ((40.585609, -105.083733, 0.0),) 57 ) 58 59 def testInfo(self): 60 item = IGeoItemSimple(self.document) 61 info = item.getInfo() 62 self.failUnlessEqual(info['srs'], 'EPSG:4326') 63 self.failUnlessEqual(info['geometryType'], 'point') 64 self.failUnlessEqual(info['description'], 'No description') 65 self.failUnlessEqual(info['spatialCoordinates'], 66 '40.585609 -105.083733 0.0') 67 self.failUnlessEqual(info['url'], 68 'http://nohost/plone/Members/test_user_1_/document') 69 self.failUnlessEqual(info['title'], 'document') 70 self.failUnlessEqual(info['id'], 'document') 71 72 def testFolderInfo(self): 73 collection = IGeoCollectionSimple(self.folder) 74 infos = collection.getItemsInfo() 75 self.failUnlessEqual(len(infos), 1) 76 self.failUnlessEqual(infos[0]['spatialCoordinates'], 77 '40.585609 -105.083733 0.0') 78 52 self.failUnlessEqual(item.geom_type, 'Point') 53 self.failUnlessEqual(item.coords, (-105.083733, 40.585609, 0.0)) 79 54 80 55 class MemberTest(PloneTestCase.PloneTestCase): … … 90 65 member = mt.getMemberById(default_user) 91 66 member.setMemberProperties( 92 {' srs':'EPSG:4326', 'geometryType':'point',67 {'geometryType':'point', 93 68 'spatialCoordinates':'40.585609 -105.083733 0.0'}) 94 69 … … 96 71 mt = self.portal.portal_membership 97 72 member = mt.getMemberById(default_user) 98 self.failUnlessEqual(member.getProperty('srs'), 'EPSG:4326')99 73 self.failUnlessEqual(member.getProperty('geometryType'), 'point') 100 74 self.failUnlessEqual(member.getProperty('spatialCoordinates'),
