* src/DataViews/_MapView.py: Reworked to display multiple smaller tiled map images
* src/images/mk_blue_marble.py: Script to create the map tiles out of the nasa blue marble image * src/images/Makefile.am: Add map tile images and bootstrap them using mk_blue_marble.py svn: r6307
This commit is contained in:
parent
a6ccb47a55
commit
83a6d06277
@ -1,3 +1,11 @@
|
|||||||
|
2006-04-10 Martin Hawlisch <Martin.Hawlisch@gmx.de>
|
||||||
|
* src/DataViews/_MapView.py: Reworked to display multiple smaller
|
||||||
|
tiled map images
|
||||||
|
* src/images/mk_blue_marble.py: Script to create the map tiles out of
|
||||||
|
the nasa blue marble image
|
||||||
|
* src/images/Makefile.am: Add map tile images and bootstrap them using
|
||||||
|
mk_blue_marble.py
|
||||||
|
|
||||||
2006-04-10 Nathan Bullock <nathanbullock@gmail.com>
|
2006-04-10 Nathan Bullock <nathanbullock@gmail.com>
|
||||||
* src/GrampsDb/_ReadGedcom.py: LDS fixes.
|
* src/GrampsDb/_ReadGedcom.py: LDS fixes.
|
||||||
* src/Editors/_EditLdsOrd.py: LDS fixes.
|
* src/Editors/_EditLdsOrd.py: LDS fixes.
|
||||||
|
@ -30,6 +30,7 @@ import gc
|
|||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import math
|
||||||
|
|
||||||
log = logging.getLogger(".")
|
log = logging.getLogger(".")
|
||||||
|
|
||||||
@ -51,6 +52,7 @@ import RelLib
|
|||||||
import PageView
|
import PageView
|
||||||
import const
|
import const
|
||||||
|
|
||||||
|
# Some initial places for debugging
|
||||||
glob_loc_data = [ # (Name, longitude, latitude)
|
glob_loc_data = [ # (Name, longitude, latitude)
|
||||||
("_Center", 0,0),
|
("_Center", 0,0),
|
||||||
("_North",0,90),
|
("_North",0,90),
|
||||||
@ -67,7 +69,12 @@ glob_loc_data = [ # (Name, longitude, latitude)
|
|||||||
("Rio de Janeiro",-43.28,-22.88),
|
("Rio de Janeiro",-43.28,-22.88),
|
||||||
("Tokyo",139.75,35.67),
|
("Tokyo",139.75,35.67),
|
||||||
("Cape Town",18.47,-33.93),
|
("Cape Town",18.47,-33.93),
|
||||||
("Anchorage",-150.00,61.17)]
|
("Anchorage",-150.00,61.17),
|
||||||
|
("Mannheim-Wallstadt",8.55,49.48),
|
||||||
|
("Mannheim-Neckarau",8.48,49.45),
|
||||||
|
("Gorxheimertal",8.73,49.53)]
|
||||||
|
|
||||||
|
enable_debug = False
|
||||||
|
|
||||||
|
|
||||||
# Draws a map image and tries to allocate space in the correct aspect ratio
|
# Draws a map image and tries to allocate space in the correct aspect ratio
|
||||||
@ -79,13 +86,19 @@ class GuideMap(gtk.DrawingArea):
|
|||||||
self.connect("size-allocate", self.size_allocate_cb)
|
self.connect("size-allocate", self.size_allocate_cb)
|
||||||
self.gc = None
|
self.gc = None
|
||||||
self.current_area = None
|
self.current_area = None
|
||||||
|
self.current_spot = None
|
||||||
self.old_size = (-1,-1)
|
self.old_size = (-1,-1)
|
||||||
|
|
||||||
# Set hightlight region
|
# Set hightlight region
|
||||||
def hightlight_area( self, area):
|
def hightlight_area( self, area):
|
||||||
self.current_area = area
|
self.current_area = area
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
|
# Set hightlight region
|
||||||
|
def hightlight_spot( self, spot):
|
||||||
|
self.current_spot = spot
|
||||||
|
self.queue_draw()
|
||||||
|
|
||||||
# Redraw the image
|
# Redraw the image
|
||||||
def expose_cb(self,widget,event):
|
def expose_cb(self,widget,event):
|
||||||
if not self.gc:
|
if not self.gc:
|
||||||
@ -101,6 +114,14 @@ class GuideMap(gtk.DrawingArea):
|
|||||||
self.current_area[3])
|
self.current_area[3])
|
||||||
self.window.draw_rectangle( self.gc, False,
|
self.window.draw_rectangle( self.gc, False,
|
||||||
r[0],r[1],r[2],r[3])
|
r[0],r[1],r[2],r[3])
|
||||||
|
if self.current_spot:
|
||||||
|
r = self.map_to_screen(self.current_spot[0],
|
||||||
|
self.current_spot[1])
|
||||||
|
self.window.draw_line( self.gc,0,r[1],
|
||||||
|
self.backbuf.get_width(),r[1])
|
||||||
|
self.window.draw_line( self.gc,r[0],0,
|
||||||
|
r[0],self.backbuf.get_height())
|
||||||
|
|
||||||
|
|
||||||
# Scale backbuffer
|
# Scale backbuffer
|
||||||
def size_allocate_cb(self,widget,allocation):
|
def size_allocate_cb(self,widget,allocation):
|
||||||
@ -118,32 +139,117 @@ class GuideMap(gtk.DrawingArea):
|
|||||||
gtk.gdk.INTERP_BILINEAR)
|
gtk.gdk.INTERP_BILINEAR)
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
||||||
def map_to_screen( self, x,y,w,h):
|
def map_to_screen( self, x,y,w=None,h=None):
|
||||||
px = int((float(x) + 180.0) / 360.0 * self.backbuf.get_width())
|
px = int((float(x) + 180.0) / 360.0 * self.backbuf.get_width())
|
||||||
py = int((90-float(y)) / 180.0 * self.backbuf.get_height())
|
py = int((90-float(y)) / 180.0 * self.backbuf.get_height())
|
||||||
pw = int(float(w) / 360.0 * self.backbuf.get_width())
|
if w and h:
|
||||||
ph = int(float(h) / 180.0 * self.backbuf.get_height())
|
pw = int(float(w) / 360.0 * self.backbuf.get_width())
|
||||||
|
ph = int(float(h) / 180.0 * self.backbuf.get_height())
|
||||||
return (px,py,pw,ph)
|
return (px,py,pw,ph)
|
||||||
|
return (px,py)
|
||||||
|
|
||||||
|
# Map tile files used by the ZoomMap
|
||||||
|
class MapTile:
|
||||||
|
def __init__( self, filename, x, y, w, h, pw, ph):
|
||||||
|
self.filename = filename
|
||||||
|
self.full_path = os.path.join(const.image_dir,filename)
|
||||||
|
self.map_x = float(x)
|
||||||
|
self.map_y = float(y)
|
||||||
|
self.map_width = float(w)
|
||||||
|
self.map_height = float(h)
|
||||||
|
self.map_pixel_width = float(pw)
|
||||||
|
self.map_pixel_height = float(ph)
|
||||||
|
self.source_pixbuf = None
|
||||||
|
self.source_scale = self.map_pixel_width / self.map_width
|
||||||
|
self.scale = None
|
||||||
|
self.scaled_pixbuf = None
|
||||||
|
self.scaled_map_x = None
|
||||||
|
self.scaled_map_y = None
|
||||||
|
|
||||||
|
def set_viewport( self, target_scale, x_in, y_in, w_in, h_in):
|
||||||
|
# intersect viewport with map area
|
||||||
|
x = max(self.map_x, max(-180.0,x_in))
|
||||||
|
y = min(self.map_y, min( 90.0,y_in))
|
||||||
|
xmax = min( min(180.0,x_in+w_in), self.map_x+self.map_width)
|
||||||
|
ymin = max( max(-90.0,y_in-h_in), self.map_y-self.map_width)
|
||||||
|
w = xmax-x
|
||||||
|
h = y-ymin
|
||||||
|
|
||||||
|
if w > 0.0 and h > 0.0:
|
||||||
|
# crop source tile to not scale the whole image_dir
|
||||||
|
xoffset = max(0,math.floor((x - self.map_x) * self.source_scale))
|
||||||
|
xmax = max(0,math.ceil((x+w - self.map_x) * self.source_scale))
|
||||||
|
yoffset = min(self.map_pixel_width,math.floor(-(y - self.map_y) * self.source_scale))
|
||||||
|
ymax = min(self.map_pixel_height,math.ceil(-(y-h - self.map_y) * self.source_scale))
|
||||||
|
|
||||||
|
rescale = target_scale / self.source_scale
|
||||||
|
if int((xmax-xoffset)*rescale) > 0 and int((ymax-yoffset)*rescale) > 0:
|
||||||
|
self.scaled_map_x = self.map_x + xoffset / self.source_scale
|
||||||
|
self.scaled_map_y = self.map_y - yoffset / self.source_scale
|
||||||
|
self.scaled_map_pixel_w = int((xmax-xoffset)*rescale)
|
||||||
|
self.scaled_map_pixel_h = int((ymax-yoffset)*rescale)
|
||||||
|
|
||||||
|
if enable_debug:
|
||||||
|
print
|
||||||
|
print "Source-Map origin: %f x %f, %f, %f" % (self.map_x,self.map_y,self.map_width,self.map_height)
|
||||||
|
print "Source-Map pixels: %f x %f" % (self.map_pixel_width,self.map_pixel_height)
|
||||||
|
print "Source-Map scale: %f" % self.source_scale
|
||||||
|
print "Target origin: %f x %f, %f, %f" % (x,y,w,h)
|
||||||
|
print "Target scale: %f" % target_scale
|
||||||
|
print "Target crop: %f x %f, %f x %f" % (xoffset,yoffset,xmax,ymax)
|
||||||
|
print "Origin of crop: %f x %f" % (self.scaled_map_x,self.scaled_map_y)
|
||||||
|
print "scaled tile size: %f x %f pix" % (self.scaled_map_pixel_w,self.scaled_map_pixel_h)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not self.source_pixbuf:
|
||||||
|
self.source_pixbuf = gtk.gdk.pixbuf_new_from_file( self.full_path)
|
||||||
|
|
||||||
|
clip_pixbuf = self.source_pixbuf.subpixbuf(int(xoffset),int(yoffset),int(xmax-xoffset),int(ymax-yoffset))
|
||||||
|
|
||||||
|
self.scale = target_scale
|
||||||
|
self.scaled_pixbuf = clip_pixbuf.scale_simple( int((xmax-xoffset)*rescale), int((ymax-yoffset)*rescale), gtk.gdk.INTERP_BILINEAR)
|
||||||
|
clip_pixbuf = None
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.scale = None
|
||||||
|
self.scaled_pixbuf = None
|
||||||
|
else:
|
||||||
|
self.scale = None
|
||||||
|
self.scaled_pixbuf = None
|
||||||
|
|
||||||
|
def free(self):
|
||||||
|
self.scale = None
|
||||||
|
self.scaled_pixbuf = None
|
||||||
|
|
||||||
|
|
||||||
# Zoomable map image
|
# Zoomable map image
|
||||||
class ZoomMap( gtk.DrawingArea):
|
class ZoomMap( gtk.DrawingArea):
|
||||||
def __init__(self, map_pixbuf, place_marker_pixbuf,
|
def __init__( self, place_marker_pixbuf, hightlight_marker_pixbuf):
|
||||||
hightlight_marker_pixbuf):
|
|
||||||
gtk.DrawingArea.__init__(self)
|
gtk.DrawingArea.__init__(self)
|
||||||
self.map_pixbuf = map_pixbuf
|
|
||||||
self.place_marker_pixbuf = place_marker_pixbuf
|
self.place_marker_pixbuf = place_marker_pixbuf
|
||||||
self.hightlight_marker_pixbuf = hightlight_marker_pixbuf
|
self.hightlight_marker_pixbuf = hightlight_marker_pixbuf
|
||||||
|
self.add_events(gtk.gdk.POINTER_MOTION_MASK) # position overlay
|
||||||
self.connect("expose-event", self.expose_cb)
|
self.connect("expose-event", self.expose_cb)
|
||||||
self.connect("size-allocate", self.size_allocate_cb)
|
self.connect("size-allocate", self.size_allocate_cb)
|
||||||
|
if enable_debug:
|
||||||
|
self.connect("motion-notify-event", self.motion_notify_event_cb)
|
||||||
self.gc = None
|
self.gc = None
|
||||||
self.old_size = (-1,-1)
|
self.current_pixel_size = (-1,-1)
|
||||||
self.zoom_pos = (0,0)
|
self.zoom_pos = (0,0)
|
||||||
self.current_area = (0,0,0,0)
|
self.magnifer = 0.0 # in pixel per degree
|
||||||
self.magnifer = 0.5
|
|
||||||
self.guide = None
|
self.guide = None
|
||||||
self.textlayout = self.create_pango_layout("")
|
self.textlayout = self.create_pango_layout("")
|
||||||
|
self.map_sources = {}
|
||||||
|
self.initial_exposed = False
|
||||||
|
|
||||||
|
def add_map_source( self,filename, x, y, w, h,pw,ph):
|
||||||
|
tile = MapTile( filename, x, y, w, h, pw, ph)
|
||||||
|
if not tile.source_scale in self.map_sources:
|
||||||
|
self.map_sources[tile.source_scale] = []
|
||||||
|
self.map_sources[tile.source_scale].append( tile)
|
||||||
|
|
||||||
# Set the guide map that should follow the zoom area
|
# Set the guide map that should follow the zoom area
|
||||||
def set_guide( self, guide):
|
def set_guide( self, guide):
|
||||||
self.guide = guide
|
self.guide = guide
|
||||||
@ -154,6 +260,21 @@ class ZoomMap( gtk.DrawingArea):
|
|||||||
self.idx_long = idx_long
|
self.idx_long = idx_long
|
||||||
self.idx_lat = idx_lat
|
self.idx_lat = idx_lat
|
||||||
|
|
||||||
|
def motion_notify_event_cb(self,widget,event):
|
||||||
|
self.textlayout.set_text( "Position: %03.0f,%03.0f pixel" % (event.x,event.y))
|
||||||
|
(w,h) = self.textlayout.get_pixel_size()
|
||||||
|
self.gc.set_foreground( self.get_colormap().alloc_color("white"))
|
||||||
|
self.window.draw_rectangle( self.gc, True, 10,50,w,h)
|
||||||
|
self.gc.set_foreground( self.get_colormap().alloc_color("red"))
|
||||||
|
self.window.draw_layout( self.gc, 10, 50, self.textlayout)
|
||||||
|
(lon,lat) = self.screen_to_map(event.x,event.y)
|
||||||
|
self.textlayout.set_text( "Position: %03.0f,%03.0f degree" % (lon,lat))
|
||||||
|
(w,h) = self.textlayout.get_pixel_size()
|
||||||
|
self.gc.set_foreground( self.get_colormap().alloc_color("white"))
|
||||||
|
self.window.draw_rectangle( self.gc, True, 10,70,w,h)
|
||||||
|
self.gc.set_foreground( self.get_colormap().alloc_color("red"))
|
||||||
|
self.window.draw_layout( self.gc, 10, 70, self.textlayout)
|
||||||
|
|
||||||
# Redraw the image
|
# Redraw the image
|
||||||
def expose_cb(self,widget,event):
|
def expose_cb(self,widget,event):
|
||||||
if not self.gc:
|
if not self.gc:
|
||||||
@ -163,15 +284,28 @@ class ZoomMap( gtk.DrawingArea):
|
|||||||
if not self.backbuf:
|
if not self.backbuf:
|
||||||
self.size_allocate_cb( self,self.get_allocation())
|
self.size_allocate_cb( self,self.get_allocation())
|
||||||
if self.backbuf and self.gc:
|
if self.backbuf and self.gc:
|
||||||
self.window.draw_pixbuf( self.gc, self.backbuf, 0,0, 0,0, -1,-1)
|
#draw all maps
|
||||||
|
scales = self.map_sources.keys()
|
||||||
|
scales.sort()
|
||||||
|
for scale in scales:
|
||||||
|
for map in self.map_sources[scale]:
|
||||||
|
if map.scaled_pixbuf:
|
||||||
|
(px,py) = self.map_to_screen( map.scaled_map_x, map.scaled_map_y)
|
||||||
|
self.window.draw_pixbuf( self.gc, map.scaled_pixbuf, 0,0, px,py)
|
||||||
|
if enable_debug:
|
||||||
|
self.window.draw_rectangle( self.gc, False, px,py,map.scaled_map_pixel_w,map.scaled_map_pixel_h)
|
||||||
|
self.window.draw_line( self.gc, px,py,px+map.scaled_map_pixel_w,py+map.scaled_map_pixel_h)
|
||||||
|
self.window.draw_line( self.gc, px,py+map.scaled_map_pixel_h,px+map.scaled_map_pixel_w,py)
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
|
||||||
# draw all available locations
|
# draw all available locations
|
||||||
if self.location_model:
|
if self.location_model:
|
||||||
iter = self.location_model.get_iter_first()
|
iter = self.location_model.get_iter_first()
|
||||||
while iter:
|
while iter:
|
||||||
(n,x,y) = self.location_model.get( iter, self.idx_name, self.idx_long, self.idx_lat)
|
(n,x,y) = self.location_model.get( iter, self.idx_name, self.idx_long, self.idx_lat)
|
||||||
(px,py) = self.map_to_screen( x, y)
|
(px,py) = self.map_to_screen( x, y)
|
||||||
if px > 0 and py > 0 and px < self.backbuf.get_width() and py < self.backbuf.get_height():
|
#if px > 0 and py > 0 and px < self.backbuf.get_width() and py < self.backbuf.get_height():
|
||||||
# draw only visible markers
|
# draw only visible markers
|
||||||
#self.window.draw_pixbuf(
|
#self.window.draw_pixbuf(
|
||||||
# self.gc,
|
# self.gc,
|
||||||
@ -180,11 +314,11 @@ class ZoomMap( gtk.DrawingArea):
|
|||||||
# px-self.place_marker_pixbuf.get_width()/2,
|
# px-self.place_marker_pixbuf.get_width()/2,
|
||||||
# py-self.place_marker_pixbuf.get_height()/2,
|
# py-self.place_marker_pixbuf.get_height()/2,
|
||||||
# -1,-1)
|
# -1,-1)
|
||||||
self.textlayout.set_text(n)
|
self.textlayout.set_text(n)
|
||||||
self.window.draw_layout(
|
self.window.draw_layout(
|
||||||
self.gc,
|
self.gc,
|
||||||
px,py,
|
px,py,
|
||||||
self.textlayout)
|
self.textlayout)
|
||||||
iter = self.location_model.iter_next( iter)
|
iter = self.location_model.iter_next( iter)
|
||||||
|
|
||||||
# hightlight current location
|
# hightlight current location
|
||||||
@ -197,78 +331,100 @@ class ZoomMap( gtk.DrawingArea):
|
|||||||
py-self.hightlight_marker_pixbuf.get_height()/2,
|
py-self.hightlight_marker_pixbuf.get_height()/2,
|
||||||
-1,-1)
|
-1,-1)
|
||||||
#self.window.draw_rectangle( self.gc, False, px-3,py-3, 6,6)
|
#self.window.draw_rectangle( self.gc, False, px-3,py-3, 6,6)
|
||||||
|
|
||||||
|
#(px1,py1) = self.map_to_screen(-180, 90)
|
||||||
|
#(px2,py2) = self.map_to_screen( 180,-90)
|
||||||
|
#self.window.draw_rectangle( self.gc, False, px1,py1,px2-px1,py2-py1)
|
||||||
|
#self.window.draw_line( self.gc, px1,py1,px2,py2)
|
||||||
|
#self.window.draw_line( self.gc, px1,py2,px2,py1)
|
||||||
|
if enable_debug:
|
||||||
|
# Output debugging info
|
||||||
|
self.textlayout.set_text( "Magnifer: %f pixel per degree" % self.magnifer)
|
||||||
|
self.window.draw_layout( self.gc, 10, 10, self.textlayout)
|
||||||
|
self.textlayout.set_text( "Current map: %f pixel per degree" % self.selected_map_scale)
|
||||||
|
self.window.draw_layout( self.gc, 10, 30, self.textlayout)
|
||||||
|
|
||||||
def map_to_screen( self, long, lat):
|
def map_to_screen( self, lon, lat):
|
||||||
px = int(self.backbuf.get_width() / self.current_map_area[2] *
|
px = int(self.current_pixel_size[0] / 2.0 + (lon - self.zoom_pos[0]) * self.magnifer)
|
||||||
(float(long) - self.current_map_area[0]))
|
py = int(self.current_pixel_size[1] / 2.0 - (lat - self.zoom_pos[1]) * self.magnifer)
|
||||||
py = int(self.backbuf.get_height() / self.current_map_area[3] *
|
|
||||||
(-float(lat) + self.current_map_area[1]))
|
|
||||||
return( px, py)
|
return( px, py)
|
||||||
|
|
||||||
|
def screen_to_map( self, px, py):
|
||||||
|
px = float(px)
|
||||||
|
py = float(py)
|
||||||
|
lon = (px - self.current_pixel_size[0]/2) / self.magnifer + self.zoom_pos[0];
|
||||||
|
lat = -(py - self.current_pixel_size[1]/2) / self.magnifer + self.zoom_pos[1];
|
||||||
|
return( lon, lat)
|
||||||
|
|
||||||
# Scale backbuffer
|
# Scale backbuffer
|
||||||
def size_allocate_cb(self,widget,allocation):
|
def size_allocate_cb(self,widget,allocation):
|
||||||
# only create new backbuffer if size is different
|
# only create new backbuffer if size is different
|
||||||
new_size = (allocation.width,allocation.height)
|
new_size = (allocation.width,allocation.height)
|
||||||
if new_size is not self.old_size or not self.backbuf:
|
if new_size is not self.current_pixel_size or not self.backbuf:
|
||||||
self.old_size = new_size
|
self.backbuf = True
|
||||||
|
self.current_pixel_size = new_size
|
||||||
|
if self.magnifer == 0.0:
|
||||||
|
# scale map to full width
|
||||||
|
self.magnifer = self.current_pixel_size[0] / 360.0
|
||||||
|
x0,y0 = self.screen_to_map( 0, 0)
|
||||||
|
x1,y1 = self.screen_to_map( new_size[0], new_size[1])
|
||||||
|
self.guide.hightlight_area( (x0,y0,x1-x0, y0-y1))
|
||||||
|
|
||||||
# Desired midpoint in map
|
def cmpfunc(s):
|
||||||
pw = int(self.old_size[0]*self.magnifer)
|
return((self.magnifer-s)*(self.magnifer-s))
|
||||||
ph = int(self.old_size[1]*self.magnifer)
|
|
||||||
|
# select best matching tile set
|
||||||
|
self.selected_map_scale = None
|
||||||
|
smallest_scale = None
|
||||||
|
largest_scale = None
|
||||||
|
for s in self.map_sources.keys():
|
||||||
|
if not self.selected_map_scale or cmpfunc(s) < cmpfunc(self.selected_map_scale):
|
||||||
|
self.selected_map_scale = s
|
||||||
|
if not smallest_scale or s < smallest_scale:
|
||||||
|
smallest_scale = s
|
||||||
|
if not largest_scale or s > largest_scale:
|
||||||
|
largest_scale = s
|
||||||
|
if enable_debug:
|
||||||
|
print "scale of display: %f" % self.magnifer
|
||||||
|
print "available map scales:"
|
||||||
|
print self.map_sources.keys()
|
||||||
|
print "largest scale: %f" % largest_scale
|
||||||
|
print "smallest scale: %f" % smallest_scale
|
||||||
|
print "selected scale: %f" % self.selected_map_scale
|
||||||
|
|
||||||
px = int((float(self.zoom_pos[0]) + 180.0) / 360.0
|
for s in self.map_sources.keys():
|
||||||
* self.map_pixbuf.get_width())
|
for map in self.map_sources[s]:
|
||||||
py = int((90-float(self.zoom_pos[1])) / 180.0
|
if s == self.selected_map_scale or s == smallest_scale:
|
||||||
* self.map_pixbuf.get_height())
|
map.set_viewport( self.magnifer, x0, y0, x1-x0, y0-y1)
|
||||||
|
else:
|
||||||
px = max( pw/2, px)
|
map.free()
|
||||||
py = max( ph/2, py)
|
|
||||||
|
|
||||||
px = min( px, self.map_pixbuf.get_width()-1-pw/2)
|
|
||||||
py = min( py, self.map_pixbuf.get_height()-1-ph/2)
|
|
||||||
|
|
||||||
try:
|
|
||||||
zoomebuf = self.map_pixbuf.subpixbuf( max(0,int(px-pw/2)),max(0,int(py-ph/2)),
|
|
||||||
min(self.map_pixbuf.get_width(),pw),
|
|
||||||
min(self.map_pixbuf.get_height(),ph))
|
|
||||||
self.backbuf = zoomebuf.scale_simple(self.old_size[0],
|
|
||||||
self.old_size[1],
|
|
||||||
gtk.gdk.INTERP_BILINEAR)
|
|
||||||
gc.collect()
|
|
||||||
mx = 360.0 / self.map_pixbuf.get_width() * (px-pw/2.0) - 180.0
|
|
||||||
my = 90.0 - 180.0 / self.map_pixbuf.get_height() * (py-ph/2.0)
|
|
||||||
mw = 360.0 / self.map_pixbuf.get_width() * pw
|
|
||||||
mh = 180.0 / self.map_pixbuf.get_height() * ph
|
|
||||||
self.current_area = (px-pw/2, py-ph/2, pw,ph)
|
|
||||||
self.current_map_area = (mx, my, mw, mh)
|
|
||||||
if self.guide:
|
|
||||||
self.guide.hightlight_area( (mx,my,mw,mh))
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Scroll to requested position
|
# Scroll to requested position
|
||||||
def scroll_to( self, long, lat):
|
def scroll_to( self, long, lat):
|
||||||
self.zoom_pos = ( min(180,(max(-180,long))), min(90,(max(-90,lat))))
|
self.zoom_pos = (float( min(180,(max(-180,long)))), float(min(90,(max(-90,lat)))))
|
||||||
self.backbuf = None
|
self.backbuf = None
|
||||||
|
if self.guide:
|
||||||
|
self.guide.hightlight_spot( self.zoom_pos)
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
def zoom_out(self):
|
def zoom_out(self):
|
||||||
self.magnifer = min( 10, self.magnifer * 1.5)
|
self.magnifer = max( 1.0, self.magnifer * 2.0/3.0)
|
||||||
self.backbuf = None
|
self.backbuf = None
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
def zoom_in(self):
|
def zoom_in(self):
|
||||||
self.magnifer = max( 0.1, self.magnifer * 0.75)
|
self.magnifer = min( 500.0, self.magnifer * 1.5)
|
||||||
self.backbuf = None
|
self.backbuf = None
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
def zoom_normal(self):
|
def zoom_normal(self):
|
||||||
self.magnifer = 1
|
self.magnifer = 1.0
|
||||||
|
self.magnifer = self.selected_map_scale
|
||||||
self.backbuf = None
|
self.backbuf = None
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
def zoom_fit(self):
|
def zoom_fit(self):
|
||||||
self.magnifer = 2
|
self.magnifer = self.current_pixel_size[0] / 360.0
|
||||||
self.backbuf = None
|
self.backbuf = None
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
@ -400,10 +556,54 @@ class MapView(PageView.PageView):
|
|||||||
|
|
||||||
no = gtk.Image()
|
no = gtk.Image()
|
||||||
# The large zoomable map
|
# The large zoomable map
|
||||||
self.zoom_map = ZoomMap(
|
self.zoom_map = ZoomMap(
|
||||||
gtk.gdk.pixbuf_new_from_file(os.path.join(const.image_dir,"land_shallow_topo_2048.jpg")),
|
|
||||||
gtk.gdk.pixbuf_new_from_file(os.path.join(const.image_dir,"bad.png")),
|
gtk.gdk.pixbuf_new_from_file(os.path.join(const.image_dir,"bad.png")),
|
||||||
gtk.gdk.pixbuf_new_from_file(os.path.join(const.image_dir,"good.png")))
|
gtk.gdk.pixbuf_new_from_file(os.path.join(const.image_dir,"good.png")))
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_0_0.jpg', -180,90, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_0_1.jpg', -135,90, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_0_2.jpg', -90,90, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_0_3.jpg', -45,90, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_0_4.jpg', 0,90, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_0_5.jpg', 45,90, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_0_6.jpg', 90,90, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_0_7.jpg', 135,90, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_1_0.jpg', -180,45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_1_1.jpg', -135,45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_1_2.jpg', -90,45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_1_3.jpg', -45,45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_1_4.jpg', 0,45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_1_5.jpg', 45,45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_1_6.jpg', 90,45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_1_7.jpg', 135,45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_2_0.jpg', -180,0, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_2_1.jpg', -135,0, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_2_2.jpg', -90,0, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_2_3.jpg', -45,0, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_2_4.jpg', 0,0, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_2_5.jpg', 45,0, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_2_6.jpg', 90,0, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_2_7.jpg', 135,0, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_3_0.jpg', -180,-45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_3_1.jpg', -135,-45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_3_2.jpg', -90,-45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_3_3.jpg', -45,-45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_3_4.jpg', 0,-45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_3_5.jpg', 45,-45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_3_6.jpg', 90,-45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x3200x1600_tile_3_7.jpg', 135,-45, 45,45, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x1600x800_tile_0_0.jpg', -180,90, 90,90, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x1600x800_tile_0_1.jpg', -90,90, 90,90, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x1600x800_tile_0_2.jpg', 0,90, 90,90, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x1600x800_tile_0_3.jpg', 90,90, 90,90, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x1600x800_tile_1_0.jpg', -180,0, 90,90, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x1600x800_tile_1_1.jpg', -90,0, 90,90, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x1600x800_tile_1_2.jpg', 0,0, 90,90, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x1600x800_tile_1_3.jpg', 90,0, 90,90, 400,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x800x400.jpg', -180,90, 360,180, 800,400)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x400x200.jpg', -180,90, 360,180, 400,200)
|
||||||
|
self.zoom_map.add_map_source('world.topo.200407.3x128x60.jpg', -180,90, 360,180, 128,60)
|
||||||
|
|
||||||
|
#self.zoom_map.add_map_source("europe_2_0.jpg",0,90,90,90,1024,1024)
|
||||||
self.zoom_map.set_size_request(300,300)
|
self.zoom_map.set_size_request(300,300)
|
||||||
hbox.pack_start( self.zoom_map, True, True, 0)
|
hbox.pack_start( self.zoom_map, True, True, 0)
|
||||||
|
|
||||||
@ -413,7 +613,7 @@ class MapView(PageView.PageView):
|
|||||||
|
|
||||||
# The small guide map
|
# The small guide map
|
||||||
self.guide_map = GuideMap(
|
self.guide_map = GuideMap(
|
||||||
gtk.gdk.pixbuf_new_from_file(os.path.join(const.image_dir,"land_shallow_topo_350.jpg")))
|
gtk.gdk.pixbuf_new_from_file(os.path.join(const.image_dir,"world.topo.200407.3x128x60.jpg")))
|
||||||
self.guide_map.set_size_request(128,64)
|
self.guide_map.set_size_request(128,64)
|
||||||
vbox.pack_start( self.guide_map, False, True, 0)
|
vbox.pack_start( self.guide_map, False, True, 0)
|
||||||
|
|
||||||
|
@ -12,8 +12,6 @@ dist_pkgdata_DATA = \
|
|||||||
flist.svg\
|
flist.svg\
|
||||||
good.png\
|
good.png\
|
||||||
gramps.png\
|
gramps.png\
|
||||||
land_shallow_topo_2048.jpg\
|
|
||||||
land_shallow_topo_350.jpg\
|
|
||||||
locked.png\
|
locked.png\
|
||||||
logo.png\
|
logo.png\
|
||||||
media.svg\
|
media.svg\
|
||||||
@ -32,6 +30,55 @@ dist_pkgdata_DATA = \
|
|||||||
stock_lock.png\
|
stock_lock.png\
|
||||||
tools.png\
|
tools.png\
|
||||||
somerights20.gif \
|
somerights20.gif \
|
||||||
document.png
|
document.png\
|
||||||
|
world.topo.200407.3x128x60.jpg\
|
||||||
|
world.topo.200407.3x400x200.jpg\
|
||||||
|
world.topo.200407.3x800x400.jpg\
|
||||||
|
world.topo.200407.3x1600x800_tile_0_0.jpg\
|
||||||
|
world.topo.200407.3x1600x800_tile_0_1.jpg\
|
||||||
|
world.topo.200407.3x1600x800_tile_0_2.jpg\
|
||||||
|
world.topo.200407.3x1600x800_tile_0_3.jpg\
|
||||||
|
world.topo.200407.3x1600x800_tile_1_0.jpg\
|
||||||
|
world.topo.200407.3x1600x800_tile_1_1.jpg\
|
||||||
|
world.topo.200407.3x1600x800_tile_1_2.jpg\
|
||||||
|
world.topo.200407.3x1600x800_tile_1_3.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_0_0.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_0_1.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_0_2.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_0_3.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_0_4.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_0_5.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_0_6.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_0_7.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_1_0.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_1_1.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_1_2.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_1_3.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_1_4.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_1_5.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_1_6.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_1_7.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_2_0.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_2_1.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_2_2.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_2_3.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_2_4.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_2_5.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_2_6.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_2_7.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_3_0.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_3_1.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_3_2.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_3_3.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_3_4.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_3_5.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_3_6.jpg\
|
||||||
|
world.topo.200407.3x3200x1600_tile_3_7.jpg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXTRA_DIST = gramps.svg
|
EXTRA_DIST = gramps.svg
|
||||||
|
|
||||||
|
world.topo.200407.3x800x400.jpg: mk_blue_marble.py
|
||||||
|
python mk_blue_marble.py
|
||||||
|
|
||||||
|
100
src/images/mk_blue_marble.py
Normal file
100
src/images/mk_blue_marble.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# Script to create smaller map tiles for use in the GRAMPS MapView.
|
||||||
|
# (c) Martin Hawlisch, martin.hawlisch@gmx.de, 2006.
|
||||||
|
# I hereby put this script into the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
# Images are generated by using the NASA Blue Marble next generation images.
|
||||||
|
# http://visibleearth.nasa.gov/view_set.php?categoryID=2355
|
||||||
|
# July, Blue Marble Next Generation w/ Topography and Bathymetry:
|
||||||
|
# http://visibleearth.nasa.gov/view_rec.php?id=7106
|
||||||
|
# 5400 pixel jpeg file:
|
||||||
|
# http://veimages.gsfc.nasa.gov/7106/world.topo.bathy.200407.3x5400x2700.jpg
|
||||||
|
# This images are public domain.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
tile_defines = []
|
||||||
|
|
||||||
|
def process_file( imagefile, image_width, image_height, map_x, map_y, map_width, outfilepattern, tile_size):
|
||||||
|
y = 0
|
||||||
|
while (y*tile_size) < image_height:
|
||||||
|
x = 0
|
||||||
|
while (x*tile_size) < image_width:
|
||||||
|
outfile = outfilepattern % (y,x)
|
||||||
|
if not os.path.isfile( outfile):
|
||||||
|
cmd = "jpegtran -optimize -crop %dx%d+%d+%d -outfile %s %s" %\
|
||||||
|
(tile_size,tile_size,x*tile_size,y*tile_size,outfile,imagefile)
|
||||||
|
print cmd
|
||||||
|
if os.system( cmd):
|
||||||
|
print "ERROR"
|
||||||
|
else:
|
||||||
|
print "tile %s already exists" % outfile
|
||||||
|
tile_width = map_width/(image_width/tile_size)
|
||||||
|
tile_x = map_x + tile_width * x
|
||||||
|
tile_y = map_y - tile_width * y
|
||||||
|
print "location: %dx%d" % (tile_x,tile_y)
|
||||||
|
tile_defines.append("self.zoom_map.add_map_source('%s', %d,%d, %d,%d, %d,%d)" %\
|
||||||
|
(outfile,tile_x,tile_y,tile_width,tile_width,tile_size,tile_size))
|
||||||
|
x = x + 1
|
||||||
|
y = y + 1
|
||||||
|
pass
|
||||||
|
|
||||||
|
def scale_down( infile, outfile, new_width):
|
||||||
|
if not os.path.isfile( outfile):
|
||||||
|
cmd = "convert %s -resize %d %s" % (infile,new_width,outfile)
|
||||||
|
print cmd
|
||||||
|
if os.system( cmd):
|
||||||
|
print "ERROR"
|
||||||
|
else:
|
||||||
|
print "scaled down image %s already exists" % outfile
|
||||||
|
|
||||||
|
def fetch_image( server, filename):
|
||||||
|
if not os.path.isfile( sourcemap_midres):
|
||||||
|
print "downloading map file %s" % filename
|
||||||
|
cmd = "wget -v %s/%s" % (server, sourcemap_midres)
|
||||||
|
print cmd
|
||||||
|
if os.system( cmd):
|
||||||
|
print "ERROR"
|
||||||
|
|
||||||
|
else:
|
||||||
|
print "mapfile %s already downloaded" % filename
|
||||||
|
|
||||||
|
server = "http://veimages.gsfc.nasa.gov/7130"
|
||||||
|
|
||||||
|
# Step 1: Fetch mid-res image
|
||||||
|
sourcemap_midres = "world.topo.200407.3x5400x2700.jpg"
|
||||||
|
fetch_image( server, sourcemap_midres)
|
||||||
|
|
||||||
|
|
||||||
|
# Step 2: Scale that down a bit (to a multiple of 16 pixels)
|
||||||
|
sourcemap_lowres = "world.topo.200407.3x3200x1600.jpg"
|
||||||
|
scale_down(sourcemap_midres,sourcemap_lowres,3200)
|
||||||
|
|
||||||
|
# Step 3: Create tiles
|
||||||
|
process_file( sourcemap_lowres, 3200, 1600, -180, 90, 360, "world.topo.200407.3x3200x1600_tile_%d_%d.jpg",400)
|
||||||
|
|
||||||
|
# Step 4: Scale down mid-res image to 2048x1024
|
||||||
|
sourcemap_lowres = "world.topo.200407.3x1600x800.jpg"
|
||||||
|
scale_down(sourcemap_midres,sourcemap_lowres,1600)
|
||||||
|
|
||||||
|
# Step 4: Tile low-res image
|
||||||
|
process_file( sourcemap_lowres, 1600, 800, -180, 90, 360, "world.topo.200407.3x1600x800_tile_%d_%d.jpg",400)
|
||||||
|
|
||||||
|
# Step 5: Scale down once more
|
||||||
|
sourcemap_thumb = "world.topo.200407.3x800x400.jpg"
|
||||||
|
scale_down(sourcemap_lowres,sourcemap_thumb,800)
|
||||||
|
|
||||||
|
# Step 5: Scale down thumb-scale image
|
||||||
|
sourcemap_thumb = "world.topo.200407.3x400x200.jpg"
|
||||||
|
scale_down(sourcemap_lowres,sourcemap_thumb,400)
|
||||||
|
|
||||||
|
# Step 5: Scale down thumb-scale image
|
||||||
|
sourcemap_thumb = "world.topo.200407.3x128x60.jpg"
|
||||||
|
scale_down(sourcemap_lowres,sourcemap_thumb,128)
|
||||||
|
|
||||||
|
|
||||||
|
for d in tile_defines:
|
||||||
|
print d
|
||||||
|
|
Loading…
Reference in New Issue
Block a user