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

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

-remove BOM
-fix version strings

  • Property svn:keywords set to Rev
File size: 4.7 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4"""Projection code (lat/long to screen conversions)
5
6Usage:
7        (library code for pyroute GUI, not for direct use)
8"""
9
10__version__ = "$Rev: 18455 $"[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 tilenames import *
27
28class Projection:
29        def __init__(self):
30                self.xyValid = False
31                self.llValid = False
32                self.needsEdgeFind = False
33
34                # Scale is the number of display pixels per projected unit
35                self.scale = tileSizePixels()
36
37        def isValid(self):
38                """Test if the module contains all the information needed to do conversions"""
39                return(self.xyValid and self.llValid)
40
41        def setView(self,x,y,w,h):
42                """Setup the display"""
43                self.w = w
44                self.h = h
45                self.xc = x + self.w
46                self.yc = y + self.h
47                self.xyValid = True
48                if(self.needsEdgeFind):
49                        self.findEdges()
50
51        def recentre(self,lat,lon,zoom = None):
52                """Move the projection to a particular geographic location
53                (with optional zoom level)"""
54                self.lat = lat
55                self.lon = lon
56                if(zoom != None):
57                        self.implementNewZoom(zoom)
58                        # note: implementNewZoom calls findEdges, hence the else: statement
59                else:
60                        self.findEdges()
61                self.llValid = True
62
63        def setZoom(self, value, isAdjustment=False):
64                """Change the zoom level, keeping same map centre
65                if isAdjustment is true, then value is relative to current zoom
66                otherwise it's an absolute value"""
67                if(isAdjustment):
68                        # TODO: maybe we don't want all zoom levels?
69                        self.implementNewZoom(self.zoom + value)
70                else:
71                        self.implementNewZoom(value)
72
73        def limitZoom(self):
74                """Check the zoom level, and move it if necessary to one of
75                the 'allowed' zoom levels"""
76                if(self.zoom < 6):
77                        self.zoom = 6
78                if(self.zoom > 17):
79                        self.zoom = 17
80
81        def implementNewZoom(self, zoom):
82                """Change the zoom level"""
83                self.zoom = int(zoom)
84                # Check it's valid
85                self.limitZoom()
86                # Update the projection
87                self.findEdges()
88
89        def findEdges(self):
90                """Update the projection meta-info based on its fundamental parameters"""
91                if(not self.xyValid):
92                        # If the display is not known yet, then we can't do anything, but we'll
93                        # mark it as something that needs doing as soon as the display
94                        # becomes valid
95                        self.needsEdgeFind = True
96                        return
97
98                # Find the map centre in projection units
99                self.px, self.py = latlon2xy(self.lat,self.lon,self.zoom)
100
101                # Find the map edges in projection units
102                self.px1 = self.px - 0.5 * self.w / self.scale
103                self.px2 = self.px + 0.5 * self.w / self.scale
104                self.py1 = self.py - 0.5 * self.h / self.scale
105                self.py2 = self.py + 0.5 * self.h / self.scale
106
107                # Store width and height in projection units, just to save time later
108                self.pdx = self.px2 - self.px1
109                self.pdy = self.py2 - self.py1
110
111                # Calculate the bounding box
112                # ASSUMPTION: (that the projection is regular and north-up)
113                self.N,self.W = xy2latlon(self.px1, self.py1, self.zoom)
114                self.S,self.E = xy2latlon(self.px2, self.py2, self.zoom)
115
116                # Mark the meta-info as valid
117                self.needsEdgeFind = False
118
119        def pxpy2xy(self,px,py):
120                """Convert projection units to display units"""
121                x = self.w * (px - self.px1) / self.pdx
122                y = self.h * (py - self.py1) / self.pdy
123                return(x,y)
124
125        def nudge(self,dx,dy):
126                """Move the map by a number of pixels relative to its current position"""
127                if(dx == 0 and dy == 0):
128                        return
129                # Calculate the lat/long of the pixel offset by dx,dy from the centre,
130                # and centre the map on that
131                newXC = self.px - dx / self.scale
132                newYC = self.py - dy / self.scale
133                self.lat,self.lon = xy2latlon(newXC,newYC, self.zoom)
134                self.findEdges()
135
136        def ll2xy(self,lat,lon):
137                """Convert geographic units to display units"""
138                px,py = latlon2xy(lat,lon,self.zoom)
139                x = (px - self.px1) * self.scale
140                y = (py - self.py1) * self.scale
141                return(x,y)
142
143        def xy2ll(self,x,y):
144                """Convert display units to geographic units"""
145                px = self.px1 + x / self.scale
146                py = self.py1 + y / self.scale
147                lat,lon = xy2latlon(px, py, self.zoom)
148                return(lat,lon)
149
150        def onscreen(self,x,y):
151                """Test if a position (in display units) is visible"""
152                return(x >= 0 and x < self.w and y >= 0 and y < self.h)
153
154        def relXY(self,x,y):
155                return(x/self.w, y/self.h)
Note: See TracBrowser for help on using the repository browser.