source: modules/_mod_vmap.py @ b52de6d

Last change on this file since b52de6d was b52de6d, checked in by xkolman2 <xkolman2@…>, 4 years ago

initial import

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

  • Property mode set to 100644
File size: 6.6 KB
Line 
1#!/usr/bin/python
2#----------------------------------------------------------------------------
3# Display map vectors
4#----------------------------------------------------------------------------
5# Copyright 2008, Oliver White
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19#---------------------------------------------------------------------------
20from base_module import ranaModule
21import cairo
22import os
23import sys
24import urllib
25import tilenames
26import vmap_load
27from math import *
28from time import time
29
30def getModule(m,d):
31  return(vmap(m,d))
32
33class vmap(ranaModule):
34  """Display map vectors"""
35  def __init__(self, m, d):
36    ranaModule.__init__(self, m, d)
37    self.tiles = {}
38    self.style_d = 0
39    self.style_c = 0
40    self.lastColour = (-1,-1,-1)
41    self.lastWidth = -1
42    self.line_d = 0
43    self.line_c = 0
44
45  def firstTime(self):
46    self.loadEnums()
47    self.setupStyles()
48
49  def getTile(self,x,y,z):
50    # Use filename as dictionary key, so that zooms which happen to
51    # use the dataset don't get loaded twice
52    filename = vmap_load.getVmapFilename(x,y,z,self.d)
53    if(not filename):
54      return(None)
55
56    # If it doesn't already exist, then load it
57    if(not self.tiles.has_key(filename)):
58      #print "Loading %s" % (filename)
59      self.tiles[filename] = vmap_load.vmapData(filename)
60     
61    return(self.tiles[filename])
62
63  def setupStyles(self):
64    self.highways = {
65      'motorway':     ((0.5, 0.5, 1.0), 6, {'shields':True}),
66      'trunk':        ((0.0, 0.8, 0.0), 6, {'shields':True}),
67      'primary':      ((0.8, 0.0, 0.0), 6, {'shields':True}),
68      'secondary':    ((0.8, 0.8, 0.0), 6, {'shields':True}),
69      'tertiary':     ((0.8, 0.8, 0.0), 6, {}),
70      'unclassified': ((1.0, 1.0, 1.0), 4, {}),
71      'service':      ((1.0, 1.0, 1.0), 2, {}),
72      'footway':      ((1.0, 0.5, 0.5), 2, {'dashed':True}),
73      'cycleway':     ((0.5, 1.0, 0.5), 2, {'dashed':True}),
74      'bridleway':    ((0.5, 1.0, 0.5), 2, {'dashed':True}),
75      }
76
77  def loadEnums(self):
78    try:
79      filename = "%s/enums.txt" % vmap_load.getVmapBaseDir(self.d)
80      f = open(filename, "r")
81      self.enums = {}
82      for line in f:
83        k,v = line.rstrip().split("\t")
84        k = int(k)
85        #print "%d = '%s'" % (k,v)
86        self.enums[k] = v
87    except IOError:
88      print "Couldn't find vector map data. Expected enum file in %s" % filename
89      sys.exit(-1)
90
91   
92  def setStyle(self, style, cr):
93    styleDef = self.highways.get(style, None)
94    start = time()
95    if(not styleDef):
96      return(False)
97    (colour,width,options) = styleDef
98    width *= self.scale
99
100    if(colour != self.lastColour):
101      (r,g,b) = colour
102      cr.set_source_rgb(r,g,b)
103      self.lastColour = colour
104
105    if(width != self.lastWidth):
106      cr.set_line_width(width)
107      self.lastWidth = width
108     
109    duration = time() - start
110    self.style_d += duration
111    self.style_c += 1
112    return(True)
113   
114  def drawTile(self,cr,tx,ty,tz,proj,mapBounds):
115    start = time()
116    mapData = self.getTile(tx,ty,tz)
117    #print " - Map data: %1.3fms" % ((time() - start) * 1000.0)
118
119    cways = 0
120    cdone = 0
121    cnodes = 0
122    coob = 0
123
124    (minlat,maxlat,minlon,maxlon) = mapBounds
125    #print " - Map: %1.3f to %1.3f, %1.3f to %1.3f"%(minlat,maxlat,minlon,maxlon)
126   
127    if(mapData):
128      #print mapData.ways
129      for wayID, way in mapData.ways.items():
130        if(not self.waysDrawn.get(wayID, False)): # if not drawn already as part of another tile
131
132          (lon1,lon2,lat1,lat2) = way['bounds']
133
134          offMap = (lon2 < minlon
135            or lon1 > maxlon
136            or lat2 < minlat
137            or lat1 > maxlat)
138
139          #print "   - Way: %1.3f to %1.3f, %1.3f to   %1.3f - %s"%(lat1,lat2,lon1,lon2, text)
140
141          if(offMap):
142            coob += 1
143          else:
144            if(self.setStyle(self.enums[way['style']], cr)):
145              count = 0
146              cways += 1
147              line_start = time()
148              for node in way['n']:
149                cnodes += 1
150                (lat,lon,nid) = node
151                x,y = proj.ll2xy(lat,lon)
152                if(count == 0):
153                  cr.move_to(x,y)
154                else:
155                  cr.line_to(x,y)
156                count += 1
157              cr.stroke()
158              line_duration = time() - line_start
159              self.line_d += line_duration
160              self.line_c += 1
161             
162          # Note: way['N'] and way['r'] are name and ref respectively
163          self.waysDrawn[wayID] = True
164        else:
165          cdone += 1
166    else:
167      print "No map data"
168
169    #if(tx == 16342 and ty == 10803):
170    #print " - %d,%d,%d: %d ways, %d done, %d oob, %d nd, %1.3fms" % (tx,ty,tz, cways, cdone, coob, cnodes, 1000.0 * (time() - start))
171
172  def drawMap(self, cr):
173    (sx,sy,sw,sh) = self.get('viewport')
174    proj = self.m.get('projection', None)
175    if(not proj or not proj.isValid()):
176      return
177   
178    self.z = int(self.get('z', 15))
179
180    start = time()
181    count = 0
182
183    self.scale = self.get("scaleLines", 1.0)
184    if(self.get("zoomLines", True) and self.z > 14):
185      self.scale *= self.z - 14
186
187    #x1,y1 = proj.pxpy2xy(proj.px1,proj.py2)
188    #y1,x1 = proj.xy2ll(x1,y1)
189    #x2,y2 = proj.pxpy2xy(proj.px2,proj.py1)
190    #y2,x2 = proj.xy2ll(x2,y2)
191    #print "%1.3f to %1.3f, %1.3f to %1.3f" % (x1,x2,y1,y2)
192    bounds = (proj.S,proj.N, proj.W,proj.E)
193    #print "%1.3f to %1.3f, %1.3f to %1.3f" % bounds
194   
195    # Render each 'tile' in view
196    self.waysDrawn = {}
197    for x in range(int(floor(proj.px1)), int(ceil(proj.px2))):
198      for y in range(int(floor(proj.py1)), int(ceil(proj.py2))):
199        self.drawTile(cr,x,y,self.z,proj,bounds)
200        count += 1
201
202    duration = time() - start
203    #print "Z%d %d tiles, %f seconds" % (self.z, count, duration)
204    #print "%f - %f" % (proj.px1, proj.px2)
205
206    if(self.get("benchmarkLines")):
207      print "Style: %1.3fms, line %1.3fms" % (
208        1000.0 * self.style_d / self.style_c,
209        1000.0 * self.line_d / self.line_c)
210   
211  def update(self):
212    pass
213
214if(__name__ == "__main__"):
215  a = vmap({},{"vmapTileDir":"../../tiledata3/output"})
216  a.loadEnums()
Note: See TracBrowser for help on using the repository browser.