import wx import math from mappanel import MapPanel def deg_to_rad(angle): return angle * math.pi / 180. def rad_to_deg(angle): return angle * 180. / math.pi def distance_points(lon1, lat1, lon2, lat2): # in rad dlon = lon2 - lon1 dlat = lat2 - lat1 a = math.sin(dlat/2) ** 2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2) ** 2 c = 2 * math.asin(min(1, math.sqrt(a))) d = (40000. / math.pi / 2) * c return d # in km class DraggableMapPanel(MapPanel): mouseposcallback = None def __init__(self, *args, **kwargs): MapPanel.__init__(self, *args, **kwargs) self.Bind(wx.EVT_MOUSE_EVENTS, self.MouseEvent) self.drag = None self.autoupdate = True self.lastpos = None def getlonlat(self, x, y): mapx = self.mapx + x / 256. mapy = self.mapy + y / 256. tilecount = 2 ** self.mapzoom lonpertile = 360. / tilecount lon = (mapx - tilecount / 2.) * lonpertile ycoord = mapy / tilecount y = (ycoord - 0.5) * 2. ydelta = y * (2. * math.pi) ediv = math.e ** (-ydelta) e = (ediv - 1.) / (ediv + 1.) lat = rad_to_deg(math.asin(e)) return lon, lat def Reposition(self): self.lines = [] self.lastpos = None MapPanel.Reposition(self) def MouseEvent(self, evt): # Handle zoom if evt.GetWheelRotation(): tile_w, tile_h = self.tilemanager.tilesize mouse_x, mouse_y = evt.GetPosition() # Old map position at the cursor old_x = self.mapx + float(mouse_x) / tile_w old_y = self.mapy + float(mouse_y) / tile_h oldzoom = self.mapzoom self.mapzoom += evt.GetWheelRotation() // evt.GetWheelDelta() zoomratio = 2 ** (self.mapzoom - oldzoom) self.mapx = old_x * zoomratio - float(mouse_x) / tile_w self.mapy = old_y * zoomratio - float(mouse_y) / tile_h self.Reposition() # Handle drag if evt.LeftDown(): self.drag = evt.GetPosition() elif (evt.Dragging() or evt.LeftUp()) and self.drag: delta = evt.GetPosition() - self.drag tile_w, tile_h = self.tilemanager.tilesize self.mapx -= float(delta.x) / tile_w self.mapy -= float(delta.y) / tile_h self.Reposition() self.drag = evt.GetPosition() if evt.LeftUp(): self.drag = None # Handle mouse position if evt.RightUp() and self.mouseposcallback: x, y = evt.GetPosition() lon, lat = self.getlonlat(x, y) if self.lastpos: self.lines.append((self.lastpos[0], self.lastpos[1], x, y)) self.Refresh() self.mouseposcallback(lon, lat) self.lastpos = (x, y) def get_distance(self): distance = 0. for x1, y1, x2, y2 in self.lines: lon1, lat1 = map(deg_to_rad, self.getlonlat(x1, y1)) lon2, lat2 = map(deg_to_rad, self.getlonlat(x2, y2)) distance += distance_points(lon1, lat1, lon2, lat2) return distance