source: subversion/applications/routing/pyroute/projection.py @ 5890

Last change on this file since 5890 was 5874, checked in by ojw, 12 years ago

Remove zoom buttons from main screen (since they're guaranteed to require downloading a bunch of data, they won't be used so often) and put them on main menu

Make the "main menu" code instead of textfile again, so that it can get complicated

Remove link to options menu, since it's not available

Make checkboxes for sketch mode and centred mode in the main menu, to show their state

File size: 5.2 KB
Line 
1#!/usr/bin/python
2#-----------------------------------------------------------------------------
3# Projection code (lat/long to screen conversions)
4#
5# Usage:
6#   (library code for pyroute GUI, not for direct use)
7#-----------------------------------------------------------------------------
8# Copyright 2007, Oliver White
9#
10# This program is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22#-----------------------------------------------------------------------------
23from tilenames import *
24
25class Projection:
26  def __init__(self):
27    self.xyValid = False
28    self.llValid = False
29    self.needsEdgeFind = False
30   
31    # Scale is the number of display pixels per projected unit
32    self.scale = tileSizePixels()
33   
34  def isValid(self):
35    """Test if the module contains all the information needed to do conversions"""
36    return(self.xyValid and self.llValid)
37 
38  def setView(self,x,y,w,h):
39    """Setup the display"""
40    self.w = w
41    self.h = h
42    self.xc = x + self.w
43    self.yc = y + self.h
44    self.xyValid = True
45    if(self.needsEdgeFind):
46      self.findEdges()
47   
48  def recentre(self,lat,lon,zoom = None):
49    """Move the projection to a particular geographic location
50    (with optional zoom level)"""
51    self.lat = lat
52    self.lon = lon
53    if(zoom != None):
54      self.implementNewZoom(zoom)
55      # note: implementNewZoom calls findEdges, hence the else: statement
56    else:
57      self.findEdges()
58    self.llValid = True
59   
60  def setZoom(self, value, isAdjustment=False):
61    """Change the zoom level, keeping same map centre
62    if isAdjustment is true, then value is relative to current zoom
63    otherwise it's an absolute value"""
64    if(isAdjustment):
65      # TODO: maybe we don't want all zoom levels?
66      self.implementNewZoom(self.zoom + value)
67    else:
68      self.implementNewZoom(value)
69 
70  def limitZoom(self):
71    """Check the zoom level, and move it if necessary to one of
72    the 'allowed' zoom levels"""
73    if(self.zoom < 6):
74      self.zoom = 6
75    if(self.zoom > 17):
76      self.zoom = 17
77 
78  def implementNewZoom(self, zoom):
79    """Change the zoom level"""
80    self.zoom = int(zoom)
81    # Check it's valid
82    self.limitZoom()
83    # Update the projection
84    self.findEdges()
85 
86  def findEdges(self):
87    """Update the projection meta-info based on its fundamental parameters"""
88    if(not self.xyValid):
89      # If the display is not known yet, then we can't do anything, but we'll
90      # mark it as something that needs doing as soon as the display
91      # becomes valid
92      print "Can't find edges"
93      self.needsEdgeFind = True
94      return
95   
96    # Find the map centre in projection units
97    self.px, self.py = latlon2xy(self.lat,self.lon,self.zoom)
98   
99    # Find the map edges in projection units
100    self.px1 = self.px - 0.5 * self.w / self.scale
101    self.px2 = self.px + 0.5 * self.w / self.scale
102    self.py1 = self.py - 0.5 * self.h / self.scale
103    self.py2 = self.py + 0.5 * self.h / self.scale
104   
105    # Store width and height in projection units, just to save time later
106    self.pdx = self.px2 - self.px1
107    self.pdy = self.py2 - self.py1
108   
109    # Calculate the bounding box
110    # ASSUMPTION: (that the projection is regular and north-up)
111    self.N,self.W = xy2latlon(self.px1, self.py1, self.zoom)
112    self.S,self.E = xy2latlon(self.px2, self.py2, self.zoom)
113   
114    # Mark the meta-info as valid
115    self.needsEdgeFind = False
116 
117  def pxpy2xy(self,px,py):
118    """Convert projection units to display units"""
119    x = self.w * (px - self.px1) / self.pdx
120    y = self.h * (py - self.py1) / self.pdy
121    return(x,y)
122 
123  def nudge(self,dx,dy):
124    """Move the map by a number of pixels relative to its current position"""
125    if(dx == 0 and dy == 0):
126      return
127    # Calculate the lat/long of the pixel offset by dx,dy from the centre,
128    # and centre the map on that
129    newXC = self.px - dx / self.scale
130    newYC = self.py - dy / self.scale
131    self.lat,self.lon = xy2latlon(newXC,newYC, self.zoom)
132    self.findEdges()
133
134  def ll2xy(self,lat,lon):
135    """Convert geographic units to display units"""
136    px,py = latlon2xy(lat,lon,self.zoom)
137    x = (px - self.px1) * self.scale
138    y = (py - self.py1) * self.scale
139    return(x,y)
140 
141  def xy2ll(self,x,y):
142    """Convert display units to geographic units"""
143    px = self.px1 + x / self.scale
144    py = self.py1 + y / self.scale
145    lat,lon = xy2latlon(px, py, self.zoom)
146    return(lat,lon)
147 
148  def onscreen(self,x,y):
149    """Test if a position (in display units) is visible"""
150    return(x >= 0 and x < self.w and y >= 0 and y < self.h)
151 
152  def relXY(self,x,y):
153    return(x/self.w, y/self.h)
Note: See TracBrowser for help on using the repository browser.