Geography : cursor driven region and autozoom ( #0004882 )

svn: r17803
This commit is contained in:
Serge Noiraud 2011-06-16 17:44:41 +00:00
parent cef37b1c13
commit 556807529a
2 changed files with 137 additions and 28 deletions

View File

@ -155,7 +155,6 @@ class PlaceSelection(ManagedWindow.ManagedWindow, osmGpsMap):
self.oldvalue = oldvalue
self.place_list = places
self.function = function
self.selection_layer = None
self.selection_layer = layer
self.layer = layer
alignment = gtk.Alignment(0,1,0,0)
@ -366,6 +365,7 @@ class GeoGraphyView(osmGpsMap, NavigationView):
"""Called when the page changes."""
NavigationView.change_page(self)
self.uistate.clear_filter_results()
self.end_selection = None
def on_delete(self):
"""
@ -705,6 +705,70 @@ class GeoGraphyView(osmGpsMap, NavigationView):
"%a %d %b %Y %H:%M:%S", time.gmtime()))
self.uistate.set_busy_cursor(False)
def _visible_marker(self, lat, lon):
"""
Is this marker in the visible area ?
"""
bbox = self.osm.get_bbox()
s_lon = lon + 10.0
s_lat = lat + 10.0
s_bbox_lat1 = bbox[0] + 10.0
s_bbox_lon1 = bbox[1] + 10.0
s_bbox_lat2 = bbox[2] + 10.0
s_bbox_lon2 = bbox[3] + 10.0
result = ( s_bbox_lat1 > s_lat > s_bbox_lat2 ) and ( s_bbox_lon1 < s_lon < s_bbox_lon2 )
return result
def _autozoom_in(self, lvl, p1lat, p1lon, p2lat, p2lon):
"""
We zoom in until at least one marker missing.
"""
if ( ( self._visible_marker(p1lat, p1lon)
and self._visible_marker(p2lat, p2lon) )
and lvl < 18 ):
lvl += 1
self.osm.set_zoom(lvl)
gobject.timeout_add(150, self._autozoom_in, lvl, p1lat, p1lon, p2lat, p2lon)
else:
gobject.timeout_add(150, self._autozoom_out, lvl, p1lat, p1lon, p2lat, p2lon)
def _autozoom_out(self, lvl, p1lat, p1lon, p2lat, p2lon):
"""
We zoom out until all markers visible.
"""
if ( not ( self._visible_marker(p1lat, p1lon)
and self._visible_marker(p2lat, p2lon) )
and lvl > 1 ):
lvl -= 1
self.osm.set_zoom(lvl)
gobject.timeout_add(150, self._autozoom_out, lvl, p1lat, p1lon, p2lat, p2lon)
else:
layer = self.get_selection_layer()
if layer:
self.osm.layer_remove(layer)
def _autozoom(self):
"""
Try to put all markers on the map. we start at current zoom.
If all markers are present, continue to zoom.
If some markers are missing : return to the zoom - 1
We must use function called by timeout to force map updates.
"""
level_start = self.osm.props.zoom
p1lat, p1lon = self.begin_selection.get_degrees()
p2lat, p2lon = self.end_selection.get_degrees()
lat = p1lat + ( p2lat - p1lat ) / 2
lon = p1lon + ( p2lon - p1lon ) / 2
# We center the map on the center of the region
self.osm.set_center(lat, lon)
self.save_center(lat, lon)
p1lat = self.begin_selection.rlat
p1lon = self.begin_selection.rlon
p2lat = self.end_selection.rlat
p2lon = self.end_selection.rlon
# We zoom in until at least one marker missing.
gobject.timeout_add(150, self._autozoom_in, level_start, p1lat, p1lon, p2lat, p2lon)
def _set_center_and_zoom(self):
"""
Calculate the zoom.
@ -720,7 +784,10 @@ class GeoGraphyView(osmGpsMap, NavigationView):
signminlat = _get_sign(self.minlat)
signmaxlon = _get_sign(self.maxlon)
signmaxlat = _get_sign(self.maxlat)
# auto zoom ?
current = osmgpsmap.point_new_degrees(self.minlat, self.minlon)
self.end_selection = current
current = osmgpsmap.point_new_degrees(self.maxlat, self.maxlon)
self.begin_selection = current
if signminlon == signmaxlon:
maxlong = abs(abs(self.minlon) - abs(self.maxlon))
else:
@ -729,16 +796,6 @@ class GeoGraphyView(osmGpsMap, NavigationView):
maxlat = abs(abs(self.minlat) - abs(self.maxlat))
else:
maxlat = abs(abs(self.minlat) + abs(self.maxlat))
# Calculate the zoom. all places must be displayed on the map.
zoomlat = _get_zoom_lat(maxlat)
zoomlong = _get_zoom_long(maxlong)
self.new_zoom = zoomlat if zoomlat < zoomlong else zoomlong
self.new_zoom -= 1
if self.new_zoom < 2:
self.new_zoom = 2
# We center the map on a point at the center of all markers
self.centerlat = maxlat/2
self.centerlon = maxlong/2
latit = longt = 0.0
for mark in self.sort:
if ( signminlat == signmaxlat ):
@ -762,19 +819,17 @@ class GeoGraphyView(osmGpsMap, NavigationView):
# all maps: 0.0 for longitude and latitude means no location.
if latit == longt == 0.0:
latit = longt = 0.00000001
self.mustcenter = False
self.latit = latit
self.longt = longt
if not (latit == longt == 0.0):
self.mustcenter = True
if config.get("geography.lock"):
self.osm.set_center_and_zoom(config.get("geography.center-lat"),
config.get("geography.center-lon"),
config.get("geography.zoom") )
else:
self.osm.set_center_and_zoom(self.latit, self.longt, self.new_zoom)
self._autozoom()
self.end_selection = None
self.save_center(self.latit, self.longt)
config.set("geography.zoom",self.new_zoom)
config.set("geography.zoom",self.osm.props.zoom)
def _get_father_and_mother_name(self, event):
"""

View File

@ -101,10 +101,14 @@ class SelectionLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
def __init__(self):
gobject.GObject.__init__(self)
self.circles = []
self.rectangles = []
def add_circle(self, r, lat, lon):
self.circles.append((r, lat, lon))
def add_rectangle(self, p1, p2):
self.rectangles.append((p1, p2))
def do_draw(self, gpsmap, drawable):
gc = drawable.new_gc()
for circle in self.circles:
@ -115,6 +119,21 @@ class SelectionLayer(gobject.GObject, osmgpsmap.GpsMapLayer):
x, y = gpsmap.convert_geographic_to_screen(top_left)
x2, y2 = gpsmap.convert_geographic_to_screen(bottom_right)
drawable.draw_arc(gc, False, x, y, x2 - x, y2 - y, 0, 360*64)
for rectangle in self.rectangles:
top_left, bottom_right = rectangle
x, y = gpsmap.convert_geographic_to_screen(top_left)
x2, y2 = gpsmap.convert_geographic_to_screen(bottom_right)
# be sure when can select a region in all case.
if ( x < x2 ):
if ( y < y2 ):
drawable.draw_rectangle(gc, False, x, y, x2 - x, y2 - y)
else:
drawable.draw_rectangle(gc, False, x, y2, x2 - x, y - y2)
else:
if ( y < y2 ):
drawable.draw_rectangle(gc, False, x2, y, x - x2, y2 - y)
else:
drawable.draw_rectangle(gc, False, x2, y2, x - x2, y - y2)
def do_render(self, gpsmap):
pass
@ -132,8 +151,11 @@ class osmGpsMap():
self.cross_map = None
self.osm = None
self.show_tooltips = True
self.zone_selection = False
self.selection_layer = None
self.context_id = 0
self.begin_selection = None
self.end_selection = None
def build_widget(self):
self.vbox = gtk.VBox(False, 0)
@ -170,6 +192,7 @@ class osmGpsMap():
self.osm = osmgpsmap.GpsMap(tile_cache=tiles_path,
map_source=constants.map_type[map_type])
current_map = osmgpsmap.GpsMapOsd( show_dpad=False, show_zoom=True)
self.end_selection = None
self.osm.layer_add(current_map)
self.osm.layer_add(DummyLayer())
self.selection_layer = self.add_selection_layer()
@ -180,8 +203,9 @@ class osmGpsMap():
config.get("geography.zoom") )
self.osm.connect('button_release_event', self.map_clicked)
self.osm.connect('changed', self.zoom_changed)
self.osm.connect('button_press_event', self.map_clicked)
self.osm.connect("motion-notify-event", self.motion_event)
self.osm.connect('changed', self.zoom_changed)
self.osm.show()
self.vbox.pack_start(self.osm)
if obj is not None:
@ -209,6 +233,17 @@ class osmGpsMap():
current = osmgpsmap.point_new_degrees(0.0,0.0)
osmmap.convert_screen_to_geographic(int(event.x), int(event.y), current)
lat, lon = current.get_degrees()
if self.zone_selection:
# We draw a rectangle to show the selected region.
layer = self.get_selection_layer()
if layer:
self.osm.layer_remove(layer)
self.selection_layer = self.add_selection_layer()
if self.end_selection == None:
self.selection_layer.add_rectangle(self.begin_selection, current)
else:
self.selection_layer.add_rectangle(self.begin_selection, self.end_selection)
else:
places = self.is_there_a_place_here(lat, lon)
mess = ""
for p in places:
@ -225,11 +260,30 @@ class osmGpsMap():
config.set("geography.center-lat",lat)
config.set("geography.center-lon",lon)
def activate_selection_zoom(self, osm, event):
if self.end_selection is not None:
self._autozoom()
return True
def map_clicked(self, osm, event):
lat,lon = self.osm.get_event_location(event).get_degrees()
current = osmgpsmap.point_new_degrees(0.0,0.0)
osm.convert_screen_to_geographic(int(event.x), int(event.y), current)
lat, lon = current.get_degrees()
if event.button == 1:
if self.end_selection is not None:
self.activate_selection_zoom(osm, event)
self.end_selection = None
else:
# do we click on a marker ?
marker = self.is_there_a_marker_here(event, lat, lon)
elif event.button == 2 and event.type == gtk.gdk.BUTTON_PRESS:
self.begin_selection = current
self.end_selection = None
self.zone_selection = True
elif event.button == 2 and event.type == gtk.gdk.BUTTON_RELEASE:
self.end_selection = current
self.zone_selection = False
elif event.button == 3:
self.build_nav_menu(osm, event, lat, lon )
else: