source: subversion/applications/routing/pyroute-dev/tiles.py @ 34690

Last change on this file since 34690 was 18456, checked in by buerste, 10 years ago

-reodering imports

  • Property svn:keywords set to Rev
File size: 4.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4"""Tile image handler (download, cache, and display tiles)
5
6Usage:
7        (library code for pyroute GUI, not for direct use)
8"""
9
10__version__ = "$Rev: 18456 $"[1:-2]
11__license__ = """This program is free software: you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation, either version 3 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program. If not, see <http://www.gnu.org/licenses/>."""
23_debug = 0
24
25
26from base import pyrouteModule
27from threading import Thread
28from tilenames import *
29import cairo
30import os
31import urllib
32
33def downloadTile(x,y,z,layer,filename):
34        url = tileURL(x,y,z,layer)
35        if(tileLayerExt(layer) != "png"):
36                base,ext = os.path.splitext(filename)
37                tempFilename = "%s.%s" % (base, tileLayerExt(layer))
38                urllib.urlretrieve(url, tempFilename)
39                sys = "convert %s %s" % (tempFilename, filename)
40                print "Running \"%s\"" % sys
41                os.system(sys)
42                os.unlink(tempFilename)
43        else:
44                urllib.urlretrieve(url, filename)
45
46class tileLoader(Thread):
47        """Downloads images in a separate thread"""
48        def __init__(self, x,y,z,layer,filename):
49                """Download a tile image"""
50                self.x = x
51                self.y = y
52                self.z = z
53                self.layer = layer
54                self.finished = 0
55                self.filename = filename
56                Thread.__init__(self)
57
58        def run(self):
59                downloadTile( \
60                        self.x,
61                        self.y,
62                        self.z,
63                        self.layer,
64                        self.filename)
65
66                self.finished = 1
67
68class tileHandler(pyrouteModule):
69        """Loads and displays map tiles"""
70        def __init__(self, modules):
71                pyrouteModule.__init__(self, modules)
72                self.images = {}
73                self.threads = {}
74                self.downloadInThread = False
75
76        def __del__(self):
77                print "Shutting-down tiles"
78                for name,thread in self.threads.items():
79                        pass
80        def imageName(self,x,y,z,layer):
81                """Get a unique name for a tile image
82                (suitable for use as part of filenames, dictionary keys, etc)"""
83                return("%s_%d_%d_%d" % (layer,z,x,y))
84
85        def loadImage(self,x,y,z, layer):
86                """Check that an image is loaded, and try to load it if not"""
87
88                # First: is the image already in memory?
89                name = self.imageName(x,y,z,layer)
90                if name in self.images.keys():
91                        return
92
93                # Second, is it already in the process of being downloaded?
94                if name in self.threads.keys():
95                        if(not self.threads[name].finished):
96                                return
97
98                # Third, is it in the disk cache? (including ones recently-downloaded)
99                filename = os.path.join(os.path.dirname(__file__), "cache", "%s.png" % name)
100                if os.path.exists(filename):
101                        self.images[name] = cairo.ImageSurface.create_from_png(filename)
102                        return
103
104                # Image not found anywhere - resort to downloading it
105                print "Downloading %s" % (name)
106                if(self.downloadInThread):
107                        self.threads[name] = tileLoader(x,y,z,layer,filename)
108                        self.threads[name].start()
109                else:
110                        downloadTile(x,y,z,layer,filename)
111                self.set("needRedraw", True)
112
113        def drawImage(self,cr, tile, bbox):
114                """Draw a tile image"""
115                name = self.imageName(tile[0],tile[1],tile[2], tile[3])
116                # If it's not in memory, then stop here
117                if not name in self.images.keys():
118                        return
119                # Move the cairo projection onto the area where we want to draw the image
120                cr.save()
121                cr.translate(bbox[0],bbox[1])
122
123                #cr.scale((bbox[2] - bbox[0]) / 256.0, (bbox[3] - bbox[1]) / 256.0)
124
125                # Display the image
126                cr.set_source_surface(self.images[name],0,0)
127                cr.paint()
128
129                # Return the cairo projection to what it was
130                cr.restore()
131
132        def draw(self, cr):
133                """Draw all the map tiles that are in view"""
134                proj = self.m['projection']
135                layer = self.get("layer","tah")
136
137                if(not proj.isValid()):
138                        return;
139                # Pick a zoom level
140                z = proj.zoom
141
142                # Loop through all tiles
143                for x in range(int(floor(proj.px1)), int(ceil(proj.px2))):
144                        for y in range(int(floor(proj.py1)), int(ceil(proj.py2))):
145
146
147                                if(1):
148                                        # Find the edges of the tile as lat/long
149                                        #S,W,N,E = tileEdges(x,y,z)
150
151                                        # Convert those edges to screen coordinates
152                                        x1,y1 = proj.pxpy2xy(x,y)
153                                        x2,y2 = proj.pxpy2xy(x+1,y+1)
154
155                                        #print "%d,%d,%d -> %1.1f-%1.1f"%(x,y,z,x1,x2)
156
157                                        # Check that the image is available in the memory cache
158                                        # and start downloading it if it's not
159                                        self.loadImage(x,y,z,layer)
160
161                                        # Draw the image
162                                        self.drawImage(cr,(x,y,z,layer),(x1,y1,x2,y2))
Note: See TracBrowser for help on using the repository browser.