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); };