From 21da05150f4376f213705ddc33c8a455caa34123 Mon Sep 17 00:00:00 2001 From: DarkLord76865 <40371578+darklord76865@users.noreply.github.com> Date: Sun, 26 Feb 2023 17:16:45 +0100 Subject: [PATCH 1/5] work on getting tiles --- tkintermapview/map_widget.py | 53 ++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/tkintermapview/map_widget.py b/tkintermapview/map_widget.py index b1f1780..95c299b 100644 --- a/tkintermapview/map_widget.py +++ b/tkintermapview/map_widget.py @@ -490,38 +490,49 @@ def request_image(self, zoom: int, x: int, y: int, db_cursor=None) -> ImageTk.Ph return self.empty_tile_image # try to get the tile from the server + + layers = [] # map, overlay + + # get map tile + save_tile = True try: url = self.tile_server.replace("{x}", str(x)).replace("{y}", str(y)).replace("{z}", str(zoom)) - image = Image.open(requests.get(url, stream=True, headers={"User-Agent": "TkinterMapView"}).raw) + layers.append(Image.open(requests.get(url, stream=True, headers={"User-Agent": "TkinterMapView"}).raw)) + except Exception: + save_tile = False - if self.overlay_tile_server is not None: + # get overlay tile + if self.overlay_tile_server is not None: + try: url = self.overlay_tile_server.replace("{x}", str(x)).replace("{y}", str(y)).replace("{z}", str(zoom)) - image_overlay = Image.open(requests.get(url, stream=True, headers={"User-Agent": "TkinterMapView"}).raw) - image = image.convert("RGBA") - image_overlay = image_overlay.convert("RGBA") + if "file://" not in url: + layers.append(Image.open(requests.get(url, stream=True, headers={"User-Agent": "TkinterMapView"}).raw)) + else: + layers.append(Image.open(url.replace("file://", ""))) + except Exception: + pass - if image_overlay.size is not (self.tile_size, self.tile_size): - image_overlay = image_overlay.resize((self.tile_size, self.tile_size), Image.ANTIALIAS) + if len(layers) == 0: # no map or overlay tile was found + image_tk = self.empty_tile_image + elif len(layers) == 1: # either map or overlay tile was found + image_tk = ImageTk.PhotoImage(layers[0]) + else: # both map and overlay tiles were found + layers = [layer.convert("RGBA") for layer in layers] - image.paste(image_overlay, (0, 0), image_overlay) + if layers[1].size is not (self.tile_size, self.tile_size): + layers[1] = layers[1].resize((self.tile_size, self.tile_size), Image.ANTIALIAS) - if self.running: - image_tk = ImageTk.PhotoImage(image) - else: - return self.empty_tile_image + layers[0].paste(layers[1], (0, 0), layers[1]) - self.tile_image_cache[f"{zoom}{x}{y}"] = image_tk - return image_tk - - except PIL.UnidentifiedImageError: # image does not exist for given coordinates - self.tile_image_cache[f"{zoom}{x}{y}"] = self.empty_tile_image - return self.empty_tile_image + image_tk = layers[0] - except requests.exceptions.ConnectionError: - return self.empty_tile_image + if save_tile: + self.tile_image_cache[f"{zoom}{x}{y}"] = image_tk - except Exception: + if not self.running: return self.empty_tile_image + else: + return image_tk def get_tile_image_from_cache(self, zoom: int, x: int, y: int): if f"{zoom}{x}{y}" not in self.tile_image_cache: From 2f04fce09d4d33353b7863cc46eb853a4e171cb0 Mon Sep 17 00:00:00 2001 From: DarkLord76865 <40371578+darklord76865@users.noreply.github.com> Date: Sun, 26 Feb 2023 17:25:03 +0100 Subject: [PATCH 2/5] small fix --- tkintermapview/map_widget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tkintermapview/map_widget.py b/tkintermapview/map_widget.py index 95c299b..8348a7f 100644 --- a/tkintermapview/map_widget.py +++ b/tkintermapview/map_widget.py @@ -524,7 +524,7 @@ def request_image(self, zoom: int, x: int, y: int, db_cursor=None) -> ImageTk.Ph layers[0].paste(layers[1], (0, 0), layers[1]) - image_tk = layers[0] + image_tk = ImageTk.PhotoImage(layers[0]) if save_tile: self.tile_image_cache[f"{zoom}{x}{y}"] = image_tk From 61e70f785ce965dc7cb099b9e96d7d5b16b4cfed Mon Sep 17 00:00:00 2001 From: DarkLord76865 <40371578+darklord76865@users.noreply.github.com> Date: Sun, 26 Feb 2023 17:35:08 +0100 Subject: [PATCH 3/5] updated readme.md example with local overlay tiles --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 1c8f00c..e757386 100644 --- a/README.md +++ b/README.md @@ -305,6 +305,9 @@ self.map_widget.set_tile_server("https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pi # example overlay tile server self.map_widget.set_overlay_tile_server("http://tiles.openseamap.org/seamark//{z}/{x}/{y}.png") # sea-map overlay self.map_widget.set_overlay_tile_server("http://a.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png") # railway infrastructure + +# local tile images as overlay tile server +self.map_widget.set_overlay_tile_server("file://PATH_TO_FOLDER_WITH_TILES/{z}/{x}/{y}.png") ```` --- From 1c6a7ebe8e4f8d7a2073dd0d280bf87734990b60 Mon Sep 17 00:00:00 2001 From: DarkLord76865 <40371578+darklord76865@users.noreply.github.com> Date: Sun, 5 Mar 2023 12:23:03 +0100 Subject: [PATCH 4/5] fixed mousewheel zoom on windows (now no zoom level is skipped) --- tkintermapview/map_widget.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tkintermapview/map_widget.py b/tkintermapview/map_widget.py index 8348a7f..2fa7612 100644 --- a/tkintermapview/map_widget.py +++ b/tkintermapview/map_widget.py @@ -905,7 +905,10 @@ def mouse_zoom(self, event): if sys.platform == "darwin": new_zoom = self.zoom + event.delta * 0.1 elif sys.platform.startswith("win"): - new_zoom = self.zoom + event.delta * 0.01 + if event.delta > 0: + new_zoom = self.zoom + 1 + else: + new_zoom = self.zoom - 1 elif event.num == 4: new_zoom = self.zoom + 1 elif event.num == 5: From d8ce037c3bd089e5ea832f79c76776f13468f39b Mon Sep 17 00:00:00 2001 From: DarkLord76865 Date: Sat, 29 Apr 2023 15:50:10 +0200 Subject: [PATCH 5/5] fix incorrect dimension change zoom out --- tkintermapview/map_widget.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tkintermapview/map_widget.py b/tkintermapview/map_widget.py index dbabd8e..5856472 100644 --- a/tkintermapview/map_widget.py +++ b/tkintermapview/map_widget.py @@ -190,9 +190,13 @@ def update_dimensions(self, event): if self.width != event.width or self.height != event.height: self.width = event.width self.height = event.height - self.min_zoom = math.ceil(math.log2(math.ceil(self.width / self.tile_size))) + self.min_zoom = max(math.ceil(math.log2(math.ceil(self.width / self.tile_size))), + math.ceil(math.log2(math.ceil(self.height / self.tile_size)))) - self.set_zoom(self.zoom) # call zoom to set the position vertices right + # pass True to set_zoom which will tell it to call draw_zoom even if it hasn't changed + # (doing this because zoom may not have changed, but top-left tile may not be in the top-left corner anymore, + # so blank tiles can appear it this isn't done) + self.set_zoom(int(round(self.zoom, 0)), called_from_update_dimensions=True) # call zoom to set the position vertices right self.draw_move() # call move to draw new tiles or delete tiles self.draw_rounded_corners() @@ -871,7 +875,7 @@ def fading_move(self): if self.running: self.after(1, self.fading_move) - def set_zoom(self, zoom: int, relative_pointer_x: float = 0.5, relative_pointer_y: float = 0.5): + def set_zoom(self, zoom: int, relative_pointer_x: float = 0.5, relative_pointer_y: float = 0.5, called_from_update_dimensions: bool = False): mouse_tile_pos_x = self.upper_left_tile_pos[0] + (self.lower_right_tile_pos[0] - self.upper_left_tile_pos[0]) * relative_pointer_x mouse_tile_pos_y = self.upper_left_tile_pos[1] + (self.lower_right_tile_pos[1] - self.upper_left_tile_pos[1]) * relative_pointer_y @@ -894,7 +898,8 @@ def set_zoom(self, zoom: int, relative_pointer_x: float = 0.5, relative_pointer_ self.lower_right_tile_pos = (current_tile_mouse_position[0] + (1 - relative_pointer_x) * (self.width / self.tile_size), current_tile_mouse_position[1] + (1 - relative_pointer_y) * (self.height / self.tile_size)) - if round(self.zoom) != round(self.last_zoom): + # check if zoom level changed or if function was called from update_dimensions and if so, redraw map + if (round(self.zoom) != round(self.last_zoom)) or called_from_update_dimensions: self.check_map_border_crossing() self.draw_zoom() self.last_zoom = round(self.zoom)