Geography : cursor driven region and autozoom ( #0004882 )

svn: r17674
This commit is contained in:
Serge Noiraud 2011-06-03 10:08:41 +00:00
parent 4841f48dcf
commit 186057add6
2 changed files with 134 additions and 27 deletions

View File

@ -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(50, self._autozoom_in, lvl, p1lat, p1lon, p2lat, p2lon)
else:
gobject.timeout_add(50, 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(50, 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(50, 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,16 @@ 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.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)
@ -180,8 +202,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,14 +232,25 @@ 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()
places = self.is_there_a_place_here(lat, lon)
mess = ""
for p in places:
if mess != "":
mess += " || "
mess += p[0]
self.uistate.status.pop(self.context_id)
self.context_id = self.uistate.status.push(1, mess)
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:
if mess != "":
mess += " || "
mess += p[0]
self.uistate.status.pop(self.context_id)
self.context_id = self.uistate.status.push(1, mess)
def save_center(self, lat, lon):
"""
@ -225,11 +259,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:
# do we click on a marker ?
marker = self.is_there_a_marker_here(event, lat, lon)
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: