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