From 6ae6d0b835ae41d2d3e0095079ce84d0cff0b297 Mon Sep 17 00:00:00 2001 From: mike-000 <49240900+mike-000@users.noreply.github.com> Date: Sat, 22 Feb 2020 22:40:29 +0000 Subject: [PATCH] Optional extra stops to refine extent transforms Add optional extra stops to refine some non-parallel transforms Refine extent transforms use by Gratucule by using 32 points (8 per side) instead of the standard corners only transform Update Graticule class description with current limitations Correct projection extent in Mollweide example and revise opening zoom level correspondingly --- examples/sphere-mollweide.js | 6 +++--- src/ol/extent.js | 38 +++++++++++++++++++++++++++--------- src/ol/layer/Graticule.js | 7 ++++--- src/ol/proj.js | 6 ++++-- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/examples/sphere-mollweide.js b/examples/sphere-mollweide.js index 7540cd095b..83fc6adcc4 100644 --- a/examples/sphere-mollweide.js +++ b/examples/sphere-mollweide.js @@ -17,8 +17,8 @@ register(proj4); // and a world extent. These are required for the Graticule. const sphereMollweideProjection = new Projection({ code: 'ESRI:53009', - extent: [-9009954.605703328, -9009954.605703328, - 9009954.605703328, 9009954.605703328], + extent: [-18019909.21177587, -9009954.605703328, + 18019909.21177587, 9009954.605703328], worldExtent: [-179, -89.99, 179, 89.99] }); @@ -37,6 +37,6 @@ const map = new Map({ view: new View({ center: [0, 0], projection: sphereMollweideProjection, - zoom: 0 + zoom: 1 }) }); diff --git a/src/ol/extent.js b/src/ol/extent.js index cc74b803fb..94eb9cb249 100644 --- a/src/ol/extent.js +++ b/src/ol/extent.js @@ -778,18 +778,38 @@ export function intersectsSegment(extent, start, end) { * @param {import("./proj.js").TransformFunction} transformFn Transform function. * Called with `[minX, minY, maxX, maxY]` extent coordinates. * @param {Extent=} opt_extent Destination extent. + * @param {number=} opt_stops Number of stops per side used for the transform. + * By default only the corners are used. * @return {Extent} Extent. * @api */ -export function applyTransform(extent, transformFn, opt_extent) { - const coordinates = [ - extent[0], extent[1], - extent[0], extent[3], - extent[2], extent[1], - extent[2], extent[3] - ]; +export function applyTransform(extent, transformFn, opt_extent, opt_stops) { + let coordinates = []; + if (opt_stops > 1) { + const width = extent[2] - extent[0]; + const height = extent[3] - extent[1]; + for (let i = 0; i < opt_stops; ++i) { + coordinates.push( + extent[0] + width * i / opt_stops, extent[1], + extent[2], extent[1] + height * i / opt_stops, + extent[2] - width * i / opt_stops, extent[3], + extent[0], extent[3] - height * i / opt_stops + ); + } + } else { + coordinates = [ + extent[0], extent[1], + extent[2], extent[1], + extent[2], extent[3], + extent[0], extent[3] + ]; + } transformFn(coordinates, coordinates, 2); - const xs = [coordinates[0], coordinates[2], coordinates[4], coordinates[6]]; - const ys = [coordinates[1], coordinates[3], coordinates[5], coordinates[7]]; + const xs = []; + const ys = []; + for (let i = 0, l = coordinates.length; i < l; i += 2) { + xs.push(coordinates[i]); + ys.push(coordinates[i + 1]); + } return _boundingExtentXYs(xs, ys, opt_extent); } diff --git a/src/ol/layer/Graticule.js b/src/ol/layer/Graticule.js index f1480dddc9..31e0f5aaee 100644 --- a/src/ol/layer/Graticule.js +++ b/src/ol/layer/Graticule.js @@ -144,7 +144,8 @@ const INTERVALS = [ /** * @classdesc - * Layer that renders a grid for a coordinate system. + * Layer that renders a grid for a coordinate system (currently only EPSG:4326 is supported). + * Note that the view projection must define both extent and worldExtent. * * @fires import("../render/Event.js").RenderEvent * @api @@ -677,7 +678,7 @@ class Graticule extends VectorLayer { Math.min(extent[3], this.maxLatP_) ]; - validExtent = transformExtent(validExtent, this.projection_, 'EPSG:4326'); + validExtent = transformExtent(validExtent, this.projection_, 'EPSG:4326', 8); const maxLat = validExtent[3]; const maxLon = validExtent[2]; const minLat = validExtent[1]; @@ -896,7 +897,7 @@ class Graticule extends VectorLayer { const epsg4326Projection = getProjection('EPSG:4326'); const worldExtent = projection.getWorldExtent(); - const worldExtentP = transformExtent(worldExtent, epsg4326Projection, projection); + const worldExtentP = transformExtent(worldExtent, epsg4326Projection, projection, 8); this.maxLat_ = worldExtent[3]; this.maxLon_ = worldExtent[2]; diff --git a/src/ol/proj.js b/src/ol/proj.js index f64cc05a85..d2be0feb3f 100644 --- a/src/ol/proj.js +++ b/src/ol/proj.js @@ -476,12 +476,14 @@ export function transform(coordinate, source, destination) { * @param {import("./extent.js").Extent} extent The extent to transform. * @param {ProjectionLike} source Source projection-like. * @param {ProjectionLike} destination Destination projection-like. + * @param {number=} opt_stops Number of stops per side used for the transform. + * By default only the corners are used. * @return {import("./extent.js").Extent} The transformed extent. * @api */ -export function transformExtent(extent, source, destination) { +export function transformExtent(extent, source, destination, opt_stops) { const transformFunc = getTransform(source, destination); - return applyTransform(extent, transformFunc); + return applyTransform(extent, transformFunc, undefined, opt_stops); }