Changeset 18832d1


Ignore:
Timestamp:
03/25/12 17:54:43 (2 years ago)
Author:
xkolman2 <xkolman2@…>
Branches:
master
Children:
9583153
Parents:
0b8050c2
git-author:
xkolman2 <xkolman2@…> (03/25/12 17:54:43)
git-committer:
xkolman2 <xkolman2@…> (03/25/12 17:54:43)
Message:

initial modRana tile processing support for the QML GUI

git-svn-id: https://nlp.fi.muni.cz/svn/gps_navigace/trunk@713 0858a4d0-ffff-46e5-938e-62b5ecb34222

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • data/default_configuration_files/map_config.conf

    r25f2707 r18832d1  
    2323[[mapnik]] 
    2424  label=OSM Mapnik 
    25   url=http://tile.openstreetmap.org/ 
     25  url=http://c.tile.openstreetmap.org/ 
    2626  type=png 
    2727  max_zoom=18 
  • modules/gui_modules/gui_qml/gui_qml.py

    rd3b35f3 r18832d1  
    2525import re 
    2626import os 
     27import traceback 
     28import cStringIO 
     29 
     30# PySide 
    2731from PySide import QtCore 
    2832from PySide.QtCore import * 
     
    8892    self.iconProvider = IconImageProvider() 
    8993    self.view.engine().addImageProvider("icons",self.iconProvider) 
     94    # add tiles provider 
     95    self.tilesProvider = TileImageProvider(self) 
     96    self.view.engine().addImageProvider("tiles",self.tilesProvider) 
     97 
    9098    rc = self.view.rootContext() 
    9199    # make options accessible from QML 
     
    99107    rc.setContextProperty("platform", platform) 
    100108 
     109    self.window.closeEvent = self._qtWindowClosed 
     110    #self.window.show() 
     111 
     112    self.rootObject = None 
     113 
     114    self._location = None # location module 
     115    self._mapTiles = None # map tiles module 
     116 
     117    self._notificationQueue = [] 
     118 
     119  def firstTime(self): 
     120    self._location = self.m.get('location', None) 
     121    self._mapTiles = self.m.get('mapTiles', None) 
     122 
     123  def getIDString(self): 
     124    return "QML" 
     125 
     126  def isFullscreen(self): 
     127    return self.window.isFullScreen() 
     128 
     129  def toggleFullscreen(self): 
     130    if self.window.isFullScreen(): 
     131      self.window.showNormal() 
     132    else: 
     133      self.window.showFullScreen() 
     134 
     135  def setFullscreen(self, value): 
     136    if value == True: 
     137      self.window.showFullScreen() 
     138    else: 
     139      self.window.showNormal() 
     140 
     141  def setCDDragThreshold(self, threshold): 
     142    """set the threshold which needs to be reached to disable centering while dragging 
     143    basically, larger threshold = longer drag is needed to disable centering 
     144    default value = 2048 
     145    """ 
     146    self.centeringDisableThreshold = threshold 
     147 
     148  def startMainLoop(self): 
     149    """start the main loop or its equivalent""" 
     150 
     151#    print "QML start main loop" 
     152 
     153    if self.modrana.dmod.startInFullscreen(): 
     154      self.toggleFullscreen() 
     155 
    101156    # Create an URL to the QML file 
    102157    url = QUrl('modules/gui_modules/gui_qml/qml/main.qml') 
    103158    # Set the QML file and show 
    104159    self.view.setSource(url) 
    105     self.window.closeEvent = self._qtWindowClosed 
     160    # get the root object 
     161    self.rootObject = self.view.rootObject() 
     162 
     163    # start main loop 
    106164    self.window.show() 
    107165 
    108     self.rootObject = self.view.rootObject() 
    109     if self.modrana.dmod.startInFullscreen(): 
    110       self.toggleFullscreen() 
    111  
    112     self._location = None # location module 
    113  
    114   def firstTime(self): 
    115     self._location = self.m.get('location', None) 
    116  
    117   def getIDString(self): 
    118     return "QML" 
    119  
    120   def isFullscreen(self): 
    121     return self.window.isFullScreen() 
    122  
    123   def toggleFullscreen(self): 
    124     if self.window.isFullScreen(): 
    125       self.window.showNormal() 
    126     else: 
    127       self.window.showFullScreen() 
    128  
    129   def setFullscreen(self, value): 
    130     if value == True: 
    131       self.window.showFullScreen() 
    132     else: 
    133       self.window.showNormal() 
    134  
    135   def setCDDragThreshold(self, threshold): 
    136     """set the threshold which needs to be reached to disable centering while dragging 
    137     basically, larger threshold = longer drag is needed to disable centering 
    138     default value = 2048 
    139     """ 
    140     self.centeringDisableThreshold = threshold 
    141  
    142   def startMainLoop(self): 
    143     """start the main loop or its equivalent""" 
    144  
    145 #    print "QML start main loop" 
    146  
    147     # start main loop 
     166    # handle any notifications that might have come before firstTime 
     167    # (the GUI is not available before firstTime) 
     168    if self._notificationQueue: 
     169      for item in self._notificationQueue: 
     170        self.notify(*item) 
     171 
    148172    self.app.exec_() 
    149173#    print "QML main loop started" 
    150174 
    151175  def _qtWindowClosed(self, event): 
    152     print('qt window closing down') 
     176    print('Qt window closing down') 
    153177    self.modrana.shutdown() 
    154178 
     
    175199    text = newlines2brs(text) 
    176200    print("QML GUI notify:\n message: %s, timeout: %d" % (text, msTimeout)) 
    177     self.rootObject.notify(text,msTimeout) 
     201    if self.rootObject: 
     202      self.rootObject.notify(text,msTimeout) 
     203    else: 
     204      self._notificationQueue.append((text, msTimeout, icon)) 
    178205 
    179206class Platform(QtCore.QObject): 
     
    245272      print iconPath 
    246273      print 'themes/%s' % (iconPath) 
     274 
     275class TileImageProvider(QDeclarativeImageProvider): 
     276  """ 
     277  the TileImageProvider class provides images images to the QML map element 
     278  """ 
     279  def __init__(self, gui): 
     280    QDeclarativeImageProvider.__init__(self, QDeclarativeImageProvider.ImageType.Image) 
     281    self.gui = gui 
     282 
     283  def requestImage(self, tileInfo, size, requestedSize): 
     284    """ 
     285    the tile info should look like this: 
     286    layerID/zl/x/y 
     287    """ 
     288    try: 
     289      # split tileInfo 
     290      (layer,z,x,y) = tileInfo.split("/") 
     291      print "LAYER" 
     292      print layer 
     293      z = int(z) 
     294      x = int(x) 
     295      y = int(y) 
     296      tileData = self.gui._mapTiles.getTile(layer, z, x, y) 
     297      # create a file-like object 
     298      f = cStringIO.StringIO(tileData) 
     299      # create image object 
     300      img=QImage() 
     301      # lod the image from in memory buffer 
     302      img.loadFromData(f.read()) 
     303      # cleanup 
     304      f.close() 
     305 
     306      return img 
     307      #return img.scaled(requestedSize) 
     308    except Exception, e: 
     309      print("QML GUI: icon image provider: loading tile failed", e) 
     310      print tileInfo 
     311      traceback.print_exc(file=sys.stdout) 
     312 
     313 
    247314 
    248315# from AGTL 
  • modules/gui_modules/gui_qml/qml/PinchMap.qml

    r4eb262d r18832d1  
    3737    property alias angle: rot.angle 
    3838 
     39    property string layer: "mapnik" 
    3940    //property string url: settings.currentMapType.url 
    40     property string url: "http://a.tile.openstreetmap.org/%(zoom)d/%(x)d/%(y)d.png" 
     41    //property string url: "http://a.tile.openstreetmap.org/%(zoom)d/%(x)d/%(y)d.png" 
     42    //property string url: "http://a.tile.openstreetmap.org/%(zoom)d/%(x)d/%(y)d.png" 
    4143 
    4244    property int earthRadius: 6371000 
     
    201203        return [x, y] 
    202204    } 
     205 
    203206    function getMappointFromCoord(lat, lon) { 
    204207        var tile = deg2num(lat, lon) 
     
    206209        var realY = (tile[1] - cornerTileY) * tileSize 
    207210        return [realX, realY] 
    208          
    209     } 
    210  
     211    } 
    211212 
    212213    function getCenter() { 
     
    230231            return "image://icons/"+ rWin.theme +"/noimage.png" 
    231232        } else { 
    232             var x = F.getMapTile(url, tx, ty, zoomLevel); 
    233             return x 
     233            //var x = F.getMapTile(url, tx, ty, zoomLevel); 
     234            return "image://tiles/"+layer+"/"+zoomLevel+"/"+tx+"/"+ty 
    234235        } 
    235236    } 
     
    290291                    anchors.fill: parent; 
    291292                    onProgressChanged: { progressBar.p = progress } 
     293                    asynchronous: true 
    292294                    source: tileUrl(tileX, tileY); 
     295 
    293296                } 
    294297 
  • modules/mod_mapTiles.py

    r03de6ba r18832d1  
    2020#--------------------------------------------------------------------------- 
    2121from __future__ import with_statement # for python 2.5 
     22import urllib 
    2223from base_module import ranaModule 
    2324from threading import Thread 
     
    2627import traceback 
    2728import urllib2 
     29import urllib3 
     30#import urllib3_old_fixed as urllib3 
    2831import time 
    2932import modrana_utils 
     
    3336 
    3437import socket 
    35 timeout = 30 # this sets timeout for all sockets 
    36 socket.setdefaulttimeout(timeout) 
     38#timeout = 30 # this sets timeout for all sockets 
     39#socket.setdefaulttimeout(timeout) 
    3740 
    3841# only import GKT libs if GTK GUI is used 
     
    108111    print "mapTiles: map folder path: %s" % self.mapFolderPath 
    109112 
     113    self._storeTiles = None 
     114 
     115    url = "http://c.tile.openstreetmap.org/" 
     116    #self.httpPool = urllib3.PoolManager() 
     117    self.httpPool = urllib3.connection_from_url(url = url, maxsize=4, timeout=3, block=False) 
     118 
     119 
    110120  def firstTime(self): 
    111121    self.mapViewModule = self.m.get('mapView', None) 
     
    114124    self.modrana.watch('mapScale', self._updateScalingCB) 
    115125    self.modrana.watch('z', self._updateScalingCB) 
    116  
    117   def getTile(self, layerID, z, x, y): 
     126    self._storeTiles = self.m.get('storeTiles', None) # get the tile storage module 
     127 
     128  def getTile(self, layer, z, x, y): 
    118129    """ 
    119130    return a tile specified by layerID, z, x & y 
     
    121132    * if not, download it 
    122133    """ 
    123  
    124     pass 
     134    layerInfo = self.mapLayers.get(layer, None) 
     135    if(layerInfo == None): # is the layer info valid ? 
     136      print("mapTiles: invalid layer") 
     137      return None 
     138    layerPrefix = layerInfo.get('folderPrefix','OpenStreetMap II') 
     139    layerType = layerInfo.get('type','png') 
     140 
     141    tileData = self._storeTiles.getTileData(layerPrefix, z, x, y, layerType) 
     142    if tileData: 
     143      print "loaded FROM CACHE" 
     144      # tile was available from storage 
     145      return tileData 
     146 
     147    # tile not available from storage, we need to download it 
     148    url = self.getTileUrl(x,y,z,layer) 
     149    print "DOWNLOAD" 
     150    print url 
     151    #request = urllib.urlopen(url) 
     152    request = self.httpPool.get_url(url) 
     153#    request = self.httpPool.urlopen("GET", "%d/%d/%d.png" % (z, x, y)) 
     154    tileData = request.data 
     155    #request.close() 
     156    print "DOWNLOAD DONE" 
     157    # check if the data is an image or an error page 
     158    if modrana_utils.isTheStringAnImage(tileData): 
     159      # store 
     160      tileFolder = self.modrana.paths.getMapFolderPath() 
     161      filePath = tileFolder + self.getImagePath(x, y, z, layerPrefix, layerType) 
     162      self._storeTiles.automaticStoreTile(tileData, layerPrefix, z, x, y, layerType, filePath) 
     163      print "STORED" 
     164      # return 
     165      return tileData 
     166    else: 
     167      print("mapTiles: downloaded tile is not an image (error page?)") 
     168      return None 
    125169 
    126170  def _updateScalingCB(self, key='mapScale', oldValue=1, newValue=1): 
     
    335379        ratio = self.get('transpRatio', "0.5,1").split(',') # get the transparency ratio 
    336380        (alphaOver, alphaBack) = (float(ratio[0]),float(ratio[1])) # convert it to floats 
    337         layer1 = self.get('layer','osma') 
    338         layer2 = self.get('layer2', 'mapnik') 
     381        layer1 = self.get('layer','mapnik') 
     382        layer2 = self.get('layer2', 'cycle') 
    339383        layerInfo = ((layer1, alphaBack),(layer2, alphaOver)) 
    340384        getName = self.getCompositeTileName 
    341385      else: 
    342         layerInfo = self.get('layer','osma') 
     386        layerInfo = self.get('layer','mapnik') 
    343387        getName = self.getTileName 
    344388 
     
    667711    layerInfo = self.mapLayers.get(layer, None) 
    668712    if(layerInfo == None): # is the layer info valid 
    669       sprint("invalid layer") 
    670713      return('NOK') 
    671714 
     
    673716    layerType = layerInfo.get('type','png') 
    674717 
    675     storeTiles = self.m.get('storeTiles', None) # get the tile storage module 
    676     if storeTiles: 
    677       start1 = time.clock() 
    678       pixbuf = storeTiles.getTile(layerPrefix, z, x, y, layerType) 
    679       """None from getTiles means the tile was not found 
    680          False means loading the tile from file to pixbuf failed""" 
    681       if pixbuf: 
    682         start2 = time.clock() 
    683         self.storeInMemmory(self.pixbufToCairoImageSurface(pixbuf), name) 
    684         if debug: 
    685           storageType = self.get('tileStorageType', 'files') 
    686           sprint("tile loaded from local storage (%s) in %1.2f ms" % (storageType,(1000 * (time.clock() - start1)))) 
    687           sprint("tile cached in memory in %1.2f ms" % (1000 * (time.clock() - start2))) 
    688         return('OK') 
     718    start1 = time.clock() 
     719    pixbuf = self._storeTiles.getTile(layerPrefix, z, x, y, layerType) 
     720    """None from getTiles means the tile was not found 
     721       False means loading the tile from file to pixbuf failed""" 
     722    if pixbuf: 
     723      start2 = time.clock() 
     724      self.storeInMemmory(self.pixbufToCairoImageSurface(pixbuf), name) 
     725      if debug: 
     726        storageType = self.get('tileStorageType', 'files') 
     727        sprint("tile loaded from local storage (%s) in %1.2f ms" % (storageType,(1000 * (time.clock() - start1)))) 
     728        sprint("tile cached in memory in %1.2f ms" % (1000 * (time.clock() - start2))) 
     729      return('OK') 
    689730 
    690731    # Image not found anywhere locally - resort to downloading it 
  • modules/mod_storeTiles.py

    r9680041 r18832d1  
    1 from ScrolledText import example 
    21from __future__ import with_statement # for python 2.5 
    32#!/usr/bin/python 
     
    6867    self.lookupConnectionLock = threading.RLock() 
    6968 
     69    self._mapTiles = None 
     70 
    7071  def firstTime(self): 
    7172    # the config folder should set the tile folder path by now 
     
    7374    # testing: 
    7475    #self.test() 
     76    self._mapTiles = self.m.get('mapTiles', None) 
    7577 
    7678  def getLayerDbFolderPath(self, folderPrefix): 
     
    274276    return os.path.join(folder, storeName) 
    275277 
     278 
    276279  def getTile(self, folderPrefix, z, x, y, extension): 
    277     """get a tile""" 
     280    """ 
     281    return a Pixbuf for the corresponding tile 
     282    """ 
     283    tileData = self.getTileData(folderPrefix, z, x, y, extension) 
     284    if tileData: 
     285      try: 
     286        pl = gtk.gdk.PixbufLoader() 
     287        pl.write(tileData) 
     288        pl.close() 
     289        pixbuf = pl.get_pixbuf() 
     290        return pixbuf # return pixbuf containing the tile image 
     291      except Exception, e: 
     292        print("storeTiles: loading tile image to pixbuf failed") 
     293        print(e) 
     294        return None 
     295    else: 
     296      # tile not found 
     297      return None 
     298 
     299 
     300  def getTileData(self, folderPrefix, z, x, y, extension): 
     301    """ 
     302    return data for the given tile 
     303    """ 
    278304    storageType = self.get('tileStorageType', 'files') 
    279305    if storageType == 'sqlite': 
     
    284310        result = self.getTileFromDb(lookupConn, dbFolderPath, z, x, y, extension) 
    285311        if result: # is the result valid ? 
    286           resultContent = result.fetchone() # get the result content 
     312          resultData = result.fetchone() # get the result content 
    287313        else: 
    288           resultContent = None # the result is invalid 
    289         if resultContent: 
    290           # convert the buffer to pixbuf 
    291           try: 
    292             pl = gtk.gdk.PixbufLoader() 
    293             pl.write(resultContent[0]) 
    294             pl.close() 
    295             pixbuf = pl.get_pixbuf() 
    296             return pixbuf # return pixbuf containing the tile image 
    297           except Exception, e: 
    298             print "loading the image buffer from sqlite to pixbuf failed:%s" % e 
     314          resultData = None # the result is invalid 
     315        if resultData: 
     316          # return tile data 
     317          return resultData[0] 
    299318        else: 
    300319          return None # the tile is not stored 
    301320    else: # the only other storage method is currently classical files storage 
    302       mapTiles = self.m.get('mapTiles', None) 
    303       if mapTiles: 
    304         tileFolderPath = mapTiles._getTileFolderPath() 
    305         layerFolderAndTileFilename = mapTiles.getImagePath(x,y,z,folderPrefix, extension) 
    306         tilePath = os.path.join(tileFolderPath, layerFolderAndTileFilename) 
    307         if os.path.exists(tilePath): 
    308           # load the file to pixbuf and return it 
    309           return mapTiles.filePath2Pixbuf(tilePath) 
    310         else: 
    311           return None # this tile is not locally stored 
     321      tileFolderPath = self._mapTiles._getTileFolderPath() 
     322      layerFolderAndTileFilename = self._mapTiles.getImagePath(x,y,z,folderPrefix, extension) 
     323      tilePath = os.path.join(tileFolderPath, layerFolderAndTileFilename) 
     324      if os.path.exists(tilePath): 
     325        # load the file to pixbuf and return it 
     326        try: 
     327          f = open(tilePath, "r") 
     328          data = f.read() 
     329          f.close() 
     330          return data 
     331        except Exception, e: 
     332          print("storeTiles: loading tile from file failed") 
     333          print(e) 
     334          return None 
     335      else: 
     336        return None # this tile is not locally stored 
    312337 
    313338  def getTileFromDb(self, lookupConn, dbFolderPath, z, x, y, extension): 
     
    315340    accessType = "get" 
    316341    #look in the lookup db 
    317     with self.lookupConnectionLock: 
     342    #with self.lookupConnectionLock: 
     343    if 1: 
    318344      """ just to make sure the access is sequential 
    319345      (due to sqlite in python 2.5 probably not liking concurrent access, 
     
    400426           would wait forever for the queue to empty 
    401427        """ 
     428        #TODO: defensive programming - check if thread is alive when storing ? 
    402429        try: 
    403430          (tile, folderPrefix, z, x, y, extension, filename) = item # unpack the tuple 
     
    437464 
    438465  def shutdown(self): 
     466    # try to commit possibly uncommitted tiles 
     467    self.sqliteTileQueue.put('shutdown',True) 
     468 
     469 
     470## TESTING CODE 
    439471#    accessType = "get" 
    440472#    folderPrefix = 'OpenStreetMap I' 
     
    468500#    print "connection reuse %f ms" % (1000 * (time.clock() - start)) 
    469501 
    470  
    471     self.sqliteTileQueue.put('shutdown',True) # try to commit possible uncommitted tiles 
    472  
    473502if(__name__ == "__main__"): 
    474503  a = example({}, {}) 
Note: See TracChangeset for help on using the changeset viewer.