nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

commit 6052331e8078776bc10148dd0b40ad21bb6f3e6f
parent e81ef8983b1cfe20e1136e1e5129da497edea69b
Author: Sergej Orlov <wladimirych@gmail.com>
Date:   Sun, 19 Mar 2017 17:06:26 +0300

[print/grid overlay] true (earth surface) scale for grid

Diffstat:
Msrc/lib/leaflet.control.printPages/decoration.grid.js | 67++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 56 insertions(+), 11 deletions(-)

diff --git a/src/lib/leaflet.control.printPages/decoration.grid.js b/src/lib/leaflet.control.printPages/decoration.grid.js @@ -1,4 +1,10 @@ import {PrintStaticLayer} from './decorations'; +import L from 'leaflet'; + + +function radians(degrees) { + return degrees * Math.PI / 180; +} class Grid extends PrintStaticLayer { lineThicknessMm = 0.2; @@ -11,10 +17,10 @@ class Grid extends PrintStaticLayer { intervals = [1, 1.5, 2, 3.3, 5, 7.5, 10, 15, 20, 33, 50, 75, 100, 150, 200, 333, 500, 750, - 1000, 1500, 2000, 3333, 5000, 7500, - 10000, 15000, 20000, 33333, 50000, 75000, - 100000, 150000, 200000, 333333, 500000, 750000, - 1000000, 1500000, 2000000, 3333333, 5000000, 7500000]; + 1000, 1500, 2000, 4000, 5000, 7500, + 10000, 15000, 20000, 40000, 50000, 75000, + 100000, 150000, 200000, 400000, 500000, 750000, + 1000000, 1500000, 2000000, 4000000, 5000000, 7500000]; getGridInterval(printOptions) { const minGridIntervalM = this.minGridIntervalMm / 10 * printOptions.scale; @@ -24,7 +30,7 @@ class Grid extends PrintStaticLayer { break } } - return {intervalM, intervalMm: intervalM / printOptions.scale * 10}; + return intervalM; } formatDistance(x) { @@ -42,23 +48,62 @@ class Grid extends PrintStaticLayer { } _drawRaster(canvas, printOptions) { + const metersPerDegree = L.Projection.SphericalMercator.R * Math.PI / 180; const ctx = canvas.getContext('2d'); ctx.beginPath(); const lineThickness = this.lineThicknessMm / 25.4 * printOptions.resolution; - const {intervalMm, intervalM} = this.getGridInterval(printOptions); - const intervalPx = intervalMm / 25.4 * printOptions.resolution; ctx.lineWidth = lineThickness; ctx.strokeStyle = '#ccc'; + + const intervalM = this.getGridInterval(printOptions); const width = printOptions.destPixelSize.x; const height = printOptions.destPixelSize.y; - for (let x = 0; x <= width; x += intervalPx) { - ctx.moveTo(x, 0); - ctx.lineTo(x, height); + const mercatorBounds = L.bounds( + L.Projection.SphericalMercator.project(printOptions.latLngBounds.getNorthWest()), + L.Projection.SphericalMercator.project(printOptions.latLngBounds.getSouthEast()) + ); + const canvasToMercatorScale = mercatorBounds.getSize().unscaleBy(printOptions.destPixelSize); + const rows = []; + let y = height; + while (true) { + let yMerc = mercatorBounds.max.y - y * canvasToMercatorScale.y; + let lat = L.Projection.SphericalMercator.unproject(L.point(0, yMerc)).lat; + rows.push({lat, y}); + if (y < 0) { + break + } + let lat2 = lat + intervalM / metersPerDegree; + let yMerc2 = L.Projection.SphericalMercator.project(L.latLng(lat2, 0)).y; + y = (mercatorBounds.max.y - yMerc2) / canvasToMercatorScale.y; } - for (let y = height; y >= 0; y -= intervalPx) { + for ({y} of rows) { ctx.moveTo(0, y); ctx.lineTo(width, y); } + const pageCanvasCenterX = printOptions.destPixelSize.x / 2; + for (let direction of [-1, 1]) { + let colN = 0; + while (true) { + let firstRow = true; + let hasPointInPage = false; + for (let {lat, y} of rows) { + let dx = colN * intervalM / Math.cos(radians(lat)) / canvasToMercatorScale.x; + if (dx < pageCanvasCenterX) { + hasPointInPage = true; + } + if (firstRow) { + ctx.moveTo(pageCanvasCenterX + dx * direction, y); + } else { + ctx.lineTo(pageCanvasCenterX + dx * direction, y); + } + firstRow = false; + } + if (!hasPointInPage) { + break + } + colN += 1; + } + } ctx.stroke(); const caption = 'Grid ' + this.formatDistance(intervalM);