Changeset 5629


Ignore:
Timestamp:
18/08/09 14:51:08 (10 years ago)
Author:
domlowe
Message:

Merging in qesdi changes to cows trunk - still need to merge new backend.

Location:
cows/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • cows/trunk

    • Property svn:ignore set to
      .project
      .pydevproject
      cows.egg-info
  • cows/trunk/cows/model/wms.py

    r5174 r5629  
    4646    """ 
    4747    def __init__(self, CRSs=[], styles=[''], dimensions={}, attribution=None, authorityURLs=[], 
    48                  dataURLs=[], featureListURLs=[], 
     48                 dataURLs=[], featureListURLs=[], metadataURLs=[], 
    4949                 minScaleDenominator=None, maxScaleDenominator=None, 
    5050                 queryable=False, **kw): 
     
    6161        self.maxScaleDenominator = maxScaleDenominator 
    6262        self.queryable = queryable 
     63        self.metadataURLs = metadataURLs 
    6364 
    6465class Style(object): 
     
    149150        self.width = width 
    150151        self.height = height 
    151          
     152 
     153class MetadataURL(FormattedURL): 
     154    """ 
     155    @ivar metadataType 
     156    @type metadataType: None or str 
     157    """ 
     158    def __init__(self, metadataType=None, **kw): 
     159        super(MetadataURL, self).__init__(**kw) 
     160        self.type = metadataType 
     161 
    152162# 
    153163#!TODO: Other objects referenced by WmsDatasetSummary 
  • cows/trunk/cows/pylons/templates/catalogue.xml

    r5378 r5629  
    3838                            request='GetCapabilities', service='WFS')}" 
    3939                            >WFS</a>] 
    40         [<a href="${url_for(cowsclienturl) + 'ENDPOINT=' + serverurl +url_for(controller='csmlwms', fileoruri=fc, id=None, 
    41                             request='GetContext', service='WMS')}" 
     40        [<a href="${url_for(cowsclienturl) + 'ENDPOINT=' + serverurl +url_for(controller='csmlwms', fileoruri=fc, id=None)}" 
    4241                            >Visualize</a>] 
    4342      </li> 
  • cows/trunk/cows/pylons/templates/wms_capabilities_1_3_0.xml

    r4910 r5629  
    1010 
    1111<WMS_Capabilities xmlns:py="http://genshi.edgewall.org/" 
    12                   xmlns="http://www.opengis.net/wms" 
    13                   xmlns:xlink="http://www.w3.org/1999/xlink" 
    14                   version="1.3.0"> 
     12          xmlns="http://www.opengis.net/wms" 
     13          xmlns:xlink="http://www.w3.org/1999/xlink" 
     14          version="1.3.0"> 
    1515 
    1616  <!--! ====================================================================== --> 
     
    2424    <DCPType><HTTP> 
    2525      <Get> 
    26         <OnlineResource xlink:type="simple" xlink:href="${op.get.href}"/> 
     26    <OnlineResource xlink:type="simple" xlink:href="${op.get.href}"/> 
    2727      </Get> 
    2828    </HTTP></DCPType> 
     
    3737 
    3838  ?> 
     39 
     40 
     41<?python 
     42 
     43    def showAtt(obj, attname): 
     44        if not hasattr(obj,attname) or getattr(obj, attname) == None: 
     45            return '' 
     46             
     47        return getattr(obj, attname) 
     48          
     49 
     50?> 
     51 
     52    <py:def function="markupLegendURL(l)"> 
     53      <LegendURL width="${l.width}" height="${l.height}"> 
     54         <Format>${l.format}</Format> 
     55         <OnlineResource xlink:type="simple" xlink:href="${l.onlineResource.href}"/> 
     56      </LegendURL> 
     57    </py:def> 
     58 
     59 
     60    <py:def function="markupStyle(s)"> 
     61      <Style> 
     62        <Name>${s.name}</Name> 
     63        <Title>${s.title}</Title> 
     64        <py:for each="l in s.legendURLs" py:if="getattr(s, 'legendURLs', None) != None"> 
     65          ${markupLegendURL(l)} 
     66        </py:for> 
     67      </Style> 
     68    </py:def> 
     69     
     70    <py:def function="markupMetadataURL(l)"> 
     71      <MetadataURL type="${showAtt(l, 'type')}" > 
     72         <Format>${l.format}</Format> 
     73         <OnlineResource xlink:type="simple" xlink:href="${l.onlineResource.href}"/> 
     74      </MetadataURL> 
     75    </py:def>     
    3976 
    4077  <Layer py:def="markupLayer(ds)" queryable="${int(ds.queryable)}"> 
     
    5390    <py:for each="bb in ds.boundingBoxes"> 
    5491      <BoundingBox CRS="${bb.crs}" 
    55                    minx="${'%.2f'%bb.lowerCorner[0]}" 
    56                    miny="${'%.2f'%bb.lowerCorner[1]}" 
    57                    maxx="${'%.2f'%bb.upperCorner[0]}" 
    58                    maxy="${'%.2f'%bb.upperCorner[1]}"/> 
     92           minx="${'%.2f'%bb.lowerCorner[0]}" 
     93           miny="${'%.2f'%bb.lowerCorner[1]}" 
     94           maxx="${'%.2f'%bb.upperCorner[0]}" 
     95           maxy="${'%.2f'%bb.upperCorner[1]}"/> 
    5996    </py:for> 
    6097 
     
    71108 
    72109    <Dimension py:for="d_n, d in ds.dimensions.iteritems()" 
    73                name="${d_n}" units="${d.valuesUnit}" 
    74                unitSymbol="${d.unitSymbol}" 
    75                default="${d.defaultValue}"  
    76                py:content="','.join(d.possibleValues.allowedValues)"/> 
     110           name="${d_n}" units="${d.valuesUnit}" 
     111           unitSymbol="${d.unitSymbol}" 
     112           default="${d.defaultValue}"  
     113           py:content="','.join(d.possibleValues.allowedValues)"/> 
    77114<!--! nearestValue="${int(d.nearestValue)}" --> 
    78     <Style> 
    79       <Name>default</Name> 
    80       <Title>Default</Title> 
    81       <LegendURL width="${ds.legendSize[0]}" height="${ds.legendSize[1]}"> 
    82         <Format py:for="f in ds.legendFormats" py:content="f"/> 
    83         <OnlineResource xlink:type="simple" xlink:href="${url_for(qualified=True, action='index')}?request=GetLegend&amp;layers=${ds.identifier}"/> 
    84       </LegendURL> 
    85     </Style> 
     115 
     116     
     117     
     118    <py:choose test="ds.styles"> 
     119 
     120        <py:when test="['']"> 
     121            <Style> 
     122                <Name>default</Name> 
     123                <Title>Default</Title> 
     124                <LegendURL width="${ds.legendSize[0]}" height="${ds.legendSize[1]}"> 
     125                    <Format py:for="f in ds.legendFormats" py:content="f"/> 
     126                    <OnlineResource xlink:type="simple" xlink:href="${url_for(qualified=True, action='index')}?request=GetLegend&amp;layers=${ds.identifier}"/> 
     127                </LegendURL> 
     128            </Style> 
     129        </py:when> 
     130 
     131        <py:otherwise> 
     132            <py:for each="s in ds.styles" py:if="getattr(ds, 'styles', None) != None"> 
     133                ${markupStyle(s)} 
     134            </py:for> 
     135        </py:otherwise> 
     136 
     137    </py:choose> 
     138     
     139    <py:if test="len(ds.metadataURLs) > 0"> 
     140        <py:for each="url in ds.metadataURLs"> 
     141            ${markupMetadataURL(url)} 
     142        </py:for> 
     143    </py:if> 
    86144 
    87145 
     
    97155    <KeywordList> 
    98156      <Keyword py:for="kw in si.keywords" 
    99                py:content="kw"/> 
     157           py:content="kw"/> 
    100158    </KeywordList> 
    101159    <OnlineResource xlink:type="simple" xlink:href="${url_for(qualified=True, action='index')}?"/> 
    102160     
    103161    <ContactInformation py:if="sm.serviceProvider is not None" 
    104                         py:with="rp=sm.serviceProvider.serviceContact"> 
     162            py:with="rp=sm.serviceProvider.serviceContact"> 
    105163      <ContactPersonPrimary> 
    106         <ContactPerson py:if="rp is not None" py:content="rp.individualName"/> 
    107         <ContactOrganization py:content="sm.serviceProvider.providerName"/> 
     164    <ContactPerson py:if="rp is not None" py:content="rp.individualName"/> 
     165    <ContactOrganization py:content="sm.serviceProvider.providerName"/> 
    108166      </ContactPersonPrimary> 
    109167      <ContactPosition py:content="rp.positionName"/> 
    110168 
    111169      <py:with vars="cn=rp.contactInfo" py:if="rp.contactInfo is not None"> 
    112         <ContactAddress py:if="cn.address is not None"> 
    113           <AddressType>postal</AddressType> 
    114           <Address> 
    115             <py:for each="d in cn.address.deliveryPoints">${d}</py:for> 
    116           </Address> 
    117           <City py:content="cn.address.city"/> 
    118           <StateOrProvince py:content="cn.address.administrativeArea"/> 
    119           <PostCode py:content="cn.address.postalCode"/> 
    120           <Country py:content="cn.address.country"/> 
    121         </ContactAddress> 
    122         <ContactVoiceTelephone py:if="cn.phone is not None" 
    123                                py:content="cn.phone.voice"/> 
    124         <ContactFacsimileTelephone py:if="cn.phone is not None" 
    125                                    py:content="cn.phone.facsimile"/> 
    126         <ContactElectronicMailAddress py:if="cn.address is not None" 
    127                                       py:content="cn.address.electronicMailAddress"/> 
     170    <ContactAddress py:if="cn.address is not None"> 
     171      <AddressType>postal</AddressType> 
     172      <Address> 
     173        <py:for each="d in cn.address.deliveryPoints">${d}</py:for> 
     174      </Address> 
     175      <City py:content="cn.address.city"/> 
     176      <StateOrProvince py:content="cn.address.administrativeArea"/> 
     177      <PostCode py:content="cn.address.postalCode"/> 
     178      <Country py:content="cn.address.country"/> 
     179    </ContactAddress> 
     180    <ContactVoiceTelephone py:if="cn.phone is not None" 
     181                   py:content="cn.phone.voice"/> 
     182    <ContactFacsimileTelephone py:if="cn.phone is not None" 
     183                   py:content="cn.phone.facsimile"/> 
     184    <ContactElectronicMailAddress py:if="cn.address is not None" 
     185                      py:content="cn.address.electronicMailAddress"/> 
    128186      </py:with> 
    129187    </ContactInformation> 
     
    142200    <py:if test="om is not None"> 
    143201      <?python 
    144         ops = ['GetCapabilities', 'GetMap', 'GetFeatureInfo'] 
    145         eops = [x for x in om.operationDict.keys() if x not in ops] 
     202    ops = ['GetCapabilities', 'GetMap', 'GetFeatureInfo'] 
     203    eops = [x for x in om.operationDict.keys() if x not in ops] 
    146204      ?> 
    147205      <Request> 
    148         <py:for each="opName in ops" py:if="opName in om.operationDict.keys()"> 
    149           <span py:content="markupOperation(opName, om.operationDict[opName])" py:strip="True"/> 
    150         </py:for> 
    151         <py:for each="opName in ops" py:if="opName in om.operationDict.keys()"> 
    152           <?python exceptions = om.operationDict[opName].parameters.get('ExceptionFormat') ?> 
    153           <Exception py:if="exceptions is not None"> 
    154             <Format py:for="e in exceptions.possibleValues.allowedValues" 
    155                     py:content="e"/> 
    156           </Exception> 
    157         </py:for> 
     206    <py:for each="opName in ops" py:if="opName in om.operationDict.keys()"> 
     207      <span py:content="markupOperation(opName, om.operationDict[opName])" py:strip="True"/> 
     208    </py:for> 
     209    <py:for each="opName in ops" py:if="opName in om.operationDict.keys()"> 
     210      <?python exceptions = om.operationDict[opName].parameters.get('ExceptionFormat') ?> 
     211      <Exception py:if="exceptions is not None"> 
     212        <Format py:for="e in exceptions.possibleValues.allowedValues" 
     213            py:content="e"/> 
     214      </Exception> 
     215    </py:for> 
    158216      </Request> 
    159217 
     
    163221      <_ExtendedCapabilities> 
    164222      <Request> 
    165         <py:for each="opName in eops"> 
    166           <span py:content="markupOperation(opName, om.operationDict[opName])" py:strip="True"/> 
    167         </py:for> 
    168         <py:for each="opName in eops"> 
    169           <?python exceptions = om.operationDict[opName].parameters.get('ExceptionFormat') ?> 
    170           <Exception py:if="exceptions is not None"> 
    171             <Format py:for="e in exceptions.possibleValues.allowedValues" 
    172                     py:content="e"/> 
    173           </Exception> 
    174         </py:for> 
     223    <py:for each="opName in eops"> 
     224      <span py:content="markupOperation(opName, om.operationDict[opName])" py:strip="True"/> 
     225    </py:for> 
     226    <py:for each="opName in eops"> 
     227      <?python exceptions = om.operationDict[opName].parameters.get('ExceptionFormat') ?> 
     228      <Exception py:if="exceptions is not None"> 
     229        <Format py:for="e in exceptions.possibleValues.allowedValues" 
     230            py:content="e"/> 
     231      </Exception> 
     232    </py:for> 
    175233      </Request> 
    176234      </_ExtendedCapabilities> 
     
    180238      <Title>Contents</Title> 
    181239      <Layer py:for="ds in sm.contents.datasetSummaries" 
    182              py:replace="markupLayer(ds)"> 
     240         py:replace="markupLayer(ds)"> 
    183241      </Layer> 
    184242    </Layer> 
  • cows/trunk/cows/pylons/wms_controller.py

    r5424 r5629  
    151151                log.info("dataURLs not populated: could not generate WCS url with url_for('wcsroute', filedoruri=%s,qualified=True)"%c.fileoruri) 
    152152                dataURLs=[] 
     153                 
     154             
     155             
     156             
     157            if hasattr(layer, 'styles'): 
     158                styles = layer.styles 
     159            else: 
     160                styles = [''] 
     161             
     162            if hasattr(layer, 'metadataURLs'): 
     163                metadataURLs = layer.metadataURLs 
     164            else: 
     165                metadataURLs = [] 
     166             
    153167            # Create the cows object 
    154168            ds = WmsDatasetSummary(identifier=layerName, 
     
    160174                                   dimensions=dims, 
    161175                                   queryable=queryable, 
    162                                    dataURLs=dataURLs) 
     176                                   dataURLs=dataURLs, 
     177                                   styles=styles, 
     178                                   metadataURLs=metadataURLs) 
    163179 
    164180            # Stuff that should go in the capabilities tree eventually 
     
    208224        layers = {} 
    209225        layerNames = self.getOwsParam(paramName) 
    210  
     226         
    211227        # Select the first layer if several are requested. 
    212228        # This plays nicer with mapClient. 
    213         #if ',' in layerName: 
    214229        layerNames = layerNames.split(',') 
    215             #raise InvalidParameterValue( 
    216             #    'Multi-layer GetMap requests are not supported', 'layers') 
     230         
     231        layerObjects = [] 
     232         
    217233        for layerName in layerNames: 
    218234            try: 
    219235                layerObj = self.layers[layerName] 
    220                 layers[layerName] = layerObj 
     236                layerObjects.append(layerObj) 
    221237            except KeyError: 
    222238                raise InvalidParameterValue('Layer %s not found' % layerName, 
    223239                                        paramName) 
    224240 
    225         #return layerName, layerObj 
    226         return layers 
     241        return layerObjects 
    227242 
    228243    def _getFormatParam(self): 
     
    278293 
    279294 
    280     def _retrieveSlab(self, layerObj, srs, dimValues, renderOpts): 
     295    def _retrieveSlab(self, layerObj, srs, style, dimValues, transparent, bgcolor, additionalParams): 
     296         
    281297        # Find the slab in the cache first 
    282         cacheKey = layerObj.getCacheKey(srs, dimValues) 
     298        cacheKey = layerObj.getCacheKey(srs, style, dimValues, transparent, bgcolor, additionalParams) 
    283299        slab = self._layerSlabCache.get(cacheKey) 
     300         
    284301        if slab is None: 
    285             slab = layerObj.getSlab(srs, dimValues, renderOpts) 
     302             
     303            slab = layerObj.getSlab(srs, style, dimValues, transparent, bgcolor, additionalParams) 
     304             
    286305            if cacheKey is not None: 
    287306                self._layerSlabCache[cacheKey] = slab 
     
    294313    def GetMap(self): 
    295314 
    296         # Housekeeping 
    297         version = self.getOwsParam('version', default=self.validVersions[0]) 
    298         if version not in self.validVersions: 
    299             raise InvalidParameterValue('Version %s not supported' % version, 
    300                                         'version') 
    301         styles = self.getOwsParam('styles', default='') 
    302         transparent = self.getOwsParam('transparent', default='FALSE') 
    303         bgcolor = self.getOwsParam('bgcolor', default='0xFFFFFF') 
    304  
    305         # Layer handling 
    306         #layerName, layerObj = self._getLayerParam() 
    307         layers = self._getLayerParam() 
    308         log.debug('GetMap request for layer(s) %s'%layers) 
    309         # Coordinate parameters 
    310         bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(',')) 
    311         width = int(self.getOwsParam('width')) 
    312         height = int(self.getOwsParam('height')) 
    313  
    314         if version == '1.1.1': 
    315             srs = self.getOwsParam('srs') 
    316         else: 
    317             srs = self.getOwsParam('crs') 
    318  
    319         #if srs not in layerObj.crss: 
    320          #   raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs)) 
    321  
    322         # Get format 
    323         format = self.getOwsParam('format') 
    324         if format not in self._pilImageFormats: 
    325             raise InvalidParameterValue( 
    326                 'Format %s not supported' % format, 'format') 
    327  
     315        # Get the parameters 
     316        version      = self._getVersionParam() 
     317        format       = self._getFormatParam()         
     318        transparent  = self._getTransparentParam() 
     319        bgcolor      = self._getBgcolorParam() 
     320        bbox         = self._getBboxParam() 
     321        width        = self._getWidthParam() 
     322        height       = self._getHeightParam() 
     323         
     324        layerObjects = self._getLayerParam() 
     325         
     326        styles       = self._getStylesParam(len(layerObjects)) 
     327        srs          = self._getSrsParam(version) 
     328         
     329        log.debug("layerNames = %s" % ([o.name for o in layerObjects],)) 
     330         
    328331        finalImg = Image.new('RGBA', (width, height), (0,0,0,0)) 
    329          
     332 
    330333        # Multiple Layers handling..   
    331         for layerName, layerObj in layers.iteritems(): 
     334        for i in range(len(layerObjects)): 
     335            layerObj = layerObjects[i] 
     336             
     337            #if no styles provided, set style = ""             
     338            if styles == "": 
     339                style = "" 
     340            else: 
     341                style = styles[i] 
     342             
    332343            if srs not in layerObj.crss: 
    333                 raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs)) 
     344                raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerObj.name, srs)) 
    334345 
    335346            dimValues = self._getDimValues(layerObj) 
     
    340351                restoredDim=self._mapParamToDim(dim) 
    341352                restoredDimValues[restoredDim]=dimValues[dim] 
    342                  
    343             #------------------------------------------------------- 
    344             # The real work 
    345             #!TODO: Minimum and maximum values 
    346  
    347             slab = self._retrieveSlab(layerObj, srs, restoredDimValues, 
    348                                       dict(minValue=0, maxValue=100)) 
    349  
    350             # We must request a bbox within the layer's bbox. 
    351             lbbox = layerObj.getBBox(srs) 
    352             ibbox = bbox_util.intersection(bbox, lbbox) 
    353  
    354             log.debug('bbox = %s' % (bbox,)) 
    355             log.debug('lbbox = %s' % (lbbox,)) 
    356             log.debug('ibbox = %s' % (ibbox,)) 
    357  
    358             # If bbox is not within layerObj.bbox then we need to calculate the 
    359             # pixel offset of the inner bbox, request the right width/height 
    360             # and paste the image into a blank background 
    361             if bbox == ibbox: 
    362                 img = slab.getImage(bbox, width, height) 
    363                 log.debug('slab image.size = %s' % (img.size,)) 
    364                          
    365             else: 
    366                  
    367                 ix0, iy0 = bbox_util.geoToPixel(ibbox[0], ibbox[3], bbox, width, height, 
    368                                                 roundUpY=True) 
    369                 ix1, iy1 = bbox_util.geoToPixel(ibbox[2], ibbox[1], bbox, width, height, 
    370                                                 roundUpX=True) 
    371                 iw = ix1-ix0 
    372                 ih = iy1-iy0 
    373                 log.debug('Deduced inner image: %s, (%d x %d)' % ((ix0, iy0, ix1, iy1), iw, ih)) 
    374                 img1 = slab.getImage(ibbox, iw, ih) 
    375  
    376                 img = Image.new('RGBA', (width, height)) 
    377                 img.paste(img1, (ix0, iy0)) 
    378                  
    379             finalImg = Image.composite(finalImg, img, finalImg)  
    380              
    381            
    382            
    383          
     353             
     354            expectedParams = [] 
     355            expectedParams.extend(self._escapedDimNames) 
     356            expectedParams.extend(layerObj.dimensions.keys()) 
     357             
     358            #get any other parameters on the request that the layer might need 
     359            additionalParams = self._getAdditionalParameters(expectedParams) 
     360             
     361            slab = self._retrieveSlab(layerObj, srs, style, dimValues,  
     362                                      transparent, bgcolor, additionalParams) 
     363 
     364            img = slab.getImage(bbox, width, height) 
     365             
     366            finalImg = Image.composite(finalImg, img, finalImg)     
     367 
    384368        # IE < 7 doesn't display the alpha layer right.  Here we sniff the 
    385369        # user agent and remove the alpha layer if necessary. 
     
    392376                finalImg = finalImg.convert('RGB') 
    393377 
    394         buf = StringIO() 
    395         finalImg.save(buf, self._pilImageFormats[format]) 
    396  
    397         response.headers['Content-Type'] = format 
    398         response.write(buf.getvalue()) 
     378        self._writeImageResponse(finalImg, format) 
    399379 
    400380 
     
    507487        format = self._getFormatParam() 
    508488 
    509         # This hook alows extra arguments to be passed to the layer backend.  It 
    510         # is required for UKCP. 
    511         renderOpts = dict(request_params=self._owsParams) 
    512  
    513         img = layerObj.getLegendImage(renderOpts=renderOpts) 
    514  
    515         buf = StringIO() 
    516         img.save(buf, self._pilImageFormats[format]) 
    517  
    518         response.headers['Content-Type'] = format 
    519         response.write(buf.getvalue()) 
     489        # This hook alows extra arguments to be passed to the layer backend. 
     490        additionalParams = self._getAdditionalParameters(['format']) 
     491         
     492        img = layerObj.getLegendImage(renderOpts=additionalParams) 
     493         
     494        self._writeImageResponse(img, format) 
     495 
    520496 
    521497 
     
    528504 
    529505             
     506    def _getAdditionalParameters(self, expectedParams): 
     507         
     508        additionalParams = {} 
     509         
     510        for paramName, paramValue in self._owsParams.items(): 
     511             
     512            paramName = paramName.lower() 
     513                         
     514            #ignore any of the expected parameters 
     515            if paramName in [p.lower() for p in expectedParams]: 
     516                continue 
     517             
     518            additionalParams[paramName] = paramValue 
     519             
     520        return additionalParams 
     521     
     522    def _getStylesParam(self, numLayers): 
     523        styles = self.getOwsParam('styles', default="") 
     524         
     525        if styles != "": 
     526            styles = styles.split(',') 
     527             
     528            assert len(styles) == numLayers, \ 
     529               "Number of styles %s didn't match the number of layers %s" % ( len(styles), numLayers) 
     530 
     531        return styles 
     532 
     533    def _getTransparentParam(self): 
     534        transparent = self.getOwsParam('transparent', default='FALSE') 
     535        return transparent.lower() == 'true' 
     536     
     537    def _getBgcolorParam(self): 
     538        return self.getOwsParam('bgcolor', default='0xFFFFFF') 
     539 
     540    def _getVersionParam(self): 
     541        version = self.getOwsParam('version', default=self.validVersions[0]) 
     542         
     543        if version not in self.validVersions: 
     544            raise InvalidParameterValue('Version %s not supported' % version, 'version') 
     545         
     546        return version 
     547 
     548    def _getSrsParam(self, version): 
     549        if version == '1.1.1': 
     550            srs = self.getOwsParam('srs') 
     551        else: 
     552            srs = self.getOwsParam('crs') 
     553             
     554        return srs 
     555 
     556    def _getBboxParam(self): 
     557        bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(',')) 
     558        return bbox 
     559     
     560    def _getWidthParam(self): 
     561        return int(self.getOwsParam('width')) 
     562     
     563    def _getHeightParam(self): 
     564        return int(self.getOwsParam('height')) 
     565     
     566 
     567    def _writeImageResponse(self, pilImage, format): 
     568         
     569        buf = StringIO() 
     570        pilImage.save(buf, self._pilImageFormats[format]) 
     571 
     572        response.headers['Content-Type'] = format 
     573        response.write(buf.getvalue())     
  • cows/trunk/cows/service/imps/csmlbackend/wms_csmllayer.py

    r5511 r5629  
    3131from cows.service.wms_iface import IwmsLayer, IwmsDimension, IwmsLayerSlab 
    3232from cows.service.imps.csmlbackend.csmlcommon import CSMLLayerMapper, CSMLConnector 
    33 import Image 
     33 
     34try: 
     35    from PIL import Image 
     36except: 
     37    import Image 
     38from cows import bbox_util 
    3439 
    3540class CSMLwmsLayerMapper(CSMLLayerMapper): 
     
    9196        for feature in csml.csmllibs.csmlextra.listify(ds.featureCollection.featureMembers): 
    9297            title, abstract, dimensions, units, crss=self.getInfo(feature) 
    93             layermap[feature.id]=CSMLwmsLayer(title,abstract, dimensions, units, crss, feature) 
     98            layermap[feature.id]=CSMLwmsLayer(title,abstract, dimensions, units, crss, feature, 
     99                                              name=feature.id) 
    94100        if len(layermap) > 0: 
    95101            self.layermapcache[fileoruri]=layermap 
     
    113119    """ 
    114120     
    115     def __init__(self, title, abstract, dimensions, units, crss, feature): 
     121    def __init__(self, title, abstract, dimensions, units, crss, feature, 
     122                 name=None): 
    116123        self.featureInfoFormats=None #NotImplemented 
    117124        self.title=title 
     125        self.name = name 
    118126        self.abstract=abstract 
    119127        self.dimensions=dimensions 
     
    154162        #raise NotImplementedError 
    155163         
    156     def getSlab(self, crs, dimValues=None, renderOpts={}): 
     164    def getSlab(self, crs, style, dimValues, transparent, bgcolor, renderOpts={}): 
    157165        """ 
    158166        Creates a slab of the layer in a particular CRS and set of 
     
    194202            raise NotImplementedError 
    195203         
    196     def getCacheKey(self, crs, dimValues=None, renderOpts={}): 
     204    def getCacheKey(self, crs, style, dimValues, transparent, bgcolor, renderOpts={}): 
    197205        """ 
    198206        Create a unique key for use in caching a slab. 
     
    400408        """ 
    401409 
    402         log.debug('getImage(%s, %s, %s)' % (bbox, width, height)) 
     410 
     411        lbbox = self.layer.getBBox(self.crs) 
     412        ibbox = bbox_util.intersection(bbox, lbbox) 
     413     
     414        log.debug('bbox = %s' % (bbox,)) 
     415        log.debug('lbbox = %s' % (lbbox,)) 
     416        log.debug('ibbox = %s' % (ibbox,)) 
     417     
     418        # If bbox is not within layerObj.bbox then we need to calculate the 
     419        # pixel offset of the inner bbox, request the right width/height 
     420        # and paste the image into a blank background 
     421        if bbox == ibbox: 
     422            img = self._renderImage(bbox, width, height) 
     423            log.debug('image.size = %s' % (img.size,)) 
     424                    
     425        else: 
     426            
     427            ix0, iy0 = bbox_util.geoToPixel(ibbox[0], ibbox[3], bbox, width, height, 
     428                                            roundUpY=True) 
     429            ix1, iy1 = bbox_util.geoToPixel(ibbox[2], ibbox[1], bbox, width, height, 
     430                                            roundUpX=True) 
     431            iw = ix1-ix0 
     432            ih = iy1-iy0 
     433            log.debug('Deduced inner image: %s, (%d x %d)' % ((ix0, iy0, ix1, iy1), iw, ih)) 
     434            img1 = self._renderImage(ibbox, iw, ih) 
     435 
     436            img = Image.new('RGBA', (width, height)) 
     437            img.paste(img1, (ix0, iy0)) 
     438                     
     439        return img 
     440 
     441 
     442    def _renderImage(self, bbox, width, height): 
     443        log.debug('_renderImage(%s, %s, %s)' % (bbox, width, height)) 
    403444         
    404445        cmap = cm.get_cmap(config['colourmap']) 
     
    422463        renderer=RGBARenderer(minval, maxval)          
    423464        return renderer.renderGrid(grid, bbox, width, height, cmap) 
     465     
    424466     
    425467class Grid(object): 
Note: See TracChangeset for help on using the changeset viewer.