You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Perhaps you're aware of the center-hopping issue: at certain points, when zooming in the map, the map center swaps between two positions, mostly between zoom levels 17, 18 and 19. (ie @ N0°0.0, E15°24.6065). This is due to a rounding issue computing float variables (6.5 digits accuracy), while the global map needs 7 digits accuracy.
I fixed this bug. But sorry, filing a pull request is over my head. So I post a patch here:
From 348ef5fc230641f442f79297e0be4894e199cf28 Mon Sep 17 00:00:00 2001
From: Thomas Freiherr <Thomas[ dot )Freiherr{ at ]gmx( dot }net>
Date: Fri, 25 Aug 2023 13:20:36 +0200
Subject: [PATCH] fix center hopping
Signed-off-by: Thomas Freiherr
---
src/converter.c | 45 ++++++++++++----------------------------
src/osm-gps-map-widget.c | 16 +++++++-------
2 files changed, 21 insertions(+), 40 deletions(-)
diff --git a/src/converter.c b/src/converter.c
index cfa7093..d822577 100644
--- a/src/converter.c
+++ b/src/converter.c
@@ -9,7 +9,7 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -55,11 +55,6 @@ int
lat2pixel( int zoom,
float lat)
{
- float lat_m;
- int pixel_y;
-
- lat_m = atanh(sin(lat));
-
/* the formula is
*
* some more notes
@@ -67,11 +62,8 @@ lat2pixel( int zoom,
*
* pixel_y = -(2^zoom * TILESIZE * lat_m) / 2PI + (2^zoom * TILESIZE) / 2
*/
- pixel_y = -(int)( (lat_m * TILESIZE * (1 << zoom) ) / (2*M_PI)) +
- ((1 << zoom) * (TILESIZE/2) );
-
-
- return pixel_y;
+ float y = atanh(sin(lat)) * TILESIZE * (1 << zoom) / (2*M_PI);
+ return -(int)(y) + (((1 << zoom) * TILESIZE) >> 1);
}
@@ -79,41 +71,28 @@ int
lon2pixel( int zoom,
float lon)
{
- int pixel_x;
-
/* the formula is
*
* pixel_x = (2^zoom * TILESIZE * lon) / 2PI + (2^zoom * TILESIZE) / 2
*/
- pixel_x = (int)(( lon * TILESIZE * (1 << zoom) ) / (2*M_PI)) +
- ( (1 << zoom) * (TILESIZE/2) );
- return pixel_x;
+ float x = lon * TILESIZE * (1 << zoom) / (2*M_PI);
+ return (int)(x) + (((1 << zoom) * TILESIZE) >> 1);
}
float
pixel2lon( float zoom,
int pixel_x)
{
- float lon;
-
- lon = ((pixel_x - ( exp(zoom * M_LN2) * (TILESIZE/2) ) ) *2*M_PI) /
- (TILESIZE * exp(zoom * M_LN2) );
-
- return lon;
+ float x = exp(zoom * M_LN2) * TILESIZE;
+ return 2*M_PI * (pixel_x - (x / 2)) / x;
}
float
pixel2lat( float zoom,
int pixel_y)
{
- float lat, lat_m;
-
- lat_m = (-( pixel_y - ( exp(zoom * M_LN2) * (TILESIZE/2) ) ) * (2*M_PI)) /
- (TILESIZE * exp(zoom * M_LN2));
-
- lat = asin(tanh(lat_m));
-
- return lat;
+ float y = exp(zoom * M_LN2) * TILESIZE;
+ return asin(tanh(2*M_PI * ((y / 2) - pixel_y) / y));
}
int
@@ -126,7 +105,9 @@ latlon2zoom(int pix_height,
{
float lat1_m = atanh(sin(lat1));
float lat2_m = atanh(sin(lat2));
- int zoom_lon = LOG2((double)(2 * pix_width * M_PI) / (TILESIZE * (lon2 - lon1)));
- int zoom_lat = LOG2((double)(2 * pix_height * M_PI) / (TILESIZE * (lat2_m - lat1_m)));
+ float d_lon = (TILESIZE * (lon2 - lon1));
+ float d_lat = (TILESIZE * (lat2_m - lat1_m));
+ int zoom_lon = (d_lon) ? LOG2((double)(2*M_PI * pix_width ) / d_lon) : 1;
+ int zoom_lat = (d_lat) ? LOG2((double)(2*M_PI * pix_height) / d_lat) : 1;
return MIN(zoom_lon, zoom_lat);
}
diff --git a/src/osm-gps-map-widget.c b/src/osm-gps-map-widget.c
index e3158cd..a374aab 100644
--- a/src/osm-gps-map-widget.c
+++ b/src/osm-gps-map-widget.c
@@ -1122,8 +1122,8 @@ osm_gps_map_fill_tiles_pixel (OsmGpsMap *map, cairo_t *cr)
tiles_nx = (allocation.width - offset_x) / TILESIZE + 1;
tiles_ny = (allocation.height - offset_y) / TILESIZE + 1;
- tile_x0 = floorf((float)priv->map_x / (float)TILESIZE);
- tile_y0 = floorf((float)priv->map_y / (float)TILESIZE);
+ tile_x0 = priv->map_x / TILESIZE;
+ tile_y0 = priv->map_y / TILESIZE;
for (i=tile_x0; i<(tile_x0+tiles_nx);i++)
{
@@ -1491,10 +1491,10 @@ osm_gps_map_map_redraw (OsmGpsMap *map)
priv->redraw_cycle++;
- /* clear white background */
- w = gtk_widget_get_allocated_width (widget);
- h = gtk_widget_get_allocated_width (widget);
- draw_white_rectangle(cr, 0, 0, w + EXTRA_BORDER * 2, h + EXTRA_BORDER * 2);
+ ///* clear white background */
+ //w = gtk_widget_get_allocated_width (widget);
+ //h = gtk_widget_get_allocated_width (widget);
+ //draw_white_rectangle(cr, 0, 0, w + EXTRA_BORDER * 2, h + EXTRA_BORDER * 2);
osm_gps_map_fill_tiles_pixel(map, cr);
@@ -3117,8 +3117,8 @@ osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude)
pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
- priv->map_x = pixel_x - allocation.width/2;
- priv->map_y = pixel_y - allocation.height/2;
+ priv->map_x = pixel_x - (allocation.width >> 1);
+ priv->map_y = pixel_y - (allocation.height >> 1);
osm_gps_map_map_redraw_idle(map);
--
2.34.1
The text was updated successfully, but these errors were encountered:
Perhaps you're aware of the center-hopping issue: at certain points, when zooming in the map, the map center swaps between two positions, mostly between zoom levels 17, 18 and 19. (ie @ N0°0.0, E15°24.6065). This is due to a rounding issue computing float variables (6.5 digits accuracy), while the global map needs 7 digits accuracy.
I fixed this bug. But sorry, filing a pull request is over my head. So I post a patch here:
The text was updated successfully, but these errors were encountered: