From d2b05991772342cf1c9afbc8c6584f6b853a5223 Mon Sep 17 00:00:00 2001 From: philip Date: Tue, 14 Jan 2020 13:39:52 +0000 Subject: [PATCH 1/3] Dynamically chose the number of subdivisions based on the size of the Image. --- src/ol/reproj/Image.js | 2 +- src/ol/reproj/Tile.js | 2 +- src/ol/reproj/Triangulation.js | 11 ++++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ol/reproj/Image.js b/src/ol/reproj/Image.js index e08778002c..7a5cfd7240 100644 --- a/src/ol/reproj/Image.js +++ b/src/ol/reproj/Image.js @@ -47,7 +47,7 @@ class ReprojImage extends ImageBase { const triangulation = new Triangulation( sourceProj, targetProj, limitedTargetExtent, maxSourceExtent, - sourceResolution * errorThresholdInPixels); + sourceResolution * errorThresholdInPixels, targetResolution); const sourceExtent = triangulation.calculateSourceExtent(); const sourceImage = getImageFunction(sourceExtent, sourceResolution, pixelRatio); diff --git a/src/ol/reproj/Tile.js b/src/ol/reproj/Tile.js index 73d508d203..7defc9e48b 100644 --- a/src/ol/reproj/Tile.js +++ b/src/ol/reproj/Tile.js @@ -160,7 +160,7 @@ class ReprojTile extends Tile { */ this.triangulation_ = new Triangulation( sourceProj, targetProj, limitedTargetExtent, maxSourceExtent, - sourceResolution * errorThresholdInPixels); + sourceResolution * errorThresholdInPixels, targetResolution); if (this.triangulation_.getTriangles().length === 0) { // no valid triangles -> EMPTY diff --git a/src/ol/reproj/Triangulation.js b/src/ol/reproj/Triangulation.js index ebdab668da..fc75ce7a9c 100644 --- a/src/ol/reproj/Triangulation.js +++ b/src/ol/reproj/Triangulation.js @@ -1,7 +1,7 @@ /** * @module ol/reproj/Triangulation */ -import {boundingExtent, createEmpty, extendCoordinate, getBottomLeft, getBottomRight, +import {boundingExtent, createEmpty, extendCoordinate, getArea, getBottomLeft, getBottomRight, getTopLeft, getTopRight, getWidth, intersects} from '../extent.js'; import {modulo} from '../math.js'; import {getTransform} from '../proj.js'; @@ -49,8 +49,9 @@ class Triangulation { * @param {import("../extent.js").Extent} targetExtent Target extent to triangulate. * @param {import("../extent.js").Extent} maxSourceExtent Maximal source extent that can be used. * @param {number} errorThreshold Acceptable error (in source units). + * @param {number} destinationResolution The (optional) resolution of the destination. */ - constructor(sourceProj, targetProj, targetExtent, maxSourceExtent, errorThreshold) { + constructor(sourceProj, targetProj, targetExtent, maxSourceExtent, errorThreshold, destinationResolution) { /** * @type {import("../proj/Projection.js").default} @@ -138,11 +139,15 @@ class Triangulation { const sourceBottomRight = this.transformInv_(destinationBottomRight); const sourceBottomLeft = this.transformInv_(destinationBottomLeft); + const maxSubdivision = MAX_SUBDIVISION + (destinationResolution ? + Math.max(0, Math.ceil(Math.log2(getArea(targetExtent) / (destinationResolution * destinationResolution * 256 * 256)))) + : 0); + this.addQuad_( destinationTopLeft, destinationTopRight, destinationBottomRight, destinationBottomLeft, sourceTopLeft, sourceTopRight, sourceBottomRight, sourceBottomLeft, - MAX_SUBDIVISION); + maxSubdivision); if (this.wrapsXInSource_) { let leftBound = Infinity; From ccf3532eb2d4a42e818930dc44e63091dfd369e4 Mon Sep 17 00:00:00 2001 From: philip Date: Tue, 14 Jan 2020 13:48:23 +0000 Subject: [PATCH 2/3] Fix the parameter name to have the opt_ prefix. --- src/ol/reproj/Triangulation.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ol/reproj/Triangulation.js b/src/ol/reproj/Triangulation.js index fc75ce7a9c..b6091d149f 100644 --- a/src/ol/reproj/Triangulation.js +++ b/src/ol/reproj/Triangulation.js @@ -49,9 +49,9 @@ class Triangulation { * @param {import("../extent.js").Extent} targetExtent Target extent to triangulate. * @param {import("../extent.js").Extent} maxSourceExtent Maximal source extent that can be used. * @param {number} errorThreshold Acceptable error (in source units). - * @param {number} destinationResolution The (optional) resolution of the destination. + * @param {?number} opt_destinationResolution The (optional) resolution of the destination. */ - constructor(sourceProj, targetProj, targetExtent, maxSourceExtent, errorThreshold, destinationResolution) { + constructor(sourceProj, targetProj, targetExtent, maxSourceExtent, errorThreshold, opt_destinationResolution) { /** * @type {import("../proj/Projection.js").default} @@ -139,8 +139,9 @@ class Triangulation { const sourceBottomRight = this.transformInv_(destinationBottomRight); const sourceBottomLeft = this.transformInv_(destinationBottomLeft); - const maxSubdivision = MAX_SUBDIVISION + (destinationResolution ? - Math.max(0, Math.ceil(Math.log2(getArea(targetExtent) / (destinationResolution * destinationResolution * 256 * 256)))) + const maxSubdivision = MAX_SUBDIVISION + (opt_destinationResolution ? + Math.max(0, Math.ceil(Math.log2(getArea(targetExtent) / + (opt_destinationResolution * opt_destinationResolution * 256 * 256)))) : 0); this.addQuad_( From 72907566bbbb6f760e2fb7be02d22766ecf191cd Mon Sep 17 00:00:00 2001 From: philip Date: Thu, 2 Apr 2020 14:14:13 +0000 Subject: [PATCH 3/3] Add comment to explain calculation. --- src/ol/reproj/Triangulation.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ol/reproj/Triangulation.js b/src/ol/reproj/Triangulation.js index b6091d149f..ba49bac8c4 100644 --- a/src/ol/reproj/Triangulation.js +++ b/src/ol/reproj/Triangulation.js @@ -139,6 +139,16 @@ class Triangulation { const sourceBottomRight = this.transformInv_(destinationBottomRight); const sourceBottomLeft = this.transformInv_(destinationBottomLeft); + /* + * The maxSubdivision controls how many splittings of the target area can + * be done. The idea here is to do a linear mapping of the target areas + * but the actual overal reprojection (can be) extremely non-linear. The + * default value of MAX_SUBDIVISION was chosen based on mapping a 256x256 + * tile size. However this function is also called to remap canvas rendered + * layers which can be much larger. This calculation increases the maxSubdivision + * value by the right factor so that each 256x256 pixel area has + * MAX_SUBDIVISION divisions. + */ const maxSubdivision = MAX_SUBDIVISION + (opt_destinationResolution ? Math.max(0, Math.ceil(Math.log2(getArea(targetExtent) / (opt_destinationResolution * opt_destinationResolution * 256 * 256))))