Changeset 5493


Ignore:
Timestamp:
17/07/09 13:00:03 (10 years ago)
Author:
pnorton
Message:

Implemented the changes made while working on the qesdi wms. Also changed the csmlbackend wms so that it works with the new WMSContoller.

Location:
cows/branches/cows_qesdi/cows
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • cows/branches/cows_qesdi/cows/pylons/templates/wms_capabilities_1_3_0.xml

    r4910 r5493  
    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    <py:def function="markupLegendURL(l)"> 
     42      <LegendURL width="${l.width}" height="${l.height}"> 
     43         <Format>${l.format}</Format> 
     44         <OnlineResource xlink:type="simple" xlink:href="${l.onlineResource.href}"/> 
     45      </LegendURL> 
     46    </py:def> 
     47 
     48 
     49    <py:def function="markupStyle(s)"> 
     50      <Style> 
     51        <Name>${s.name}</Name> 
     52        <Title>${s.title}</Title> 
     53        <py:for each="l in s.legendURLs" py:if="getattr(s, 'legendURLs', None) != None"> 
     54          ${markupLegendURL(l)} 
     55        </py:for> 
     56      </Style> 
     57    </py:def> 
    3958 
    4059  <Layer py:def="markupLayer(ds)" queryable="${int(ds.queryable)}"> 
     
    5372    <py:for each="bb in ds.boundingBoxes"> 
    5473      <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]}"/> 
     74           minx="${'%.2f'%bb.lowerCorner[0]}" 
     75           miny="${'%.2f'%bb.lowerCorner[1]}" 
     76           maxx="${'%.2f'%bb.upperCorner[0]}" 
     77           maxy="${'%.2f'%bb.upperCorner[1]}"/> 
    5978    </py:for> 
    6079 
     
    7190 
    7291    <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)"/> 
     92           name="${d_n}" units="${d.valuesUnit}" 
     93           unitSymbol="${d.unitSymbol}" 
     94           default="${d.defaultValue}"  
     95           py:content="','.join(d.possibleValues.allowedValues)"/> 
    7796<!--! 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> 
     97 
     98     
     99     
     100    <py:choose test="ds.styles"> 
     101 
     102        <py:when test="['']"> 
     103            <Style> 
     104                <Name>default</Name> 
     105                <Title>Default</Title> 
     106                <LegendURL width="${ds.legendSize[0]}" height="${ds.legendSize[1]}"> 
     107                    <Format py:for="f in ds.legendFormats" py:content="f"/> 
     108                    <OnlineResource xlink:type="simple" xlink:href="${url_for(qualified=True, action='index')}?request=GetLegend&amp;layers=${ds.identifier}"/> 
     109                </LegendURL> 
     110            </Style> 
     111        </py:when> 
     112 
     113        <py:otherwise> 
     114            <py:for each="s in ds.styles" py:if="getattr(ds, 'styles', None) != None"> 
     115                ${markupStyle(s)} 
     116            </py:for> 
     117        </py:otherwise> 
     118 
     119    </py:choose> 
    86120 
    87121 
     
    97131    <KeywordList> 
    98132      <Keyword py:for="kw in si.keywords" 
    99                py:content="kw"/> 
     133           py:content="kw"/> 
    100134    </KeywordList> 
    101135    <OnlineResource xlink:type="simple" xlink:href="${url_for(qualified=True, action='index')}?"/> 
    102136     
    103137    <ContactInformation py:if="sm.serviceProvider is not None" 
    104                         py:with="rp=sm.serviceProvider.serviceContact"> 
     138            py:with="rp=sm.serviceProvider.serviceContact"> 
    105139      <ContactPersonPrimary> 
    106         <ContactPerson py:if="rp is not None" py:content="rp.individualName"/> 
    107         <ContactOrganization py:content="sm.serviceProvider.providerName"/> 
     140    <ContactPerson py:if="rp is not None" py:content="rp.individualName"/> 
     141    <ContactOrganization py:content="sm.serviceProvider.providerName"/> 
    108142      </ContactPersonPrimary> 
    109143      <ContactPosition py:content="rp.positionName"/> 
    110144 
    111145      <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"/> 
     146    <ContactAddress py:if="cn.address is not None"> 
     147      <AddressType>postal</AddressType> 
     148      <Address> 
     149        <py:for each="d in cn.address.deliveryPoints">${d}</py:for> 
     150      </Address> 
     151      <City py:content="cn.address.city"/> 
     152      <StateOrProvince py:content="cn.address.administrativeArea"/> 
     153      <PostCode py:content="cn.address.postalCode"/> 
     154      <Country py:content="cn.address.country"/> 
     155    </ContactAddress> 
     156    <ContactVoiceTelephone py:if="cn.phone is not None" 
     157                   py:content="cn.phone.voice"/> 
     158    <ContactFacsimileTelephone py:if="cn.phone is not None" 
     159                   py:content="cn.phone.facsimile"/> 
     160    <ContactElectronicMailAddress py:if="cn.address is not None" 
     161                      py:content="cn.address.electronicMailAddress"/> 
    128162      </py:with> 
    129163    </ContactInformation> 
     
    142176    <py:if test="om is not None"> 
    143177      <?python 
    144         ops = ['GetCapabilities', 'GetMap', 'GetFeatureInfo'] 
    145         eops = [x for x in om.operationDict.keys() if x not in ops] 
     178    ops = ['GetCapabilities', 'GetMap', 'GetFeatureInfo'] 
     179    eops = [x for x in om.operationDict.keys() if x not in ops] 
    146180      ?> 
    147181      <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> 
     182    <py:for each="opName in ops" py:if="opName in om.operationDict.keys()"> 
     183      <span py:content="markupOperation(opName, om.operationDict[opName])" py:strip="True"/> 
     184    </py:for> 
     185    <py:for each="opName in ops" py:if="opName in om.operationDict.keys()"> 
     186      <?python exceptions = om.operationDict[opName].parameters.get('ExceptionFormat') ?> 
     187      <Exception py:if="exceptions is not None"> 
     188        <Format py:for="e in exceptions.possibleValues.allowedValues" 
     189            py:content="e"/> 
     190      </Exception> 
     191    </py:for> 
    158192      </Request> 
    159193 
     
    163197      <_ExtendedCapabilities> 
    164198      <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> 
     199    <py:for each="opName in eops"> 
     200      <span py:content="markupOperation(opName, om.operationDict[opName])" py:strip="True"/> 
     201    </py:for> 
     202    <py:for each="opName in eops"> 
     203      <?python exceptions = om.operationDict[opName].parameters.get('ExceptionFormat') ?> 
     204      <Exception py:if="exceptions is not None"> 
     205        <Format py:for="e in exceptions.possibleValues.allowedValues" 
     206            py:content="e"/> 
     207      </Exception> 
     208    </py:for> 
    175209      </Request> 
    176210      </_ExtendedCapabilities> 
     
    180214      <Title>Contents</Title> 
    181215      <Layer py:for="ds in sm.contents.datasetSummaries" 
    182              py:replace="markupLayer(ds)"> 
     216         py:replace="markupLayer(ds)"> 
    183217      </Layer> 
    184218    </Layer> 
  • cows/branches/cows_qesdi/cows/pylons/wms_controller.py

    r5424 r5493  
    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            if hasattr(layer, 'styles'): 
     156                styles = layer.styles 
     157            else: 
     158                styles = [''] 
     159                 
    153160            # Create the cows object 
    154161            ds = WmsDatasetSummary(identifier=layerName, 
     
    160167                                   dimensions=dims, 
    161168                                   queryable=queryable, 
    162                                    dataURLs=dataURLs) 
     169                                   dataURLs=dataURLs, 
     170                                   styles=styles) 
    163171 
    164172            # Stuff that should go in the capabilities tree eventually 
     
    208216        layers = {} 
    209217        layerNames = self.getOwsParam(paramName) 
    210  
     218         
    211219        # Select the first layer if several are requested. 
    212220        # This plays nicer with mapClient. 
    213         #if ',' in layerName: 
    214221        layerNames = layerNames.split(',') 
    215             #raise InvalidParameterValue( 
    216             #    'Multi-layer GetMap requests are not supported', 'layers') 
     222         
     223        layerObjects = [] 
     224         
    217225        for layerName in layerNames: 
    218226            try: 
    219227                layerObj = self.layers[layerName] 
    220                 layers[layerName] = layerObj 
     228                layerObjects.append(layerObj) 
    221229            except KeyError: 
    222230                raise InvalidParameterValue('Layer %s not found' % layerName, 
    223231                                        paramName) 
    224232 
    225         #return layerName, layerObj 
    226         return layers 
     233        return layerObjects 
    227234 
    228235    def _getFormatParam(self): 
     
    278285 
    279286 
    280     def _retrieveSlab(self, layerObj, srs, dimValues, renderOpts): 
     287    def _retrieveSlab(self, layerObj, srs, style, dimValues, transparent, bgcolor, additionalParams): 
     288         
    281289        # Find the slab in the cache first 
    282         cacheKey = layerObj.getCacheKey(srs, dimValues) 
     290        cacheKey = layerObj.getCacheKey(srs, style, dimValues, transparent, bgcolor, additionalParams) 
    283291        slab = self._layerSlabCache.get(cacheKey) 
     292         
    284293        if slab is None: 
    285             slab = layerObj.getSlab(srs, dimValues, renderOpts) 
     294             
     295            slab = layerObj.getSlab(srs, style, dimValues, transparent, bgcolor, additionalParams) 
     296             
    286297            if cacheKey is not None: 
    287298                self._layerSlabCache[cacheKey] = slab 
     
    294305    def GetMap(self): 
    295306 
    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  
     307        # Get the parameters 
     308        version      = self._getVersionParam() 
     309        format       = self._getFormatParam()         
     310        transparent  = self._getTransparentParam() 
     311        bgcolor      = self._getBgcolorParam() 
     312        bbox         = self._getBboxParam() 
     313        width        = self._getWidthParam() 
     314        height       = self._getHeightParam() 
     315         
     316        layerObjects = self._getLayerParam() 
     317         
     318        styles       = self._getStylesParam(len(layerObjects)) 
     319        srs          = self._getSrsParam(version) 
     320         
     321        log.debug("layerNames = %s" % ([o.name for o in layerObjects],)) 
     322         
    328323        finalImg = Image.new('RGBA', (width, height), (0,0,0,0)) 
    329          
     324 
    330325        # Multiple Layers handling..   
    331         for layerName, layerObj in layers.iteritems(): 
     326        for i in range(len(layerObjects)): 
     327            layerObj = layerObjects[i] 
     328             
     329            #if no styles provided, set style = ""             
     330            if styles == "": 
     331                style = "" 
     332            else: 
     333                style = styles[i] 
     334             
    332335            if srs not in layerObj.crss: 
    333                 raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerName, srs)) 
     336                raise InvalidParameterValue('Layer %s does not support SRS %s' % (layerObj.name, srs)) 
    334337 
    335338            dimValues = self._getDimValues(layerObj) 
     
    340343                restoredDim=self._mapParamToDim(dim) 
    341344                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          
     345             
     346            expectedParams = [] 
     347            expectedParams.extend(self._escapedDimNames) 
     348            expectedParams.extend(layerObj.dimensions.keys()) 
     349             
     350            #get any other parameters on the request that the layer might need 
     351            additionalParams = self._getAdditionalParameters(expectedParams) 
     352             
     353            slab = self._retrieveSlab(layerObj, srs, style, dimValues,  
     354                                      transparent, bgcolor, additionalParams) 
     355 
     356            img = slab.getImage(bbox, width, height) 
     357             
     358            finalImg = Image.composite(finalImg, img, finalImg)     
     359 
    384360        # IE < 7 doesn't display the alpha layer right.  Here we sniff the 
    385361        # user agent and remove the alpha layer if necessary. 
     
    392368                finalImg = finalImg.convert('RGB') 
    393369 
    394         buf = StringIO() 
    395         finalImg.save(buf, self._pilImageFormats[format]) 
    396  
    397         response.headers['Content-Type'] = format 
    398         response.write(buf.getvalue()) 
     370        self._writeImageResponse(finalImg, format) 
    399371 
    400372 
     
    507479        format = self._getFormatParam() 
    508480 
    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()) 
     481        # This hook alows extra arguments to be passed to the layer backend. 
     482        additionalParams = self._getAdditionalParameters(['format']) 
     483         
     484        img = layerObj.getLegendImage(renderOpts=additionalParams) 
     485         
     486        self._writeImageResponse(img, format) 
     487 
    520488 
    521489 
     
    528496 
    529497             
     498    def _getAdditionalParameters(self, expectedParams): 
     499         
     500        additionalParams = {} 
     501         
     502        for paramName, paramValue in self._owsParams.items(): 
     503             
     504            paramName = paramName.lower() 
     505                         
     506            #ignore any of the expected parameters 
     507            if paramName in [p.lower() for p in expectedParams]: 
     508                continue 
     509             
     510            additionalParams[paramName] = paramValue 
     511             
     512        return additionalParams 
     513     
     514    def _getStylesParam(self, numLayers): 
     515        styles = self.getOwsParam('styles', default="") 
     516         
     517        if styles != "": 
     518            styles = styles.split(',') 
     519             
     520            assert len(styles) == numLayers, \ 
     521               "Number of styles %s didn't match the number of layers %s" % ( len(styles), numLayers) 
     522 
     523        return styles 
     524 
     525    def _getTransparentParam(self): 
     526        transparent = self.getOwsParam('transparent', default='FALSE') 
     527        return transparent.lower() == 'true' 
     528     
     529    def _getBgcolorParam(self): 
     530        return self.getOwsParam('bgcolor', default='0xFFFFFF') 
     531 
     532    def _getVersionParam(self): 
     533        version = self.getOwsParam('version', default=self.validVersions[0]) 
     534         
     535        if version not in self.validVersions: 
     536            raise InvalidParameterValue('Version %s not supported' % version, 'version') 
     537         
     538        return version 
     539 
     540    def _getSrsParam(self, version): 
     541        if version == '1.1.1': 
     542            srs = self.getOwsParam('srs') 
     543        else: 
     544            srs = self.getOwsParam('crs') 
     545             
     546        return srs 
     547 
     548    def _getBboxParam(self): 
     549        bbox = tuple(float(x) for x in self.getOwsParam('bbox').split(',')) 
     550        return bbox 
     551     
     552    def _getWidthParam(self): 
     553        return int(self.getOwsParam('width')) 
     554     
     555    def _getHeightParam(self): 
     556        return int(self.getOwsParam('height')) 
     557     
     558 
     559    def _writeImageResponse(self, pilImage, format): 
     560         
     561        buf = StringIO() 
     562        pilImage.save(buf, self._pilImageFormats[format]) 
     563 
     564        response.headers['Content-Type'] = format 
     565        response.write(buf.getvalue())     
  • cows/branches/cows_qesdi/cows/service/imps/csmlbackend/wms_csmllayer.py

    r5399 r5493  
    3131from cows.service.wms_iface import IwmsLayer, IwmsDimension, IwmsLayerSlab 
    3232from cows.service.imps.csmlbackend.csmlcommon import CSMLLayerMapper, CSMLConnector 
    33  
     33from cows import bbox_util 
    3434 
    3535class CSMLwmsLayerMapper(CSMLLayerMapper): 
     
    9191        for feature in csml.csmllibs.csmlextra.listify(ds.featureCollection.featureMembers): 
    9292            title, abstract, dimensions, units, crss=self.getInfo(feature) 
    93             layermap[feature.id]=CSMLwmsLayer(title,abstract, dimensions, units, crss, feature) 
     93            layermap[feature.id]=CSMLwmsLayer(title,abstract, dimensions, units, crss, feature, 
     94                                              name=feature.id) 
    9495        if len(layermap) > 0: 
    9596            self.layermapcache[fileoruri]=layermap 
     
    113114    """ 
    114115     
    115     def __init__(self, title, abstract, dimensions, units, crss, feature): 
     116    def __init__(self, title, abstract, dimensions, units, crss, feature, 
     117                 name=None): 
    116118        self.featureInfoFormats=None #NotImplemented 
    117119        self.title=title 
     120        self.name = name 
    118121        self.abstract=abstract 
    119122        self.dimensions=dimensions 
     
    154157        #raise NotImplementedError 
    155158         
    156     def getSlab(self, crs, dimValues=None, renderOpts={}): 
     159    def getSlab(self, crs, style, dimValues, transparent, bgcolor, renderOpts={}): 
    157160        """ 
    158161        Creates a slab of the layer in a particular CRS and set of 
     
    194197            raise NotImplementedError 
    195198         
    196     def getCacheKey(self, crs, dimValues=None, renderOpts={}): 
     199    def getCacheKey(self, crs, style, dimValues, transparent, bgcolor, renderOpts={}): 
    197200        """ 
    198201        Create a unique key for use in caching a slab. 
     
    400403        """ 
    401404 
    402         log.debug('getImage(%s, %s, %s)' % (bbox, width, height)) 
     405 
     406        lbbox = self.layer.getBBox(self.crs) 
     407        ibbox = bbox_util.intersection(bbox, lbbox) 
     408     
     409        log.debug('bbox = %s' % (bbox,)) 
     410        log.debug('lbbox = %s' % (lbbox,)) 
     411        log.debug('ibbox = %s' % (ibbox,)) 
     412     
     413        # If bbox is not within layerObj.bbox then we need to calculate the 
     414        # pixel offset of the inner bbox, request the right width/height 
     415        # and paste the image into a blank background 
     416        if bbox == ibbox: 
     417            img = self._renderImage(bbox, width, height) 
     418            log.debug('image.size = %s' % (img.size,)) 
     419                    
     420        else: 
     421            
     422            ix0, iy0 = bbox_util.geoToPixel(ibbox[0], ibbox[3], bbox, width, height, 
     423                                            roundUpY=True) 
     424            ix1, iy1 = bbox_util.geoToPixel(ibbox[2], ibbox[1], bbox, width, height, 
     425                                            roundUpX=True) 
     426            iw = ix1-ix0 
     427            ih = iy1-iy0 
     428            log.debug('Deduced inner image: %s, (%d x %d)' % ((ix0, iy0, ix1, iy1), iw, ih)) 
     429            img1 = self._renderImage(ibbox, iw, ih) 
     430 
     431            img = Image.new('RGBA', (width, height)) 
     432            img.paste(img1, (ix0, iy0)) 
     433                     
     434        return img 
     435 
     436 
     437    def _renderImage(self, bbox, width, height): 
     438        log.debug('_renderImage(%s, %s, %s)' % (bbox, width, height)) 
    403439         
    404440        cmap = cm.get_cmap(config['colourmap']) 
     
    413449        renderer=RGBARenderer(minval, maxval)          
    414450        return renderer.renderGrid(grid, bbox, width, height, cmap) 
     451     
    415452     
    416453class Grid(object): 
Note: See TracChangeset for help on using the changeset viewer.