Merge pull request #13383 from ahocevar/user-projection

User projection API
This commit is contained in:
Andreas Hocevar
2022-02-15 09:30:50 +01:00
committed by GitHub
7 changed files with 80 additions and 14 deletions
-1
View File
@@ -7,7 +7,6 @@ docs: >
makes it so the map view uses geographic coordinates (even if the view projection is makes it so the map view uses geographic coordinates (even if the view projection is
not geographic). not geographic).
tags: "geographic" tags: "geographic"
experimental: true
--- ---
<div id="map" class="map"></div> <div id="map" class="map"></div>
<select id="mode"> <select id="mode">
-1
View File
@@ -7,7 +7,6 @@ docs: >
makes it so the map view uses geographic coordinates (even if the view projection is makes it so the map view uses geographic coordinates (even if the view projection is
not geographic). not geographic).
tags: "geographic" tags: "geographic"
experimental: true
resources: resources:
- https://code.jquery.com/jquery-3.5.1.min.js - https://code.jquery.com/jquery-3.5.1.min.js
- https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css - https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css
-1
View File
@@ -10,6 +10,5 @@ docs: >
any geometry on each render frame. The `useGeographic` function is used in this example so that any geometry on each render frame. The `useGeographic` function is used in this example so that
geometries can be in geographic coordinates. geometries can be in geographic coordinates.
tags: "immediate, geographic" tags: "immediate, geographic"
experimental: true
--- ---
<div id="map" class="map"></div> <div id="map" class="map"></div>
-1
View File
@@ -11,6 +11,5 @@ tags: "geographic, vector, WFS, tile, strategy, loading, server, maptiler"
cloak: cloak:
- key: get_your_own_D6rA4zTHduk6KOKTXzGB - key: get_your_own_D6rA4zTHduk6KOKTXzGB
value: Get your own API key at https://www.maptiler.com/cloud/ value: Get your own API key at https://www.maptiler.com/cloud/
experimental: true
--- ---
<div id="map" class="map"></div> <div id="map" class="map"></div>
+5 -1
View File
@@ -10,6 +10,7 @@ import {DEFAULT_TILE_SIZE} from './tilegrid/common.js';
import { import {
METERS_PER_UNIT, METERS_PER_UNIT,
createProjection, createProjection,
disableCoordinateWarning,
fromUserCoordinate, fromUserCoordinate,
fromUserExtent, fromUserExtent,
getUserProjection, getUserProjection,
@@ -241,7 +242,7 @@ const DEFAULT_MIN_ZOOM = 0;
* A View has a `projection`. The projection determines the * A View has a `projection`. The projection determines the
* coordinate system of the center, and its units determine the units of the * coordinate system of the center, and its units determine the units of the
* resolution (projection units per pixel). The default projection is * resolution (projection units per pixel). The default projection is
* Spherical Mercator (EPSG:3857). * Web Mercator (EPSG:3857).
* *
* ### The view states * ### The view states
* *
@@ -406,6 +407,9 @@ class View extends BaseObject {
if (options.extent) { if (options.extent) {
options.extent = fromUserExtent(options.extent, this.projection_); options.extent = fromUserExtent(options.extent, this.projection_);
} }
if (options.projection) {
disableCoordinateWarning();
}
this.applyOptions_(options); this.applyOptions_(options);
} }
+34 -9
View File
@@ -73,8 +73,8 @@ import {
} from './proj/transforms.js'; } from './proj/transforms.js';
import {applyTransform, getWidth} from './extent.js'; import {applyTransform, getWidth} from './extent.js';
import {clamp, modulo} from './math.js'; import {clamp, modulo} from './math.js';
import {equals, getWorldsAway} from './coordinate.js';
import {getDistance} from './sphere.js'; import {getDistance} from './sphere.js';
import {getWorldsAway} from './coordinate.js';
/** /**
* A projection as {@link module:ol/proj/Projection}, SRS identifier * A projection as {@link module:ol/proj/Projection}, SRS identifier
@@ -97,6 +97,16 @@ export {METERS_PER_UNIT};
export {Projection}; export {Projection};
let showCoordinateWarning = true;
/**
* @param {boolean} [opt_disable = true] Disable console info about `useGeographic()`
*/
export function disableCoordinateWarning(opt_disable) {
const hide = opt_disable === undefined ? true : opt_disable;
showCoordinateWarning = !hide;
}
/** /**
* @param {Array<number>} input Input coordinate array. * @param {Array<number>} input Input coordinate array.
* @param {Array<number>} [opt_output] Output array of coordinate values. * @param {Array<number>} [opt_output] Output array of coordinate values.
@@ -386,6 +396,7 @@ export function addCoordinateTransforms(source, destination, forward, inverse) {
* @api * @api
*/ */
export function fromLonLat(coordinate, opt_projection) { export function fromLonLat(coordinate, opt_projection) {
disableCoordinateWarning();
return transform( return transform(
coordinate, coordinate,
'EPSG:4326', 'EPSG:4326',
@@ -539,18 +550,17 @@ let userProjection = null;
/** /**
* Set the projection for coordinates supplied from and returned by API methods. * Set the projection for coordinates supplied from and returned by API methods.
* Note that this method is not yet a part of the stable API. Support for user * This includes all API methods except for those interacting with tile grids.
* projections is not yet complete and should be considered experimental.
* @param {ProjectionLike} projection The user projection. * @param {ProjectionLike} projection The user projection.
* @api
*/ */
export function setUserProjection(projection) { export function setUserProjection(projection) {
userProjection = get(projection); userProjection = get(projection);
} }
/** /**
* Clear the user projection if set. Note that this method is not yet a part of * Clear the user projection if set.
* the stable API. Support for user projections is not yet complete and should * @api
* be considered experimental.
*/ */
export function clearUserProjection() { export function clearUserProjection() {
userProjection = null; userProjection = null;
@@ -561,15 +571,16 @@ export function clearUserProjection() {
* Note that this method is not yet a part of the stable API. Support for user * Note that this method is not yet a part of the stable API. Support for user
* projections is not yet complete and should be considered experimental. * projections is not yet complete and should be considered experimental.
* @return {Projection|null} The user projection (or null if not set). * @return {Projection|null} The user projection (or null if not set).
* @api
*/ */
export function getUserProjection() { export function getUserProjection() {
return userProjection; return userProjection;
} }
/** /**
* Use geographic coordinates (WGS-84 datum) in API methods. Note that this * Use geographic coordinates (WGS-84 datum) in API methods. This includes all API
* method is not yet a part of the stable API. Support for user projections is * methods except for those interacting with tile grids.
* not yet complete and should be considered experimental. * @api
*/ */
export function useGeographic() { export function useGeographic() {
setUserProjection('EPSG:4326'); setUserProjection('EPSG:4326');
@@ -598,6 +609,20 @@ export function toUserCoordinate(coordinate, sourceProjection) {
*/ */
export function fromUserCoordinate(coordinate, destProjection) { export function fromUserCoordinate(coordinate, destProjection) {
if (!userProjection) { if (!userProjection) {
if (
showCoordinateWarning &&
!equals(coordinate, [0, 0]) &&
coordinate[0] >= -180 &&
coordinate[0] <= 180 &&
coordinate[1] >= -90 &&
coordinate[1] <= 90
) {
showCoordinateWarning = false;
// eslint-disable-next-line no-console
console.warn(
'Call useGeographic() ol/proj once to work with [longitude, latitude] coordinates.'
);
}
return coordinate; return coordinate;
} }
return transform(coordinate, userProjection, destProjection); return transform(coordinate, userProjection, destProjection);
+41
View File
@@ -1,5 +1,6 @@
import Projection from '../../../src/ol/proj/Projection.js'; import Projection from '../../../src/ol/proj/Projection.js';
import Units from '../../../src/ol/proj/Units.js'; import Units from '../../../src/ol/proj/Units.js';
import View from '../../../src/ol/View.js';
import expect from '../expect.js'; import expect from '../expect.js';
import proj4 from 'proj4'; import proj4 from 'proj4';
import {HALF_SIZE} from '../../../src/ol/proj/epsg3857.js'; import {HALF_SIZE} from '../../../src/ol/proj/epsg3857.js';
@@ -8,6 +9,7 @@ import {
addCommon, addCommon,
clearAllProjections, clearAllProjections,
clearUserProjection, clearUserProjection,
disableCoordinateWarning,
equivalent, equivalent,
fromLonLat, fromLonLat,
fromUserCoordinate, fromUserCoordinate,
@@ -890,4 +892,43 @@ describe('ol/proj.js', function () {
); );
}); });
}); });
describe('Console info about `setUserProjection`', function () {
let originalConsole, callCount;
beforeEach(function () {
disableCoordinateWarning(false);
originalConsole = console;
callCount = 0;
global.console = {
...console,
warn: () => ++callCount,
};
});
afterEach(function () {
global.console = originalConsole;
clearUserProjection();
});
it('is shown once when suspicious coordinates are used', function () {
const view = new View({
center: [16, 48],
});
view.setCenter([15, 47]);
expect(callCount).to.be(1);
});
it('is not shown when fromLonLat() is used', function () {
const view = new View({
center: fromLonLat([16, 48]),
});
view.setCenter(fromLonLat([15, 47]));
expect(callCount).to.be(0);
});
it('is not shown when useGeographic() is used', function () {
useGeographic();
const view = new View({
center: [16, 48],
});
view.setCenter([15, 47]);
expect(callCount).to.be(0);
});
});
}); });