Changeset 1221

Show
Ignore:
Timestamp:
11/05/07 15:06:43 (1 year ago)
Author:
sgillies
Message:

Pare down IGeoItemSimple to the bare minimum methods and attributes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • PleiadesGeocoder/trunk/CHANGES.txt

    r1218 r1221  
    44All ticket numbers are relative to http://icon.stoa.org/trac/pleiades/tickets. 
    55 
    6 1.0b1 
    7 ----- 
     61.0b1: 5 November 2007 
     7---------------------- 
     8 
    89- IGeoserializeable and IGeoreferenceable are now markers for viewables only. 
    910- 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. 
    1015 
    11 1.0a1 
    12 ----- 
    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, 2007 
    19 ------------------------- 
    20 - Update to KML 2.1. 
    21 - Add name and description to network link and folders. 
    22  
  • PleiadesGeocoder/trunk/HISTORY.txt

    r630 r1221  
    33 
    44All ticket numbers are relative to http://icon.stoa.org/trac/pleiades/tickets. 
     5 
     61.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 
     130.6.2 - 20 February, 2007 
     14------------------------- 
     15- Update to KML 2.1. 
     16- Add name and description to network link and folders. 
    517 
    6180.6.1 - 9 Ocober 2006 
  • PleiadesGeocoder/trunk/browser/info.py

    r1185 r1221  
    3636class IGeoInfosetView(Interface): 
    3737 
    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        """ 
    4046 
    4147    def forKML(): 
    42         """Process into an infoset for export to KML.""" 
     48        """Returns an iterator over KML compatible data.""" 
     49 
     50 
     51def 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 
     67def 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 
     79class 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 
    43131 
    44132def get_coords(coord_string, geomtype='point'): 
     
    56144        return (tuple(coords),) 
    57145 
    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 
     147class GeoMembersInfosetView(BrowserView): 
    71148 
    72149    """View of content that supports GeoRSS and KML output. 
     
    74151    implements(IGeoInfosetView) 
    75152 
    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): 
    119154        """Get a sequence of informative dicts""" 
    120155        folder = self.context 
     
    166201            if len(info['properties']['title']) < 1: 
    167202                info['properties']['title'] = 'No title' 
    168                  
    169             infos.append(info) 
    170         return infos 
     203            yield info 
    171204 
    172205    def forKML(self): 
     
    216249            if len(info['properties']['title']) < 1: 
    217250                info['properties']['title'] = 'No title' 
    218                  
    219             infos.append(info) 
    220         return infos 
    221  
     251            yield info 
     252 
  • PleiadesGeocoder/trunk/geo.py

    r1218 r1221  
    6565            annotations[ANNO_KEY] = PersistentDict() 
    6666            self.georef = annotations[ANNO_KEY] 
    67             self.georef['srs'] = 'EPSG:4326' 
    6867            self.georef['geometryType'] = None 
    6968            self.georef['spatialCoordinates'] = None 
    7069 
    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']) 
    8474 
    8575    @property 
     
    9585            return None 
    9686 
    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'] = geomtype 
    102  
    103     def getSpatialCoordinates(self): 
    104         values = [float(v) for v in self.georef['spatialCoordinates'].split()] 
    105         nvalues = len(values) 
    106         npoints = nvalues/3 
    107         coords = [] 
    108         for i in range(npoints): 
    109             coords.append(tuple(values[3*i:3*i+3])) 
    110         return tuple(coords) 
    111  
    112     @property 
    113     def spatialCoordinates(self): 
    114         """GeoRSS Simple coordinate string.""" 
    115         values = self.georef['spatialCoordinates'].split() 
    116         nvalues = len(values) 
    117         npoints = nvalues/3 
    118         coords = [] 
    119         for i in range(npoints): 
    120             coords.extend(values[3*i:3*i+2]) 
    121         return ' '.join(coords) 
    122  
    12387    @property 
    12488    def coords(self): 
    125         if not self.georef['spatialCoordinates']
     89        if not self.isGeoreferenced()
    12690            return None 
    12791        values = [float(v) for v in self.georef['spatialCoordinates'].split()] 
     
    13195        for i in range(npoints): 
    13296            coords.append((values[3*i+1], values[3*i], values[3*i+2])) 
    133         geomtype = self.getGeometryType() 
     97        geomtype = self.georef['geometryType'] 
    13498        if geomtype == 'point': 
    13599            return coords[0] 
     
    138102        elif geomtype == 'polygon': 
    139103            return (tuple(coords),) 
    140  
    141     def setGeometry(self, geomtype, coords): 
    142         # set geometry type 
    143         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'] = geomtype 
    147  
    148         # check number of points against geometry type 
    149         try: 
    150             if geomtype == 'point': assert len(coords) == 1 
    151             if geomtype == 'line': assert len(coords) >= 2 
    152             if geomtype == 'polygon': assert len(coords) >= 4 
    153             if geomtype == 'box': assert len(coords) == 2 
    154         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() 
    169104 
    170105    def setGeoInterface(self, geomtype, coordinates): 
     
    195130                "Insufficient number of ordinates: %s" % str(point) 
    196131        self.georef['spatialCoordinates'] = value.lstrip() 
    197  
    198     def isGeoreferenced(self): 
    199         """Return True if the object is "on the map".""" 
    200         g = self.georef 
    201         return bool(g['geometryType']) and bool(g['spatialCoordinates']) 
    202  
    203     def hasPoint(self): 
    204         if self.getGeometryType() == 'point': 
    205             return 1 
    206         else: 
    207             return 0 
    208          
    209     def hasLineString(self): 
    210         if self.getGeometryType() == 'line': 
    211             return 1 
    212         else: 
    213             return 0 
    214  
    215     def hasPolygon(self): 
    216         if self.getGeometryType() == 'polygon': 
    217             return 1 
    218         else: 
    219             return 0 
    220  
    221     def getInfo(self, dims=3): 
    222         """Return an informative dict.""" 
    223         g = self.georef 
    224         context = self.context 
    225         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/3 
    233             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/3 
    240             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 objects 
    248         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 info 
    257132 
    258133    @property 
     
    305180            yield item 
    306181 
    307     def getItemsInfo(self): 
    308         infos = [] 
    309         for item in self.geoItems(): 
    310             infos.append(item.getInfo()) 
    311         return infos 
    312182 
    313     def getBoundingBox(self): 
    314         raise NotImplementedError 
    315  
    316  
    317  
  • PleiadesGeocoder/trunk/skins/PleiadesGeocoder/georss.pt

    r1161 r1221  
    55  xmlns:gml="http://www.opengis.net/gml"   
    66  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
    1010  > 
    1111  <tal:b  
     
    1919  <author/> 
    2020  <id tal:content="furl">ID</id> 
    21      
    22   <entry 
    23     tal:repeat="item python:items[:int(maxitems)]
     21 
     22  <entry  
     23    tal:repeat="item python:item_iterator(maxitems)
    2424    > 
    2525    <title tal:content="item/properties/title">TITLE</title> 
  • PleiadesGeocoder/trunk/tests/FolderGeoViews.txt

    r1174 r1221  
    2323    >>> member = mt.getMemberById('test_user_1_') 
    2424    >>> member.setMemberProperties( 
    25     ...     {'srs':'EPSG:4326', 'geometryType':'point', 
     25    ...     {'geometryType':'point', 
    2626    ...      'spatialCoordinates':'40.585609 -105.083733 0.0', 
    2727    ...      'fullname': 'Test User', 
     
    3434    >>> document = folder.document 
    3535    >>> item = IGeoItemSimple(document) 
    36     >>> item.setSRS('EPSG:4326') 
    37     >>> item.setGeometry('point', ((40.585609, -105.083733),)) 
     36    >>> item.setGeoInterface('Point', (-105.083733, 40.585609)) 
    3837    >>> item.isGeoreferenced() 
    3938    True 
  • PleiadesGeocoder/trunk/tests/test_simple.py

    r1218 r1221  
    3838 
    3939        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)) 
    4241 
    4342    def testInterfaces(self): 
     
    5150    def testGetValues(self): 
    5251        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)) 
    7954 
    8055class MemberTest(PloneTestCase.PloneTestCase): 
     
    9065        member = mt.getMemberById(default_user) 
    9166        member.setMemberProperties( 
    92                 {'srs':'EPSG:4326', 'geometryType':'point', 
     67                {'geometryType':'point', 
    9368                 'spatialCoordinates':'40.585609 -105.083733 0.0'}) 
    9469         
     
    9671        mt = self.portal.portal_membership 
    9772        member = mt.getMemberById(default_user) 
    98         self.failUnlessEqual(member.getProperty('srs'), 'EPSG:4326') 
    9973        self.failUnlessEqual(member.getProperty('geometryType'), 'point') 
    10074        self.failUnlessEqual(member.getProperty('spatialCoordinates'),