diff --git a/apps.json b/apps.json
index 0a1fd3039..a312b90a3 100644
--- a/apps.json
+++ b/apps.json
@@ -1928,7 +1928,7 @@
"id": "openstmap",
"name": "OpenStreetMap",
"shortName": "OpenStMap",
- "version": "0.09",
+ "version": "0.10",
"description": "[BETA] Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are",
"icon": "app.png",
"tags": "outdoors,gps",
diff --git a/apps/openstmap/ChangeLog b/apps/openstmap/ChangeLog
index 60b9d9ae3..69c34ed4e 100644
--- a/apps/openstmap/ChangeLog
+++ b/apps/openstmap/ChangeLog
@@ -7,3 +7,4 @@
0.07: Move to 96px tiles - less files (64 -> 25) and speed up rendering
0.08: Update for drag event refactor
0.09: Use current theme cols when drawing GPS info
+0.10: Improve scale factor calculation to fix scaling issues (#984)
diff --git a/apps/openstmap/custom.html b/apps/openstmap/custom.html
index 88d94ed37..eeb148f54 100644
--- a/apps/openstmap/custom.html
+++ b/apps/openstmap/custom.html
@@ -63,10 +63,17 @@ TODO:
/* Can see possible tiles on http://leaflet-extras.github.io/leaflet-providers/preview/
However some don't allow cross-origin use */
var TILELAYER = 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'; // simple, high contrast
- //var TILELAYER = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
+ var PREVIEWTILELAYER = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
//var TILELAYER = 'http://a.tile.stamen.com/toner/{z}/{x}/{y}.png'; // black and white
+
var map = L.map('map').locate({setView: true, maxZoom: 16});
- var tileLayer = L.tileLayer(TILELAYER, {
+ // Tiles used for Bangle.js itself
+ var bangleTileLayer = L.tileLayer(TILELAYER, {
+ maxZoom: 18,
+ attribution: 'Map data © OpenStreetMap contributors'
+ });
+ // Tiles used for the may the user sees (faster)
+ var previewTileLayer = L.tileLayer(PREVIEWTILELAYER, {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors'
});
@@ -83,7 +90,7 @@ TODO:
}
var mapFiles = [];
- tileLayer.addTo(map);
+ previewTileLayer.addTo(map);
function tilesLoaded(ctx, width, height) {
var options = {
@@ -122,16 +129,35 @@ TODO:
}
document.getElementById("getmap").addEventListener("click", function() {
- var bounds = map.getBounds();
var zoom = map.getZoom();
- var centerlatlon = bounds.getCenter();
- var center = map.project(centerlatlon, zoom).divideBy(256);
+ var centerlatlon = map.getBounds().getCenter();
+ var center = map.project(centerlatlon, zoom).divideBy(OSMTILESIZE);
var ox = Math.round((center.x - Math.floor(center.x)) * OSMTILESIZE);
var oy = Math.round((center.y - Math.floor(center.y)) * OSMTILESIZE);
- center = center.floor();
+ center = center.floor(); // make sure we're in the middle of a tile
+ // JS version of Bangle.js's projection
+ function bproject(lat, lon) {
+ const degToRad = Math.PI / 180; // degree to radian conversion
+ const latMax = 85.0511287798; // clip latitude to sane values
+ const R = 6378137; // earth radius in m
+ if (lat > latMax) lat=latMax;
+ if (lat < -latMax) lat=-latMax;
+ var s = Math.sin(lat * degToRad);
+ return new L.Point(
+ (R * lon * degToRad),
+ (R * Math.log((1 + s) / (1 - s)) / 2)
+ );
+ }
+ // Work out scale factors (how much from Bangle.project does one pixel equate to?)
+ var pc = map.unproject(center.multiplyBy(OSMTILESIZE), zoom);
+ var pd = map.unproject(center.multiplyBy(OSMTILESIZE).add({x:1,y:0}), zoom);
+ var bc = bproject(pc.lat, pc.lng)
+ var bd = bproject(pd.lat, pd.lng)
+ var scale = bc.distanceTo(bd);
+
var tileGetters = [];
- // Render everything to a canvas - 512 x 512 px
+ // Render everything to a canvas...
var canvas = document.getElementById("maptiles");
canvas.style.display="";
var ctx = canvas.getContext('2d');
@@ -150,7 +176,8 @@ TODO:
resolve();
};
}));
- img.src = tileLayer.getTileUrl(coords);
+ bangleTileLayer._tileZoom = previewTileLayer._tileZoom;
+ img.src = bangleTileLayer.getTileUrl(coords);
})(i,j);
}
}
@@ -163,7 +190,7 @@ TODO:
imgx : canvas.width,
imgy : canvas.height,
tilesize : TILESIZE,
- scale : 10000*Math.pow(2,16-zoom), // FIXME - this is probably wrong
+ scale : scale, // how much of Bangle.project(latlon) does one pixel equate to?
lat : centerlatlon.lat,
lon : centerlatlon.lng
})});
diff --git a/apps/openstmap/openstmap.js b/apps/openstmap/openstmap.js
index 554a71ca3..d995aca25 100644
--- a/apps/openstmap/openstmap.js
+++ b/apps/openstmap/openstmap.js
@@ -34,8 +34,8 @@ exports.draw = function() {
var cx = g.getWidth()/2;
var cy = g.getHeight()/2;
var p = Bangle.project({lat:m.lat,lon:m.lon});
- var ix = (p.x-map.center.x)*4096/map.scale + (map.imgx/2) - cx;
- var iy = (map.center.y-p.y)*4096/map.scale + (map.imgy/2) - cy;
+ var ix = (p.x-map.center.x)/map.scale + (map.imgx/2) - cx;
+ var iy = (map.center.y-p.y)/map.scale + (map.imgy/2) - cy;
//console.log(ix,iy);
var tx = 0|(ix/map.tilesize);
var ty = 0|(iy/map.tilesize);
@@ -57,8 +57,8 @@ exports.latLonToXY = function(lat, lon) {
var cx = g.getWidth()/2;
var cy = g.getHeight()/2;
return {
- x : (q.x-p.x)*4096/map.scale + cx,
- y : cy - (q.y-p.y)*4096/map.scale
+ x : (q.x-p.x)/map.scale + cx,
+ y : cy - (q.y-p.y)/map.scale
};
};
@@ -66,6 +66,6 @@ exports.latLonToXY = function(lat, lon) {
exports.scroll = function(x,y) {
var a = Bangle.project({lat:this.lat,lon:this.lon});
var b = Bangle.project({lat:this.lat+1,lon:this.lon+1});
- this.lon += x * this.map.scale / ((a.x-b.x) * 4096);
- this.lat -= y * this.map.scale / ((a.y-b.y) * 4096);
+ this.lon += x * this.map.scale / (a.x-b.x);
+ this.lat -= y * this.map.scale / (a.y-b.y);
};