This commit is contained in:
46
node_modules/ol/src/AssertionError.js
generated
vendored
Normal file
46
node_modules/ol/src/AssertionError.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @module ol/AssertionError
|
||||
*/
|
||||
import {VERSION} from './util.js';
|
||||
|
||||
/**
|
||||
* Error object thrown when an assertion failed. This is an ECMA-262 Error,
|
||||
* extended with a `code` property.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error.
|
||||
*/
|
||||
class AssertionError extends Error {
|
||||
/**
|
||||
* @param {number} code Error code.
|
||||
*/
|
||||
constructor(code) {
|
||||
const path = VERSION === 'latest' ? VERSION : 'v' + VERSION.split('-')[0];
|
||||
const message =
|
||||
'Assertion failed. See https://openlayers.org/en/' +
|
||||
path +
|
||||
'/doc/errors/#' +
|
||||
code +
|
||||
' for details.';
|
||||
|
||||
super(message);
|
||||
|
||||
/**
|
||||
* Error code. The meaning of the code can be found on
|
||||
* https://openlayers.org/en/latest/doc/errors/ (replace `latest` with
|
||||
* the version found in the OpenLayers script's header comment if a version
|
||||
* other than the latest is used).
|
||||
* @type {number}
|
||||
* @api
|
||||
*/
|
||||
this.code = code;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = 'AssertionError';
|
||||
|
||||
// Re-assign message, see https://github.com/Rich-Harris/buble/issues/40
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
export default AssertionError;
|
||||
315
node_modules/ol/src/Collection.js
generated
vendored
Normal file
315
node_modules/ol/src/Collection.js
generated
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
/**
|
||||
* @module ol/Collection
|
||||
*/
|
||||
import AssertionError from './AssertionError.js';
|
||||
import BaseObject from './Object.js';
|
||||
import CollectionEventType from './CollectionEventType.js';
|
||||
import Event from './events/Event.js';
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
* @private
|
||||
*/
|
||||
const Property = {
|
||||
LENGTH: 'length',
|
||||
};
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted by {@link module:ol/Collection~Collection} instances are instances of this
|
||||
* type.
|
||||
*/
|
||||
export class CollectionEvent extends Event {
|
||||
/**
|
||||
* @param {import("./CollectionEventType.js").default} type Type.
|
||||
* @param {*} [opt_element] Element.
|
||||
* @param {number} [opt_index] The index of the added or removed element.
|
||||
*/
|
||||
constructor(type, opt_element, opt_index) {
|
||||
super(type);
|
||||
|
||||
/**
|
||||
* The element that is added to or removed from the collection.
|
||||
* @type {*}
|
||||
* @api
|
||||
*/
|
||||
this.element = opt_element;
|
||||
|
||||
/**
|
||||
* The index of the added or removed element.
|
||||
* @type {number}
|
||||
* @api
|
||||
*/
|
||||
this.index = opt_index;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {import("./Observable").OnSignature<import("./Observable").EventTypes, import("./events/Event.js").default, Return> &
|
||||
* import("./Observable").OnSignature<import("./ObjectEventType").Types|'change:length', import("./Object").ObjectEvent, Return> &
|
||||
* import("./Observable").OnSignature<'add'|'remove', CollectionEvent, Return> &
|
||||
* import("./Observable").CombinedOnSignature<import("./Observable").EventTypes|import("./ObjectEventType").Types|
|
||||
* 'change:length'|'add'|'remove',Return>} CollectionOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {boolean} [unique=false] Disallow the same item from being added to
|
||||
* the collection twice.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* An expanded version of standard JS Array, adding convenience methods for
|
||||
* manipulation. Add and remove changes to the Collection trigger a Collection
|
||||
* event. Note that this does not cover changes to the objects _within_ the
|
||||
* Collection; they trigger events on the appropriate object, not on the
|
||||
* Collection as a whole.
|
||||
*
|
||||
* @fires CollectionEvent
|
||||
*
|
||||
* @template T
|
||||
* @api
|
||||
*/
|
||||
class Collection extends BaseObject {
|
||||
/**
|
||||
* @param {Array<T>} [opt_array] Array.
|
||||
* @param {Options} [opt_options] Collection options.
|
||||
*/
|
||||
constructor(opt_array, opt_options) {
|
||||
super();
|
||||
|
||||
/***
|
||||
* @type {CollectionOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.on;
|
||||
|
||||
/***
|
||||
* @type {CollectionOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.once;
|
||||
|
||||
/***
|
||||
* @type {CollectionOnSignature<void>}
|
||||
*/
|
||||
this.un;
|
||||
|
||||
const options = opt_options || {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.unique_ = !!options.unique;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Array<T>}
|
||||
*/
|
||||
this.array_ = opt_array ? opt_array : [];
|
||||
|
||||
if (this.unique_) {
|
||||
for (let i = 0, ii = this.array_.length; i < ii; ++i) {
|
||||
this.assertUnique_(this.array_[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
this.updateLength_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements from the collection.
|
||||
* @api
|
||||
*/
|
||||
clear() {
|
||||
while (this.getLength() > 0) {
|
||||
this.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add elements to the collection. This pushes each item in the provided array
|
||||
* to the end of the collection.
|
||||
* @param {!Array<T>} arr Array.
|
||||
* @return {Collection<T>} This collection.
|
||||
* @api
|
||||
*/
|
||||
extend(arr) {
|
||||
for (let i = 0, ii = arr.length; i < ii; ++i) {
|
||||
this.push(arr[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over each element, calling the provided callback.
|
||||
* @param {function(T, number, Array<T>): *} f The function to call
|
||||
* for every element. This function takes 3 arguments (the element, the
|
||||
* index and the array). The return value is ignored.
|
||||
* @api
|
||||
*/
|
||||
forEach(f) {
|
||||
const array = this.array_;
|
||||
for (let i = 0, ii = array.length; i < ii; ++i) {
|
||||
f(array[i], i, array);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the underlying Array object. Warning: if the array
|
||||
* is mutated, no events will be dispatched by the collection, and the
|
||||
* collection's "length" property won't be in sync with the actual length
|
||||
* of the array.
|
||||
* @return {!Array<T>} Array.
|
||||
* @api
|
||||
*/
|
||||
getArray() {
|
||||
return this.array_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element at the provided index.
|
||||
* @param {number} index Index.
|
||||
* @return {T} Element.
|
||||
* @api
|
||||
*/
|
||||
item(index) {
|
||||
return this.array_[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of this collection.
|
||||
* @return {number} The length of the array.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getLength() {
|
||||
return this.get(Property.LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the provided index.
|
||||
* @param {number} index Index.
|
||||
* @param {T} elem Element.
|
||||
* @api
|
||||
*/
|
||||
insertAt(index, elem) {
|
||||
if (this.unique_) {
|
||||
this.assertUnique_(elem);
|
||||
}
|
||||
this.array_.splice(index, 0, elem);
|
||||
this.updateLength_();
|
||||
this.dispatchEvent(
|
||||
new CollectionEvent(CollectionEventType.ADD, elem, index)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the last element of the collection and return it.
|
||||
* Return `undefined` if the collection is empty.
|
||||
* @return {T|undefined} Element.
|
||||
* @api
|
||||
*/
|
||||
pop() {
|
||||
return this.removeAt(this.getLength() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the provided element at the end of the collection.
|
||||
* @param {T} elem Element.
|
||||
* @return {number} New length of the collection.
|
||||
* @api
|
||||
*/
|
||||
push(elem) {
|
||||
if (this.unique_) {
|
||||
this.assertUnique_(elem);
|
||||
}
|
||||
const n = this.getLength();
|
||||
this.insertAt(n, elem);
|
||||
return this.getLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the first occurrence of an element from the collection.
|
||||
* @param {T} elem Element.
|
||||
* @return {T|undefined} The removed element or undefined if none found.
|
||||
* @api
|
||||
*/
|
||||
remove(elem) {
|
||||
const arr = this.array_;
|
||||
for (let i = 0, ii = arr.length; i < ii; ++i) {
|
||||
if (arr[i] === elem) {
|
||||
return this.removeAt(i);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the element at the provided index and return it.
|
||||
* Return `undefined` if the collection does not contain this index.
|
||||
* @param {number} index Index.
|
||||
* @return {T|undefined} Value.
|
||||
* @api
|
||||
*/
|
||||
removeAt(index) {
|
||||
const prev = this.array_[index];
|
||||
this.array_.splice(index, 1);
|
||||
this.updateLength_();
|
||||
this.dispatchEvent(
|
||||
new CollectionEvent(CollectionEventType.REMOVE, prev, index)
|
||||
);
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the element at the provided index.
|
||||
* @param {number} index Index.
|
||||
* @param {T} elem Element.
|
||||
* @api
|
||||
*/
|
||||
setAt(index, elem) {
|
||||
const n = this.getLength();
|
||||
if (index < n) {
|
||||
if (this.unique_) {
|
||||
this.assertUnique_(elem, index);
|
||||
}
|
||||
const prev = this.array_[index];
|
||||
this.array_[index] = elem;
|
||||
this.dispatchEvent(
|
||||
new CollectionEvent(CollectionEventType.REMOVE, prev, index)
|
||||
);
|
||||
this.dispatchEvent(
|
||||
new CollectionEvent(CollectionEventType.ADD, elem, index)
|
||||
);
|
||||
} else {
|
||||
for (let j = n; j < index; ++j) {
|
||||
this.insertAt(j, undefined);
|
||||
}
|
||||
this.insertAt(index, elem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
updateLength_() {
|
||||
this.set(Property.LENGTH, this.array_.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {T} elem Element.
|
||||
* @param {number} [opt_except] Optional index to ignore.
|
||||
*/
|
||||
assertUnique_(elem, opt_except) {
|
||||
for (let i = 0, ii = this.array_.length; i < ii; ++i) {
|
||||
if (this.array_[i] === elem && i !== opt_except) {
|
||||
throw new AssertionError(58);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Collection;
|
||||
21
node_modules/ol/src/CollectionEventType.js
generated
vendored
Normal file
21
node_modules/ol/src/CollectionEventType.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @module ol/CollectionEventType
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Triggered when an item is added to the collection.
|
||||
* @event module:ol/Collection.CollectionEvent#add
|
||||
* @api
|
||||
*/
|
||||
ADD: 'add',
|
||||
/**
|
||||
* Triggered when an item is removed from the collection.
|
||||
* @event module:ol/Collection.CollectionEvent#remove
|
||||
* @api
|
||||
*/
|
||||
REMOVE: 'remove',
|
||||
};
|
||||
114
node_modules/ol/src/DataTile.js
generated
vendored
Normal file
114
node_modules/ol/src/DataTile.js
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* @module ol/DataTile
|
||||
*/
|
||||
import Tile from './Tile.js';
|
||||
import TileState from './TileState.js';
|
||||
|
||||
/**
|
||||
* Data that can be used with a DataTile. For increased browser compatibility, use
|
||||
* Uint8Array instead of Uint8ClampedArray where possible.
|
||||
* @typedef {Uint8Array|Uint8ClampedArray|Float32Array|DataView} Data
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||
* @property {function(): Promise<Data>} loader Data loader.
|
||||
* @property {number} [transition=250] A duration for tile opacity
|
||||
* transitions in milliseconds. A duration of 0 disables the opacity transition.
|
||||
* @property {boolean} [interpolate=false] Use interpolated values when resampling. By default,
|
||||
* the nearest neighbor is used when resampling.
|
||||
* @property {import('./size.js').Size} [size=[256, 256]] Tile size.
|
||||
* @api
|
||||
*/
|
||||
|
||||
class DataTile extends Tile {
|
||||
/**
|
||||
* @param {Options} options Tile options.
|
||||
*/
|
||||
constructor(options) {
|
||||
const state = TileState.IDLE;
|
||||
|
||||
super(options.tileCoord, state, {
|
||||
transition: options.transition,
|
||||
interpolate: options.interpolate,
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {function(): Promise<Data>}
|
||||
* @private
|
||||
*/
|
||||
this.loader_ = options.loader;
|
||||
|
||||
/**
|
||||
* @type {Data}
|
||||
* @private
|
||||
*/
|
||||
this.data_ = null;
|
||||
|
||||
/**
|
||||
* @type {Error}
|
||||
* @private
|
||||
*/
|
||||
this.error_ = null;
|
||||
|
||||
/**
|
||||
* @type {import('./size.js').Size}
|
||||
* @private
|
||||
*/
|
||||
this.size_ = options.size || [256, 256];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tile size.
|
||||
* @return {import('./size.js').Size} Tile size.
|
||||
*/
|
||||
getSize() {
|
||||
return this.size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data for the tile.
|
||||
* @return {Data} Tile data.
|
||||
* @api
|
||||
*/
|
||||
getData() {
|
||||
return this.data_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any loading error.
|
||||
* @return {Error} Loading error.
|
||||
* @api
|
||||
*/
|
||||
getError() {
|
||||
return this.error_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load not yet loaded URI.
|
||||
* @api
|
||||
*/
|
||||
load() {
|
||||
if (this.state !== TileState.IDLE && this.state !== TileState.ERROR) {
|
||||
return;
|
||||
}
|
||||
this.state = TileState.LOADING;
|
||||
this.changed();
|
||||
|
||||
const self = this;
|
||||
this.loader_()
|
||||
.then(function (data) {
|
||||
self.data_ = data;
|
||||
self.state = TileState.LOADED;
|
||||
self.changed();
|
||||
})
|
||||
.catch(function (error) {
|
||||
self.error_ = error;
|
||||
self.state = TileState.ERROR;
|
||||
self.changed();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default DataTile;
|
||||
36
node_modules/ol/src/Disposable.js
generated
vendored
Normal file
36
node_modules/ol/src/Disposable.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @module ol/Disposable
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Objects that need to clean up after themselves.
|
||||
*/
|
||||
class Disposable {
|
||||
constructor() {
|
||||
/**
|
||||
* The object has already been disposed.
|
||||
* @type {boolean}
|
||||
* @protected
|
||||
*/
|
||||
this.disposed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up.
|
||||
*/
|
||||
dispose() {
|
||||
if (!this.disposed) {
|
||||
this.disposed = true;
|
||||
this.disposeInternal();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension point for disposable objects.
|
||||
* @protected
|
||||
*/
|
||||
disposeInternal() {}
|
||||
}
|
||||
|
||||
export default Disposable;
|
||||
337
node_modules/ol/src/Feature.js
generated
vendored
Normal file
337
node_modules/ol/src/Feature.js
generated
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
/**
|
||||
* @module ol/Feature
|
||||
*/
|
||||
import BaseObject from './Object.js';
|
||||
import EventType from './events/EventType.js';
|
||||
import {assert} from './asserts.js';
|
||||
import {listen, unlistenByKey} from './events.js';
|
||||
|
||||
/**
|
||||
* @typedef {typeof Feature|typeof import("./render/Feature.js").default} FeatureClass
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Feature|import("./render/Feature.js").default} FeatureLike
|
||||
*/
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {import("./Observable").OnSignature<import("./Observable").EventTypes, import("./events/Event.js").default, Return> &
|
||||
* import("./Observable").OnSignature<import("./ObjectEventType").Types|'change:geometry', import("./Object").ObjectEvent, Return> &
|
||||
* import("./Observable").CombinedOnSignature<import("./Observable").EventTypes|import("./ObjectEventType").Types
|
||||
* |'change:geometry', Return>} FeatureOnSignature
|
||||
*/
|
||||
|
||||
/***
|
||||
* @template Geometry
|
||||
* @typedef {Object<string, *> & { geometry?: Geometry }} ObjectWithGeometry
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A vector object for geographic features with a geometry and other
|
||||
* attribute properties, similar to the features in vector file formats like
|
||||
* GeoJSON.
|
||||
*
|
||||
* Features can be styled individually with `setStyle`; otherwise they use the
|
||||
* style of their vector layer.
|
||||
*
|
||||
* Note that attribute properties are set as {@link module:ol/Object~BaseObject} properties on
|
||||
* the feature object, so they are observable, and have get/set accessors.
|
||||
*
|
||||
* Typically, a feature has a single geometry property. You can set the
|
||||
* geometry using the `setGeometry` method and get it with `getGeometry`.
|
||||
* It is possible to store more than one geometry on a feature using attribute
|
||||
* properties. By default, the geometry used for rendering is identified by
|
||||
* the property name `geometry`. If you want to use another geometry property
|
||||
* for rendering, use the `setGeometryName` method to change the attribute
|
||||
* property associated with the geometry for the feature. For example:
|
||||
*
|
||||
* ```js
|
||||
*
|
||||
* import Feature from 'ol/Feature';
|
||||
* import Polygon from 'ol/geom/Polygon';
|
||||
* import Point from 'ol/geom/Point';
|
||||
*
|
||||
* var feature = new Feature({
|
||||
* geometry: new Polygon(polyCoords),
|
||||
* labelPoint: new Point(labelCoords),
|
||||
* name: 'My Polygon'
|
||||
* });
|
||||
*
|
||||
* // get the polygon geometry
|
||||
* var poly = feature.getGeometry();
|
||||
*
|
||||
* // Render the feature as a point using the coordinates from labelPoint
|
||||
* feature.setGeometryName('labelPoint');
|
||||
*
|
||||
* // get the point geometry
|
||||
* var point = feature.getGeometry();
|
||||
* ```
|
||||
*
|
||||
* @api
|
||||
* @template {import("./geom/Geometry.js").default} [Geometry=import("./geom/Geometry.js").default]
|
||||
*/
|
||||
class Feature extends BaseObject {
|
||||
/**
|
||||
* @param {Geometry|ObjectWithGeometry<Geometry>} [opt_geometryOrProperties]
|
||||
* You may pass a Geometry object directly, or an object literal containing
|
||||
* properties. If you pass an object literal, you may include a Geometry
|
||||
* associated with a `geometry` key.
|
||||
*/
|
||||
constructor(opt_geometryOrProperties) {
|
||||
super();
|
||||
|
||||
/***
|
||||
* @type {FeatureOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.on;
|
||||
|
||||
/***
|
||||
* @type {FeatureOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.once;
|
||||
|
||||
/***
|
||||
* @type {FeatureOnSignature<void>}
|
||||
*/
|
||||
this.un;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|string|undefined}
|
||||
*/
|
||||
this.id_ = undefined;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.geometryName_ = 'geometry';
|
||||
|
||||
/**
|
||||
* User provided style.
|
||||
* @private
|
||||
* @type {import("./style/Style.js").StyleLike}
|
||||
*/
|
||||
this.style_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./style/Style.js").StyleFunction|undefined}
|
||||
*/
|
||||
this.styleFunction_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?import("./events.js").EventsKey}
|
||||
*/
|
||||
this.geometryChangeKey_ = null;
|
||||
|
||||
this.addChangeListener(this.geometryName_, this.handleGeometryChanged_);
|
||||
|
||||
if (opt_geometryOrProperties) {
|
||||
if (
|
||||
typeof (
|
||||
/** @type {?} */ (opt_geometryOrProperties).getSimplifiedGeometry
|
||||
) === 'function'
|
||||
) {
|
||||
const geometry = /** @type {Geometry} */ (opt_geometryOrProperties);
|
||||
this.setGeometry(geometry);
|
||||
} else {
|
||||
/** @type {Object<string, *>} */
|
||||
const properties = opt_geometryOrProperties;
|
||||
this.setProperties(properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this feature. If the original feature has a geometry it
|
||||
* is also cloned. The feature id is not set in the clone.
|
||||
* @return {Feature<Geometry>} The clone.
|
||||
* @api
|
||||
*/
|
||||
clone() {
|
||||
const clone = /** @type {Feature<Geometry>} */ (
|
||||
new Feature(this.hasProperties() ? this.getProperties() : null)
|
||||
);
|
||||
clone.setGeometryName(this.getGeometryName());
|
||||
const geometry = this.getGeometry();
|
||||
if (geometry) {
|
||||
clone.setGeometry(/** @type {Geometry} */ (geometry.clone()));
|
||||
}
|
||||
const style = this.getStyle();
|
||||
if (style) {
|
||||
clone.setStyle(style);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the feature's default geometry. A feature may have any number of named
|
||||
* geometries. The "default" geometry (the one that is rendered by default) is
|
||||
* set when calling {@link module:ol/Feature~Feature#setGeometry}.
|
||||
* @return {Geometry|undefined} The default geometry for the feature.
|
||||
* @api
|
||||
* @observable
|
||||
*/
|
||||
getGeometry() {
|
||||
return /** @type {Geometry|undefined} */ (this.get(this.geometryName_));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the feature identifier. This is a stable identifier for the feature and
|
||||
* is either set when reading data from a remote source or set explicitly by
|
||||
* calling {@link module:ol/Feature~Feature#setId}.
|
||||
* @return {number|string|undefined} Id.
|
||||
* @api
|
||||
*/
|
||||
getId() {
|
||||
return this.id_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the feature's default geometry. By default, the default
|
||||
* geometry is named `geometry`.
|
||||
* @return {string} Get the property name associated with the default geometry
|
||||
* for this feature.
|
||||
* @api
|
||||
*/
|
||||
getGeometryName() {
|
||||
return this.geometryName_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the feature's style. Will return what was provided to the
|
||||
* {@link module:ol/Feature~Feature#setStyle} method.
|
||||
* @return {import("./style/Style.js").StyleLike|undefined} The feature style.
|
||||
* @api
|
||||
*/
|
||||
getStyle() {
|
||||
return this.style_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the feature's style function.
|
||||
* @return {import("./style/Style.js").StyleFunction|undefined} Return a function
|
||||
* representing the current style of this feature.
|
||||
* @api
|
||||
*/
|
||||
getStyleFunction() {
|
||||
return this.styleFunction_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleGeometryChange_() {
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleGeometryChanged_() {
|
||||
if (this.geometryChangeKey_) {
|
||||
unlistenByKey(this.geometryChangeKey_);
|
||||
this.geometryChangeKey_ = null;
|
||||
}
|
||||
const geometry = this.getGeometry();
|
||||
if (geometry) {
|
||||
this.geometryChangeKey_ = listen(
|
||||
geometry,
|
||||
EventType.CHANGE,
|
||||
this.handleGeometryChange_,
|
||||
this
|
||||
);
|
||||
}
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default geometry for the feature. This will update the property
|
||||
* with the name returned by {@link module:ol/Feature~Feature#getGeometryName}.
|
||||
* @param {Geometry|undefined} geometry The new geometry.
|
||||
* @api
|
||||
* @observable
|
||||
*/
|
||||
setGeometry(geometry) {
|
||||
this.set(this.geometryName_, geometry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the style for the feature to override the layer style. This can be a
|
||||
* single style object, an array of styles, or a function that takes a
|
||||
* resolution and returns an array of styles. To unset the feature style, call
|
||||
* `setStyle()` without arguments or a falsey value.
|
||||
* @param {import("./style/Style.js").StyleLike} [opt_style] Style for this feature.
|
||||
* @api
|
||||
* @fires module:ol/events/Event~BaseEvent#event:change
|
||||
*/
|
||||
setStyle(opt_style) {
|
||||
this.style_ = opt_style;
|
||||
this.styleFunction_ = !opt_style
|
||||
? undefined
|
||||
: createStyleFunction(opt_style);
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the feature id. The feature id is considered stable and may be used when
|
||||
* requesting features or comparing identifiers returned from a remote source.
|
||||
* The feature id can be used with the
|
||||
* {@link module:ol/source/Vector~VectorSource#getFeatureById} method.
|
||||
* @param {number|string|undefined} id The feature id.
|
||||
* @api
|
||||
* @fires module:ol/events/Event~BaseEvent#event:change
|
||||
*/
|
||||
setId(id) {
|
||||
this.id_ = id;
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the property name to be used when getting the feature's default geometry.
|
||||
* When calling {@link module:ol/Feature~Feature#getGeometry}, the value of the property with
|
||||
* this name will be returned.
|
||||
* @param {string} name The property name of the default geometry.
|
||||
* @api
|
||||
*/
|
||||
setGeometryName(name) {
|
||||
this.removeChangeListener(this.geometryName_, this.handleGeometryChanged_);
|
||||
this.geometryName_ = name;
|
||||
this.addChangeListener(this.geometryName_, this.handleGeometryChanged_);
|
||||
this.handleGeometryChanged_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the provided object into a feature style function. Functions passed
|
||||
* through unchanged. Arrays of Style or single style objects wrapped
|
||||
* in a new feature style function.
|
||||
* @param {!import("./style/Style.js").StyleFunction|!Array<import("./style/Style.js").default>|!import("./style/Style.js").default} obj
|
||||
* A feature style function, a single style, or an array of styles.
|
||||
* @return {import("./style/Style.js").StyleFunction} A style function.
|
||||
*/
|
||||
export function createStyleFunction(obj) {
|
||||
if (typeof obj === 'function') {
|
||||
return obj;
|
||||
} else {
|
||||
/**
|
||||
* @type {Array<import("./style/Style.js").default>}
|
||||
*/
|
||||
let styles;
|
||||
if (Array.isArray(obj)) {
|
||||
styles = obj;
|
||||
} else {
|
||||
assert(typeof (/** @type {?} */ (obj).getZIndex) === 'function', 41); // Expected an `import("./style/Style.js").Style` or an array of `import("./style/Style.js").Style`
|
||||
const style = /** @type {import("./style/Style.js").default} */ (obj);
|
||||
styles = [style];
|
||||
}
|
||||
return function () {
|
||||
return styles;
|
||||
};
|
||||
}
|
||||
}
|
||||
export default Feature;
|
||||
399
node_modules/ol/src/Geolocation.js
generated
vendored
Normal file
399
node_modules/ol/src/Geolocation.js
generated
vendored
Normal file
@@ -0,0 +1,399 @@
|
||||
/**
|
||||
* @module ol/Geolocation
|
||||
*/
|
||||
import BaseEvent from './events/Event.js';
|
||||
import BaseObject from './Object.js';
|
||||
import EventType from './events/EventType.js';
|
||||
import {circular as circularPolygon} from './geom/Polygon.js';
|
||||
import {
|
||||
get as getProjection,
|
||||
getTransformFromProjections,
|
||||
identityTransform,
|
||||
} from './proj.js';
|
||||
import {toRadians} from './math.js';
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
const Property = {
|
||||
ACCURACY: 'accuracy',
|
||||
ACCURACY_GEOMETRY: 'accuracyGeometry',
|
||||
ALTITUDE: 'altitude',
|
||||
ALTITUDE_ACCURACY: 'altitudeAccuracy',
|
||||
HEADING: 'heading',
|
||||
POSITION: 'position',
|
||||
PROJECTION: 'projection',
|
||||
SPEED: 'speed',
|
||||
TRACKING: 'tracking',
|
||||
TRACKING_OPTIONS: 'trackingOptions',
|
||||
};
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted on Geolocation error.
|
||||
*/
|
||||
class GeolocationError extends BaseEvent {
|
||||
/**
|
||||
* @param {GeolocationPositionError} error error object.
|
||||
*/
|
||||
constructor(error) {
|
||||
super(EventType.ERROR);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.code = error.code;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.message = error.message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {boolean} [tracking=false] Start Tracking right after
|
||||
* instantiation.
|
||||
* @property {PositionOptions} [trackingOptions] Tracking options.
|
||||
* See https://www.w3.org/TR/geolocation-API/#position_options_interface.
|
||||
* @property {import("./proj.js").ProjectionLike} [projection] The projection the position
|
||||
* is reported in.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {import("./ObjectEventType").Types|'change:accuracy'|'change:accuracyGeometry'|'change:altitude'|
|
||||
* 'change:altitudeAccuracy'|'change:heading'|'change:position'|'change:projection'|'change:speed'|'change:tracking'|
|
||||
* 'change:trackingOptions'} GeolocationObjectEventTypes
|
||||
*/
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {import("./Observable").OnSignature<import("./Observable").EventTypes, import("./events/Event.js").default, Return> &
|
||||
* import("./Observable").OnSignature<GeolocationObjectEventTypes, import("./Object").ObjectEvent, Return> &
|
||||
* import("./Observable").OnSignature<'error', GeolocationError, Return> &
|
||||
* import("./Observable").CombinedOnSignature<import("./Observable").EventTypes|GeolocationObjectEventTypes|
|
||||
* 'error', Return>} GeolocationOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Helper class for providing HTML5 Geolocation capabilities.
|
||||
* The [Geolocation API](https://www.w3.org/TR/geolocation-API/)
|
||||
* is used to locate a user's position.
|
||||
*
|
||||
* To get notified of position changes, register a listener for the generic
|
||||
* `change` event on your instance of {@link module:ol/Geolocation~Geolocation}.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* var geolocation = new Geolocation({
|
||||
* // take the projection to use from the map's view
|
||||
* projection: view.getProjection()
|
||||
* });
|
||||
* // listen to changes in position
|
||||
* geolocation.on('change', function(evt) {
|
||||
* window.console.log(geolocation.getPosition());
|
||||
* });
|
||||
*
|
||||
* @fires module:ol/events/Event~BaseEvent#event:error
|
||||
* @api
|
||||
*/
|
||||
class Geolocation extends BaseObject {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
/***
|
||||
* @type {GeolocationOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.on;
|
||||
|
||||
/***
|
||||
* @type {GeolocationOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.once;
|
||||
|
||||
/***
|
||||
* @type {GeolocationOnSignature<void>}
|
||||
*/
|
||||
this.un;
|
||||
|
||||
const options = opt_options || {};
|
||||
|
||||
/**
|
||||
* The unprojected (EPSG:4326) device position.
|
||||
* @private
|
||||
* @type {?import("./coordinate.js").Coordinate}
|
||||
*/
|
||||
this.position_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./proj.js").TransformFunction}
|
||||
*/
|
||||
this.transform_ = identityTransform;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.watchId_ = undefined;
|
||||
|
||||
this.addChangeListener(Property.PROJECTION, this.handleProjectionChanged_);
|
||||
this.addChangeListener(Property.TRACKING, this.handleTrackingChanged_);
|
||||
|
||||
if (options.projection !== undefined) {
|
||||
this.setProjection(options.projection);
|
||||
}
|
||||
if (options.trackingOptions !== undefined) {
|
||||
this.setTrackingOptions(options.trackingOptions);
|
||||
}
|
||||
|
||||
this.setTracking(options.tracking !== undefined ? options.tracking : false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up.
|
||||
*/
|
||||
disposeInternal() {
|
||||
this.setTracking(false);
|
||||
super.disposeInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleProjectionChanged_() {
|
||||
const projection = this.getProjection();
|
||||
if (projection) {
|
||||
this.transform_ = getTransformFromProjections(
|
||||
getProjection('EPSG:4326'),
|
||||
projection
|
||||
);
|
||||
if (this.position_) {
|
||||
this.set(Property.POSITION, this.transform_(this.position_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleTrackingChanged_() {
|
||||
if ('geolocation' in navigator) {
|
||||
const tracking = this.getTracking();
|
||||
if (tracking && this.watchId_ === undefined) {
|
||||
this.watchId_ = navigator.geolocation.watchPosition(
|
||||
this.positionChange_.bind(this),
|
||||
this.positionError_.bind(this),
|
||||
this.getTrackingOptions()
|
||||
);
|
||||
} else if (!tracking && this.watchId_ !== undefined) {
|
||||
navigator.geolocation.clearWatch(this.watchId_);
|
||||
this.watchId_ = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {GeolocationPosition} position position event.
|
||||
*/
|
||||
positionChange_(position) {
|
||||
const coords = position.coords;
|
||||
this.set(Property.ACCURACY, coords.accuracy);
|
||||
this.set(
|
||||
Property.ALTITUDE,
|
||||
coords.altitude === null ? undefined : coords.altitude
|
||||
);
|
||||
this.set(
|
||||
Property.ALTITUDE_ACCURACY,
|
||||
coords.altitudeAccuracy === null ? undefined : coords.altitudeAccuracy
|
||||
);
|
||||
this.set(
|
||||
Property.HEADING,
|
||||
coords.heading === null ? undefined : toRadians(coords.heading)
|
||||
);
|
||||
if (!this.position_) {
|
||||
this.position_ = [coords.longitude, coords.latitude];
|
||||
} else {
|
||||
this.position_[0] = coords.longitude;
|
||||
this.position_[1] = coords.latitude;
|
||||
}
|
||||
const projectedPosition = this.transform_(this.position_);
|
||||
this.set(Property.POSITION, projectedPosition);
|
||||
this.set(Property.SPEED, coords.speed === null ? undefined : coords.speed);
|
||||
const geometry = circularPolygon(this.position_, coords.accuracy);
|
||||
geometry.applyTransform(this.transform_);
|
||||
this.set(Property.ACCURACY_GEOMETRY, geometry);
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {GeolocationPositionError} error error object.
|
||||
*/
|
||||
positionError_(error) {
|
||||
this.dispatchEvent(new GeolocationError(error));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the accuracy of the position in meters.
|
||||
* @return {number|undefined} The accuracy of the position measurement in
|
||||
* meters.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getAccuracy() {
|
||||
return /** @type {number|undefined} */ (this.get(Property.ACCURACY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a geometry of the position accuracy.
|
||||
* @return {?import("./geom/Polygon.js").default} A geometry of the position accuracy.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getAccuracyGeometry() {
|
||||
return /** @type {?import("./geom/Polygon.js").default} */ (
|
||||
this.get(Property.ACCURACY_GEOMETRY) || null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the altitude associated with the position.
|
||||
* @return {number|undefined} The altitude of the position in meters above mean
|
||||
* sea level.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getAltitude() {
|
||||
return /** @type {number|undefined} */ (this.get(Property.ALTITUDE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the altitude accuracy of the position.
|
||||
* @return {number|undefined} The accuracy of the altitude measurement in
|
||||
* meters.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getAltitudeAccuracy() {
|
||||
return /** @type {number|undefined} */ (
|
||||
this.get(Property.ALTITUDE_ACCURACY)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the heading as radians clockwise from North.
|
||||
* Note: depending on the browser, the heading is only defined if the `enableHighAccuracy`
|
||||
* is set to `true` in the tracking options.
|
||||
* @return {number|undefined} The heading of the device in radians from north.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getHeading() {
|
||||
return /** @type {number|undefined} */ (this.get(Property.HEADING));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the device.
|
||||
* @return {import("./coordinate.js").Coordinate|undefined} The current position of the device reported
|
||||
* in the current projection.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getPosition() {
|
||||
return /** @type {import("./coordinate.js").Coordinate|undefined} */ (
|
||||
this.get(Property.POSITION)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the projection associated with the position.
|
||||
* @return {import("./proj/Projection.js").default|undefined} The projection the position is
|
||||
* reported in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getProjection() {
|
||||
return /** @type {import("./proj/Projection.js").default|undefined} */ (
|
||||
this.get(Property.PROJECTION)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the speed in meters per second.
|
||||
* @return {number|undefined} The instantaneous speed of the device in meters
|
||||
* per second.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getSpeed() {
|
||||
return /** @type {number|undefined} */ (this.get(Property.SPEED));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the device location is being tracked.
|
||||
* @return {boolean} The device location is being tracked.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getTracking() {
|
||||
return /** @type {boolean} */ (this.get(Property.TRACKING));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tracking options.
|
||||
* See https://www.w3.org/TR/geolocation-API/#position-options.
|
||||
* @return {PositionOptions|undefined} PositionOptions as defined by
|
||||
* the [HTML5 Geolocation spec
|
||||
* ](https://www.w3.org/TR/geolocation-API/#position_options_interface).
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getTrackingOptions() {
|
||||
return /** @type {PositionOptions|undefined} */ (
|
||||
this.get(Property.TRACKING_OPTIONS)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the projection to use for transforming the coordinates.
|
||||
* @param {import("./proj.js").ProjectionLike} projection The projection the position is
|
||||
* reported in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setProjection(projection) {
|
||||
this.set(Property.PROJECTION, getProjection(projection));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable tracking.
|
||||
* @param {boolean} tracking Enable tracking.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setTracking(tracking) {
|
||||
this.set(Property.TRACKING, tracking);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tracking options.
|
||||
* See http://www.w3.org/TR/geolocation-API/#position-options.
|
||||
* @param {PositionOptions} options PositionOptions as defined by the
|
||||
* [HTML5 Geolocation spec
|
||||
* ](http://www.w3.org/TR/geolocation-API/#position_options_interface).
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setTrackingOptions(options) {
|
||||
this.set(Property.TRACKING_OPTIONS, options);
|
||||
}
|
||||
}
|
||||
|
||||
export default Geolocation;
|
||||
204
node_modules/ol/src/Image.js
generated
vendored
Normal file
204
node_modules/ol/src/Image.js
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* @module ol/Image
|
||||
*/
|
||||
import EventType from './events/EventType.js';
|
||||
import ImageBase from './ImageBase.js';
|
||||
import ImageState from './ImageState.js';
|
||||
import {IMAGE_DECODE} from './has.js';
|
||||
import {getHeight} from './extent.js';
|
||||
import {listenOnce, unlistenByKey} from './events.js';
|
||||
|
||||
/**
|
||||
* A function that takes an {@link module:ol/Image~ImageWrapper} for the image and a
|
||||
* `{string}` for the src as arguments. It is supposed to make it so the
|
||||
* underlying image {@link module:ol/Image~ImageWrapper#getImage} is assigned the
|
||||
* content specified by the src. If not specified, the default is
|
||||
*
|
||||
* function(image, src) {
|
||||
* image.getImage().src = src;
|
||||
* }
|
||||
*
|
||||
* Providing a custom `imageLoadFunction` can be useful to load images with
|
||||
* post requests or - in general - through XHR requests, where the src of the
|
||||
* image element would be set to a data URI when the content is loaded.
|
||||
*
|
||||
* @typedef {function(ImageWrapper, string): void} LoadFunction
|
||||
* @api
|
||||
*/
|
||||
|
||||
class ImageWrapper extends ImageBase {
|
||||
/**
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {number|undefined} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {string} src Image source URI.
|
||||
* @param {?string} crossOrigin Cross origin.
|
||||
* @param {LoadFunction} imageLoadFunction Image load function.
|
||||
*/
|
||||
constructor(
|
||||
extent,
|
||||
resolution,
|
||||
pixelRatio,
|
||||
src,
|
||||
crossOrigin,
|
||||
imageLoadFunction
|
||||
) {
|
||||
super(extent, resolution, pixelRatio, ImageState.IDLE);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.src_ = src;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement}
|
||||
*/
|
||||
this.image_ = new Image();
|
||||
if (crossOrigin !== null) {
|
||||
this.image_.crossOrigin = crossOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?function():void}
|
||||
*/
|
||||
this.unlisten_ = null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {import("./ImageState.js").default}
|
||||
*/
|
||||
this.state = ImageState.IDLE;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {LoadFunction}
|
||||
*/
|
||||
this.imageLoadFunction_ = imageLoadFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
||||
* @api
|
||||
*/
|
||||
getImage() {
|
||||
return this.image_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks loading or read errors.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
handleImageError_() {
|
||||
this.state = ImageState.ERROR;
|
||||
this.unlistenImage_();
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks successful image load.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
handleImageLoad_() {
|
||||
if (this.resolution === undefined) {
|
||||
this.resolution = getHeight(this.extent) / this.image_.height;
|
||||
}
|
||||
this.state = ImageState.LOADED;
|
||||
this.unlistenImage_();
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the image or retry if loading previously failed.
|
||||
* Loading is taken care of by the tile queue, and calling this method is
|
||||
* only needed for preloading or for reloading in case of an error.
|
||||
* @api
|
||||
*/
|
||||
load() {
|
||||
if (this.state == ImageState.IDLE || this.state == ImageState.ERROR) {
|
||||
this.state = ImageState.LOADING;
|
||||
this.changed();
|
||||
this.imageLoadFunction_(this, this.src_);
|
||||
this.unlisten_ = listenImage(
|
||||
this.image_,
|
||||
this.handleImageLoad_.bind(this),
|
||||
this.handleImageError_.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image.
|
||||
*/
|
||||
setImage(image) {
|
||||
this.image_ = image;
|
||||
this.resolution = getHeight(this.extent) / this.image_.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards event handlers which listen for load completion or errors.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
unlistenImage_() {
|
||||
if (this.unlisten_) {
|
||||
this.unlisten_();
|
||||
this.unlisten_ = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image element.
|
||||
* @param {function():any} loadHandler Load callback function.
|
||||
* @param {function():any} errorHandler Error callback function.
|
||||
* @return {function():void} Callback to stop listening.
|
||||
*/
|
||||
export function listenImage(image, loadHandler, errorHandler) {
|
||||
const img = /** @type {HTMLImageElement} */ (image);
|
||||
let listening = true;
|
||||
let decoding = false;
|
||||
let loaded = false;
|
||||
|
||||
const listenerKeys = [
|
||||
listenOnce(img, EventType.LOAD, function () {
|
||||
loaded = true;
|
||||
if (!decoding) {
|
||||
loadHandler();
|
||||
}
|
||||
}),
|
||||
];
|
||||
|
||||
if (img.src && IMAGE_DECODE) {
|
||||
decoding = true;
|
||||
img
|
||||
.decode()
|
||||
.then(function () {
|
||||
if (listening) {
|
||||
loadHandler();
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
if (listening) {
|
||||
if (loaded) {
|
||||
loadHandler();
|
||||
} else {
|
||||
errorHandler();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
listenerKeys.push(listenOnce(img, EventType.ERROR, errorHandler));
|
||||
}
|
||||
|
||||
return function unlisten() {
|
||||
listening = false;
|
||||
listenerKeys.forEach(unlistenByKey);
|
||||
};
|
||||
}
|
||||
|
||||
export default ImageWrapper;
|
||||
98
node_modules/ol/src/ImageBase.js
generated
vendored
Normal file
98
node_modules/ol/src/ImageBase.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @module ol/ImageBase
|
||||
*/
|
||||
import EventTarget from './events/Target.js';
|
||||
import EventType from './events/EventType.js';
|
||||
import {abstract} from './util.js';
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
*/
|
||||
class ImageBase extends EventTarget {
|
||||
/**
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {number|undefined} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {import("./ImageState.js").default} state State.
|
||||
*/
|
||||
constructor(extent, resolution, pixelRatio, state) {
|
||||
super();
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {import("./extent.js").Extent}
|
||||
*/
|
||||
this.extent = extent;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.pixelRatio_ = pixelRatio;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.resolution = resolution;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {import("./ImageState.js").default}
|
||||
*/
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
changed() {
|
||||
this.dispatchEvent(EventType.CHANGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./extent.js").Extent} Extent.
|
||||
*/
|
||||
getExtent() {
|
||||
return this.extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
||||
*/
|
||||
getImage() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} PixelRatio.
|
||||
*/
|
||||
getPixelRatio() {
|
||||
return this.pixelRatio_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Resolution.
|
||||
*/
|
||||
getResolution() {
|
||||
return /** @type {number} */ (this.resolution);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./ImageState.js").default} State.
|
||||
*/
|
||||
getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load not yet loaded URI.
|
||||
* @abstract
|
||||
*/
|
||||
load() {
|
||||
abstract();
|
||||
}
|
||||
}
|
||||
|
||||
export default ImageBase;
|
||||
93
node_modules/ol/src/ImageCanvas.js
generated
vendored
Normal file
93
node_modules/ol/src/ImageCanvas.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @module ol/ImageCanvas
|
||||
*/
|
||||
import ImageBase from './ImageBase.js';
|
||||
import ImageState from './ImageState.js';
|
||||
|
||||
/**
|
||||
* A function that is called to trigger asynchronous canvas drawing. It is
|
||||
* called with a "done" callback that should be called when drawing is done.
|
||||
* If any error occurs during drawing, the "done" callback should be called with
|
||||
* that error.
|
||||
*
|
||||
* @typedef {function(function(Error=): void): void} Loader
|
||||
*/
|
||||
|
||||
class ImageCanvas extends ImageBase {
|
||||
/**
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {HTMLCanvasElement} canvas Canvas.
|
||||
* @param {Loader} [opt_loader] Optional loader function to
|
||||
* support asynchronous canvas drawing.
|
||||
*/
|
||||
constructor(extent, resolution, pixelRatio, canvas, opt_loader) {
|
||||
const state =
|
||||
opt_loader !== undefined ? ImageState.IDLE : ImageState.LOADED;
|
||||
|
||||
super(extent, resolution, pixelRatio, state);
|
||||
|
||||
/**
|
||||
* Optional canvas loader function.
|
||||
* @type {?Loader}
|
||||
* @private
|
||||
*/
|
||||
this.loader_ = opt_loader !== undefined ? opt_loader : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLCanvasElement}
|
||||
*/
|
||||
this.canvas_ = canvas;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?Error}
|
||||
*/
|
||||
this.error_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any error associated with asynchronous rendering.
|
||||
* @return {?Error} Any error that occurred during rendering.
|
||||
*/
|
||||
getError() {
|
||||
return this.error_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle async drawing complete.
|
||||
* @param {Error} [err] Any error during drawing.
|
||||
* @private
|
||||
*/
|
||||
handleLoad_(err) {
|
||||
if (err) {
|
||||
this.error_ = err;
|
||||
this.state = ImageState.ERROR;
|
||||
} else {
|
||||
this.state = ImageState.LOADED;
|
||||
}
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load not yet loaded URI.
|
||||
*/
|
||||
load() {
|
||||
if (this.state == ImageState.IDLE) {
|
||||
this.state = ImageState.LOADING;
|
||||
this.changed();
|
||||
this.loader_(this.handleLoad_.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {HTMLCanvasElement} Canvas element.
|
||||
*/
|
||||
getImage() {
|
||||
return this.canvas_;
|
||||
}
|
||||
}
|
||||
|
||||
export default ImageCanvas;
|
||||
14
node_modules/ol/src/ImageState.js
generated
vendored
Normal file
14
node_modules/ol/src/ImageState.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @module ol/ImageState
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
export default {
|
||||
IDLE: 0,
|
||||
LOADING: 1,
|
||||
LOADED: 2,
|
||||
ERROR: 3,
|
||||
EMPTY: 4,
|
||||
};
|
||||
162
node_modules/ol/src/ImageTile.js
generated
vendored
Normal file
162
node_modules/ol/src/ImageTile.js
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @module ol/ImageTile
|
||||
*/
|
||||
import Tile from './Tile.js';
|
||||
import TileState from './TileState.js';
|
||||
import {createCanvasContext2D} from './dom.js';
|
||||
import {listenImage} from './Image.js';
|
||||
|
||||
class ImageTile extends Tile {
|
||||
/**
|
||||
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||
* @param {import("./TileState.js").default} state State.
|
||||
* @param {string} src Image source URI.
|
||||
* @param {?string} crossOrigin Cross origin.
|
||||
* @param {import("./Tile.js").LoadFunction} tileLoadFunction Tile load function.
|
||||
* @param {import("./Tile.js").Options} [opt_options] Tile options.
|
||||
*/
|
||||
constructor(
|
||||
tileCoord,
|
||||
state,
|
||||
src,
|
||||
crossOrigin,
|
||||
tileLoadFunction,
|
||||
opt_options
|
||||
) {
|
||||
super(tileCoord, state, opt_options);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?string}
|
||||
*/
|
||||
this.crossOrigin_ = crossOrigin;
|
||||
|
||||
/**
|
||||
* Image URI
|
||||
*
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.src_ = src;
|
||||
|
||||
this.key = src;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLImageElement|HTMLCanvasElement}
|
||||
*/
|
||||
this.image_ = new Image();
|
||||
if (crossOrigin !== null) {
|
||||
this.image_.crossOrigin = crossOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?function():void}
|
||||
*/
|
||||
this.unlisten_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./Tile.js").LoadFunction}
|
||||
*/
|
||||
this.tileLoadFunction_ = tileLoadFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML image element for this tile (may be a Canvas, Image, or Video).
|
||||
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
||||
* @api
|
||||
*/
|
||||
getImage() {
|
||||
return this.image_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an HTML image element for this tile (may be a Canvas or preloaded Image).
|
||||
* @param {HTMLCanvasElement|HTMLImageElement} element Element.
|
||||
*/
|
||||
setImage(element) {
|
||||
this.image_ = element;
|
||||
this.state = TileState.LOADED;
|
||||
this.unlistenImage_();
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks loading or read errors.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
handleImageError_() {
|
||||
this.state = TileState.ERROR;
|
||||
this.unlistenImage_();
|
||||
this.image_ = getBlankImage();
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks successful image load.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
handleImageLoad_() {
|
||||
const image = /** @type {HTMLImageElement} */ (this.image_);
|
||||
if (image.naturalWidth && image.naturalHeight) {
|
||||
this.state = TileState.LOADED;
|
||||
} else {
|
||||
this.state = TileState.EMPTY;
|
||||
}
|
||||
this.unlistenImage_();
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load not yet loaded URI.
|
||||
* @api
|
||||
*/
|
||||
load() {
|
||||
if (this.state == TileState.ERROR) {
|
||||
this.state = TileState.IDLE;
|
||||
this.image_ = new Image();
|
||||
if (this.crossOrigin_ !== null) {
|
||||
this.image_.crossOrigin = this.crossOrigin_;
|
||||
}
|
||||
}
|
||||
if (this.state == TileState.IDLE) {
|
||||
this.state = TileState.LOADING;
|
||||
this.changed();
|
||||
this.tileLoadFunction_(this, this.src_);
|
||||
this.unlisten_ = listenImage(
|
||||
this.image_,
|
||||
this.handleImageLoad_.bind(this),
|
||||
this.handleImageError_.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards event handlers which listen for load completion or errors.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
unlistenImage_() {
|
||||
if (this.unlisten_) {
|
||||
this.unlisten_();
|
||||
this.unlisten_ = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a 1-pixel blank image.
|
||||
* @return {HTMLCanvasElement} Blank image.
|
||||
*/
|
||||
function getBlankImage() {
|
||||
const ctx = createCanvasContext2D(1, 1);
|
||||
ctx.fillStyle = 'rgba(0,0,0,0)';
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
return ctx.canvas;
|
||||
}
|
||||
|
||||
export default ImageTile;
|
||||
126
node_modules/ol/src/Kinetic.js
generated
vendored
Normal file
126
node_modules/ol/src/Kinetic.js
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @module ol/Kinetic
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Implementation of inertial deceleration for map movement.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Kinetic {
|
||||
/**
|
||||
* @param {number} decay Rate of decay (must be negative).
|
||||
* @param {number} minVelocity Minimum velocity (pixels/millisecond).
|
||||
* @param {number} delay Delay to consider to calculate the kinetic
|
||||
* initial values (milliseconds).
|
||||
*/
|
||||
constructor(decay, minVelocity, delay) {
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.decay_ = decay;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.minVelocity_ = minVelocity;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.delay_ = delay;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<number>}
|
||||
*/
|
||||
this.points_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.angle_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.initialVelocity_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME empty description for jsdoc
|
||||
*/
|
||||
begin() {
|
||||
this.points_.length = 0;
|
||||
this.angle_ = 0;
|
||||
this.initialVelocity_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
*/
|
||||
update(x, y) {
|
||||
this.points_.push(x, y, Date.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether we should do kinetic animation.
|
||||
*/
|
||||
end() {
|
||||
if (this.points_.length < 6) {
|
||||
// at least 2 points are required (i.e. there must be at least 6 elements
|
||||
// in the array)
|
||||
return false;
|
||||
}
|
||||
const delay = Date.now() - this.delay_;
|
||||
const lastIndex = this.points_.length - 3;
|
||||
if (this.points_[lastIndex + 2] < delay) {
|
||||
// the last tracked point is too old, which means that the user stopped
|
||||
// panning before releasing the map
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the first point which still falls into the delay time
|
||||
let firstIndex = lastIndex - 3;
|
||||
while (firstIndex > 0 && this.points_[firstIndex + 2] > delay) {
|
||||
firstIndex -= 3;
|
||||
}
|
||||
|
||||
const duration = this.points_[lastIndex + 2] - this.points_[firstIndex + 2];
|
||||
// we don't want a duration of 0 (divide by zero)
|
||||
// we also make sure the user panned for a duration of at least one frame
|
||||
// (1/60s) to compute sane displacement values
|
||||
if (duration < 1000 / 60) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const dx = this.points_[lastIndex] - this.points_[firstIndex];
|
||||
const dy = this.points_[lastIndex + 1] - this.points_[firstIndex + 1];
|
||||
this.angle_ = Math.atan2(dy, dx);
|
||||
this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration;
|
||||
return this.initialVelocity_ > this.minVelocity_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Total distance travelled (pixels).
|
||||
*/
|
||||
getDistance() {
|
||||
return (this.minVelocity_ - this.initialVelocity_) / this.decay_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Angle of the kinetic panning animation (radians).
|
||||
*/
|
||||
getAngle() {
|
||||
return this.angle_;
|
||||
}
|
||||
}
|
||||
|
||||
export default Kinetic;
|
||||
80
node_modules/ol/src/Map.js
generated
vendored
Normal file
80
node_modules/ol/src/Map.js
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @module ol/Map
|
||||
*/
|
||||
import CompositeMapRenderer from './renderer/Composite.js';
|
||||
import PluggableMap from './PluggableMap.js';
|
||||
import {assign} from './obj.js';
|
||||
import {defaults as defaultControls} from './control.js';
|
||||
import {defaults as defaultInteractions} from './interaction.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* The map is the core component of OpenLayers. For a map to render, a view,
|
||||
* one or more layers, and a target container are needed:
|
||||
*
|
||||
* import Map from 'ol/Map';
|
||||
* import View from 'ol/View';
|
||||
* import TileLayer from 'ol/layer/Tile';
|
||||
* import OSM from 'ol/source/OSM';
|
||||
*
|
||||
* var map = new Map({
|
||||
* view: new View({
|
||||
* center: [0, 0],
|
||||
* zoom: 1
|
||||
* }),
|
||||
* layers: [
|
||||
* new TileLayer({
|
||||
* source: new OSM()
|
||||
* })
|
||||
* ],
|
||||
* target: 'map'
|
||||
* });
|
||||
*
|
||||
* The above snippet creates a map using a {@link module:ol/layer/Tile~TileLayer} to
|
||||
* display {@link module:ol/source/OSM~OSM} OSM data and render it to a DOM
|
||||
* element with the id `map`.
|
||||
*
|
||||
* The constructor places a viewport container (with CSS class name
|
||||
* `ol-viewport`) in the target element (see `getViewport()`), and then two
|
||||
* further elements within the viewport: one with CSS class name
|
||||
* `ol-overlaycontainer-stopevent` for controls and some overlays, and one with
|
||||
* CSS class name `ol-overlaycontainer` for other overlays (see the `stopEvent`
|
||||
* option of {@link module:ol/Overlay~Overlay} for the difference). The map
|
||||
* itself is placed in a further element within the viewport.
|
||||
*
|
||||
* Layers are stored as a {@link module:ol/Collection~Collection} in
|
||||
* layerGroups. A top-level group is provided by the library. This is what is
|
||||
* accessed by `getLayerGroup` and `setLayerGroup`. Layers entered in the
|
||||
* options are added to this group, and `addLayer` and `removeLayer` change the
|
||||
* layer collection in the group. `getLayers` is a convenience function for
|
||||
* `getLayerGroup().getLayers()`. Note that {@link module:ol/layer/Group~LayerGroup}
|
||||
* is a subclass of {@link module:ol/layer/Base~BaseLayer}, so layers entered in the
|
||||
* options or added with `addLayer` can be groups, which can contain further
|
||||
* groups, and so on.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Map extends PluggableMap {
|
||||
/**
|
||||
* @param {import("./PluggableMap.js").MapOptions} options Map options.
|
||||
*/
|
||||
constructor(options) {
|
||||
options = assign({}, options);
|
||||
if (!options.controls) {
|
||||
options.controls = defaultControls();
|
||||
}
|
||||
if (!options.interactions) {
|
||||
options.interactions = defaultInteractions({
|
||||
onFocusOnly: true,
|
||||
});
|
||||
}
|
||||
|
||||
super(options);
|
||||
}
|
||||
|
||||
createRenderer() {
|
||||
return new CompositeMapRenderer(this);
|
||||
}
|
||||
}
|
||||
|
||||
export default Map;
|
||||
122
node_modules/ol/src/MapBrowserEvent.js
generated
vendored
Normal file
122
node_modules/ol/src/MapBrowserEvent.js
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* @module ol/MapBrowserEvent
|
||||
*/
|
||||
import MapEvent from './MapEvent.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted as map browser events are instances of this type.
|
||||
* See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map browser event.
|
||||
* @template {UIEvent} EVENT
|
||||
*/
|
||||
class MapBrowserEvent extends MapEvent {
|
||||
/**
|
||||
* @param {string} type Event type.
|
||||
* @param {import("./PluggableMap.js").default} map Map.
|
||||
* @param {EVENT} originalEvent Original event.
|
||||
* @param {boolean} [opt_dragging] Is the map currently being dragged?
|
||||
* @param {import("./PluggableMap.js").FrameState} [opt_frameState] Frame state.
|
||||
* @param {Array<PointerEvent>} [opt_activePointers] Active pointers.
|
||||
*/
|
||||
constructor(
|
||||
type,
|
||||
map,
|
||||
originalEvent,
|
||||
opt_dragging,
|
||||
opt_frameState,
|
||||
opt_activePointers
|
||||
) {
|
||||
super(type, map, opt_frameState);
|
||||
|
||||
/**
|
||||
* The original browser event.
|
||||
* @const
|
||||
* @type {EVENT}
|
||||
* @api
|
||||
*/
|
||||
this.originalEvent = originalEvent;
|
||||
|
||||
/**
|
||||
* The map pixel relative to the viewport corresponding to the original browser event.
|
||||
* @type {?import("./pixel.js").Pixel}
|
||||
*/
|
||||
this.pixel_ = null;
|
||||
|
||||
/**
|
||||
* The coordinate in the user projection corresponding to the original browser event.
|
||||
* @type {?import("./coordinate.js").Coordinate}
|
||||
*/
|
||||
this.coordinate_ = null;
|
||||
|
||||
/**
|
||||
* Indicates if the map is currently being dragged. Only set for
|
||||
* `POINTERDRAG` and `POINTERMOVE` events. Default is `false`.
|
||||
*
|
||||
* @type {boolean}
|
||||
* @api
|
||||
*/
|
||||
this.dragging = opt_dragging !== undefined ? opt_dragging : false;
|
||||
|
||||
/**
|
||||
* @type {Array<PointerEvent>|undefined}
|
||||
*/
|
||||
this.activePointers = opt_activePointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* The map pixel relative to the viewport corresponding to the original event.
|
||||
* @type {import("./pixel.js").Pixel}
|
||||
* @api
|
||||
*/
|
||||
get pixel() {
|
||||
if (!this.pixel_) {
|
||||
this.pixel_ = this.map.getEventPixel(this.originalEvent);
|
||||
}
|
||||
return this.pixel_;
|
||||
}
|
||||
set pixel(pixel) {
|
||||
this.pixel_ = pixel;
|
||||
}
|
||||
|
||||
/**
|
||||
* The coordinate corresponding to the original browser event. This will be in the user
|
||||
* projection if one is set. Otherwise it will be in the view projection.
|
||||
* @type {import("./coordinate.js").Coordinate}
|
||||
* @api
|
||||
*/
|
||||
get coordinate() {
|
||||
if (!this.coordinate_) {
|
||||
this.coordinate_ = this.map.getCoordinateFromPixel(this.pixel);
|
||||
}
|
||||
return this.coordinate_;
|
||||
}
|
||||
set coordinate(coordinate) {
|
||||
this.coordinate_ = coordinate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents the default browser action.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault.
|
||||
* @api
|
||||
*/
|
||||
preventDefault() {
|
||||
super.preventDefault();
|
||||
if ('preventDefault' in this.originalEvent) {
|
||||
/** @type {UIEvent} */ (this.originalEvent).preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents further propagation of the current event.
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation.
|
||||
* @api
|
||||
*/
|
||||
stopPropagation() {
|
||||
super.stopPropagation();
|
||||
if ('stopPropagation' in this.originalEvent) {
|
||||
/** @type {UIEvent} */ (this.originalEvent).stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default MapBrowserEvent;
|
||||
421
node_modules/ol/src/MapBrowserEventHandler.js
generated
vendored
Normal file
421
node_modules/ol/src/MapBrowserEventHandler.js
generated
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
/**
|
||||
* @module ol/MapBrowserEventHandler
|
||||
*/
|
||||
|
||||
import EventType from './events/EventType.js';
|
||||
import MapBrowserEvent from './MapBrowserEvent.js';
|
||||
import MapBrowserEventType from './MapBrowserEventType.js';
|
||||
import PointerEventType from './pointer/EventType.js';
|
||||
import Target from './events/Target.js';
|
||||
import {PASSIVE_EVENT_LISTENERS} from './has.js';
|
||||
import {VOID} from './functions.js';
|
||||
import {getValues} from './obj.js';
|
||||
import {listen, unlistenByKey} from './events.js';
|
||||
|
||||
class MapBrowserEventHandler extends Target {
|
||||
/**
|
||||
* @param {import("./PluggableMap.js").default} map The map with the viewport to listen to events on.
|
||||
* @param {number} [moveTolerance] The minimal distance the pointer must travel to trigger a move.
|
||||
*/
|
||||
constructor(map, moveTolerance) {
|
||||
super(map);
|
||||
|
||||
/**
|
||||
* This is the element that we will listen to the real events on.
|
||||
* @type {import("./PluggableMap.js").default}
|
||||
* @private
|
||||
*/
|
||||
this.map_ = map;
|
||||
|
||||
/**
|
||||
* @type {any}
|
||||
* @private
|
||||
*/
|
||||
this.clickTimeoutId_;
|
||||
|
||||
/**
|
||||
* Emulate dblclick and singleclick. Will be true when only one pointer is active.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.emulateClicks_ = false;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.dragging_ = false;
|
||||
|
||||
/**
|
||||
* @type {!Array<import("./events.js").EventsKey>}
|
||||
* @private
|
||||
*/
|
||||
this.dragListenerKeys_ = [];
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.moveTolerance_ = moveTolerance === undefined ? 1 : moveTolerance;
|
||||
|
||||
/**
|
||||
* The most recent "down" type event (or null if none have occurred).
|
||||
* Set on pointerdown.
|
||||
* @type {PointerEvent|null}
|
||||
* @private
|
||||
*/
|
||||
this.down_ = null;
|
||||
|
||||
const element = this.map_.getViewport();
|
||||
|
||||
/**
|
||||
* @type {Array<PointerEvent>}
|
||||
* @private
|
||||
*/
|
||||
this.activePointers_ = [];
|
||||
|
||||
/**
|
||||
* @type {!Object<number, Event>}
|
||||
* @private
|
||||
*/
|
||||
this.trackedTouches_ = {};
|
||||
|
||||
this.element_ = element;
|
||||
|
||||
/**
|
||||
* @type {?import("./events.js").EventsKey}
|
||||
* @private
|
||||
*/
|
||||
this.pointerdownListenerKey_ = listen(
|
||||
element,
|
||||
PointerEventType.POINTERDOWN,
|
||||
this.handlePointerDown_,
|
||||
this
|
||||
);
|
||||
|
||||
/**
|
||||
* @type {PointerEvent}
|
||||
* @private
|
||||
*/
|
||||
this.originalPointerMoveEvent_;
|
||||
|
||||
/**
|
||||
* @type {?import("./events.js").EventsKey}
|
||||
* @private
|
||||
*/
|
||||
this.relayedListenerKey_ = listen(
|
||||
element,
|
||||
PointerEventType.POINTERMOVE,
|
||||
this.relayMoveEvent_,
|
||||
this
|
||||
);
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.boundHandleTouchMove_ = this.handleTouchMove_.bind(this);
|
||||
|
||||
this.element_.addEventListener(
|
||||
EventType.TOUCHMOVE,
|
||||
this.boundHandleTouchMove_,
|
||||
PASSIVE_EVENT_LISTENERS ? {passive: false} : false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PointerEvent} pointerEvent Pointer
|
||||
* event.
|
||||
* @private
|
||||
*/
|
||||
emulateClick_(pointerEvent) {
|
||||
let newEvent = new MapBrowserEvent(
|
||||
MapBrowserEventType.CLICK,
|
||||
this.map_,
|
||||
pointerEvent
|
||||
);
|
||||
this.dispatchEvent(newEvent);
|
||||
if (this.clickTimeoutId_ !== undefined) {
|
||||
// double-click
|
||||
clearTimeout(this.clickTimeoutId_);
|
||||
this.clickTimeoutId_ = undefined;
|
||||
newEvent = new MapBrowserEvent(
|
||||
MapBrowserEventType.DBLCLICK,
|
||||
this.map_,
|
||||
pointerEvent
|
||||
);
|
||||
this.dispatchEvent(newEvent);
|
||||
} else {
|
||||
// click
|
||||
this.clickTimeoutId_ = setTimeout(
|
||||
/** @this {MapBrowserEventHandler} */
|
||||
function () {
|
||||
this.clickTimeoutId_ = undefined;
|
||||
const newEvent = new MapBrowserEvent(
|
||||
MapBrowserEventType.SINGLECLICK,
|
||||
this.map_,
|
||||
pointerEvent
|
||||
);
|
||||
this.dispatchEvent(newEvent);
|
||||
}.bind(this),
|
||||
250
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps track on how many pointers are currently active.
|
||||
*
|
||||
* @param {PointerEvent} pointerEvent Pointer
|
||||
* event.
|
||||
* @private
|
||||
*/
|
||||
updateActivePointers_(pointerEvent) {
|
||||
const event = pointerEvent;
|
||||
const id = event.pointerId;
|
||||
|
||||
if (
|
||||
event.type == MapBrowserEventType.POINTERUP ||
|
||||
event.type == MapBrowserEventType.POINTERCANCEL
|
||||
) {
|
||||
delete this.trackedTouches_[id];
|
||||
for (const pointerId in this.trackedTouches_) {
|
||||
if (this.trackedTouches_[pointerId].target !== event.target) {
|
||||
// Some platforms assign a new pointerId when the target changes.
|
||||
// If this happens, delete one tracked pointer. If there is more
|
||||
// than one tracked pointer for the old target, it will be cleared
|
||||
// by subsequent POINTERUP events from other pointers.
|
||||
delete this.trackedTouches_[pointerId];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
event.type == MapBrowserEventType.POINTERDOWN ||
|
||||
event.type == MapBrowserEventType.POINTERMOVE
|
||||
) {
|
||||
this.trackedTouches_[id] = event;
|
||||
}
|
||||
this.activePointers_ = getValues(this.trackedTouches_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PointerEvent} pointerEvent Pointer
|
||||
* event.
|
||||
* @private
|
||||
*/
|
||||
handlePointerUp_(pointerEvent) {
|
||||
this.updateActivePointers_(pointerEvent);
|
||||
const newEvent = new MapBrowserEvent(
|
||||
MapBrowserEventType.POINTERUP,
|
||||
this.map_,
|
||||
pointerEvent,
|
||||
undefined,
|
||||
undefined,
|
||||
this.activePointers_
|
||||
);
|
||||
this.dispatchEvent(newEvent);
|
||||
|
||||
// We emulate click events on left mouse button click, touch contact, and pen
|
||||
// contact. isMouseActionButton returns true in these cases (evt.button is set
|
||||
// to 0).
|
||||
// See http://www.w3.org/TR/pointerevents/#button-states
|
||||
// We only fire click, singleclick, and doubleclick if nobody has called
|
||||
// event.preventDefault().
|
||||
if (
|
||||
this.emulateClicks_ &&
|
||||
!newEvent.defaultPrevented &&
|
||||
!this.dragging_ &&
|
||||
this.isMouseActionButton_(pointerEvent)
|
||||
) {
|
||||
this.emulateClick_(this.down_);
|
||||
}
|
||||
|
||||
if (this.activePointers_.length === 0) {
|
||||
this.dragListenerKeys_.forEach(unlistenByKey);
|
||||
this.dragListenerKeys_.length = 0;
|
||||
this.dragging_ = false;
|
||||
this.down_ = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PointerEvent} pointerEvent Pointer
|
||||
* event.
|
||||
* @return {boolean} If the left mouse button was pressed.
|
||||
* @private
|
||||
*/
|
||||
isMouseActionButton_(pointerEvent) {
|
||||
return pointerEvent.button === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PointerEvent} pointerEvent Pointer
|
||||
* event.
|
||||
* @private
|
||||
*/
|
||||
handlePointerDown_(pointerEvent) {
|
||||
this.emulateClicks_ = this.activePointers_.length === 0;
|
||||
this.updateActivePointers_(pointerEvent);
|
||||
const newEvent = new MapBrowserEvent(
|
||||
MapBrowserEventType.POINTERDOWN,
|
||||
this.map_,
|
||||
pointerEvent,
|
||||
undefined,
|
||||
undefined,
|
||||
this.activePointers_
|
||||
);
|
||||
this.dispatchEvent(newEvent);
|
||||
|
||||
// Store a copy of the down event
|
||||
this.down_ = /** @type {PointerEvent} */ ({});
|
||||
for (const property in pointerEvent) {
|
||||
const value = pointerEvent[property];
|
||||
this.down_[property] = typeof value === 'function' ? VOID : value;
|
||||
}
|
||||
|
||||
if (this.dragListenerKeys_.length === 0) {
|
||||
const doc = this.map_.getOwnerDocument();
|
||||
this.dragListenerKeys_.push(
|
||||
listen(
|
||||
doc,
|
||||
MapBrowserEventType.POINTERMOVE,
|
||||
this.handlePointerMove_,
|
||||
this
|
||||
),
|
||||
listen(doc, MapBrowserEventType.POINTERUP, this.handlePointerUp_, this),
|
||||
/* Note that the listener for `pointercancel is set up on
|
||||
* `pointerEventHandler_` and not `documentPointerEventHandler_` like
|
||||
* the `pointerup` and `pointermove` listeners.
|
||||
*
|
||||
* The reason for this is the following: `TouchSource.vacuumTouches_()`
|
||||
* issues `pointercancel` events, when there was no `touchend` for a
|
||||
* `touchstart`. Now, let's say a first `touchstart` is registered on
|
||||
* `pointerEventHandler_`. The `documentPointerEventHandler_` is set up.
|
||||
* But `documentPointerEventHandler_` doesn't know about the first
|
||||
* `touchstart`. If there is no `touchend` for the `touchstart`, we can
|
||||
* only receive a `touchcancel` from `pointerEventHandler_`, because it is
|
||||
* only registered there.
|
||||
*/
|
||||
listen(
|
||||
this.element_,
|
||||
MapBrowserEventType.POINTERCANCEL,
|
||||
this.handlePointerUp_,
|
||||
this
|
||||
)
|
||||
);
|
||||
if (this.element_.getRootNode && this.element_.getRootNode() !== doc) {
|
||||
this.dragListenerKeys_.push(
|
||||
listen(
|
||||
this.element_.getRootNode(),
|
||||
MapBrowserEventType.POINTERUP,
|
||||
this.handlePointerUp_,
|
||||
this
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PointerEvent} pointerEvent Pointer
|
||||
* event.
|
||||
* @private
|
||||
*/
|
||||
handlePointerMove_(pointerEvent) {
|
||||
// Between pointerdown and pointerup, pointermove events are triggered.
|
||||
// To avoid a 'false' touchmove event to be dispatched, we test if the pointer
|
||||
// moved a significant distance.
|
||||
if (this.isMoving_(pointerEvent)) {
|
||||
this.updateActivePointers_(pointerEvent);
|
||||
this.dragging_ = true;
|
||||
const newEvent = new MapBrowserEvent(
|
||||
MapBrowserEventType.POINTERDRAG,
|
||||
this.map_,
|
||||
pointerEvent,
|
||||
this.dragging_,
|
||||
undefined,
|
||||
this.activePointers_
|
||||
);
|
||||
this.dispatchEvent(newEvent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap and relay a pointermove event.
|
||||
* @param {PointerEvent} pointerEvent Pointer
|
||||
* event.
|
||||
* @private
|
||||
*/
|
||||
relayMoveEvent_(pointerEvent) {
|
||||
this.originalPointerMoveEvent_ = pointerEvent;
|
||||
const dragging = !!(this.down_ && this.isMoving_(pointerEvent));
|
||||
this.dispatchEvent(
|
||||
new MapBrowserEvent(
|
||||
MapBrowserEventType.POINTERMOVE,
|
||||
this.map_,
|
||||
pointerEvent,
|
||||
dragging
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flexible handling of a `touch-action: none` css equivalent: because calling
|
||||
* `preventDefault()` on a `pointermove` event does not stop native page scrolling
|
||||
* and zooming, we also listen for `touchmove` and call `preventDefault()` on it
|
||||
* when an interaction (currently `DragPan` handles the event.
|
||||
* @param {TouchEvent} event Event.
|
||||
* @private
|
||||
*/
|
||||
handleTouchMove_(event) {
|
||||
// Due to https://github.com/mpizenberg/elm-pep/issues/2, `this.originalPointerMoveEvent_`
|
||||
// may not be initialized yet when we get here on a platform without native pointer events.
|
||||
const originalEvent = this.originalPointerMoveEvent_;
|
||||
if (
|
||||
(!originalEvent || originalEvent.defaultPrevented) &&
|
||||
(typeof event.cancelable !== 'boolean' || event.cancelable === true)
|
||||
) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PointerEvent} pointerEvent Pointer
|
||||
* event.
|
||||
* @return {boolean} Is moving.
|
||||
* @private
|
||||
*/
|
||||
isMoving_(pointerEvent) {
|
||||
return (
|
||||
this.dragging_ ||
|
||||
Math.abs(pointerEvent.clientX - this.down_.clientX) >
|
||||
this.moveTolerance_ ||
|
||||
Math.abs(pointerEvent.clientY - this.down_.clientY) > this.moveTolerance_
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up.
|
||||
*/
|
||||
disposeInternal() {
|
||||
if (this.relayedListenerKey_) {
|
||||
unlistenByKey(this.relayedListenerKey_);
|
||||
this.relayedListenerKey_ = null;
|
||||
}
|
||||
this.element_.removeEventListener(
|
||||
EventType.TOUCHMOVE,
|
||||
this.boundHandleTouchMove_
|
||||
);
|
||||
|
||||
if (this.pointerdownListenerKey_) {
|
||||
unlistenByKey(this.pointerdownListenerKey_);
|
||||
this.pointerdownListenerKey_ = null;
|
||||
}
|
||||
|
||||
this.dragListenerKeys_.forEach(unlistenByKey);
|
||||
this.dragListenerKeys_.length = 0;
|
||||
|
||||
this.element_ = null;
|
||||
super.disposeInternal();
|
||||
}
|
||||
}
|
||||
|
||||
export default MapBrowserEventHandler;
|
||||
59
node_modules/ol/src/MapBrowserEventType.js
generated
vendored
Normal file
59
node_modules/ol/src/MapBrowserEventType.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @module ol/MapBrowserEventType
|
||||
*/
|
||||
import EventType from './events/EventType.js';
|
||||
|
||||
/**
|
||||
* Constants for event names.
|
||||
* @enum {string}
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* A true single click with no dragging and no double click. Note that this
|
||||
* event is delayed by 250 ms to ensure that it is not a double click.
|
||||
* @event module:ol/MapBrowserEvent~MapBrowserEvent#singleclick
|
||||
* @api
|
||||
*/
|
||||
SINGLECLICK: 'singleclick',
|
||||
|
||||
/**
|
||||
* A click with no dragging. A double click will fire two of this.
|
||||
* @event module:ol/MapBrowserEvent~MapBrowserEvent#click
|
||||
* @api
|
||||
*/
|
||||
CLICK: EventType.CLICK,
|
||||
|
||||
/**
|
||||
* A true double click, with no dragging.
|
||||
* @event module:ol/MapBrowserEvent~MapBrowserEvent#dblclick
|
||||
* @api
|
||||
*/
|
||||
DBLCLICK: EventType.DBLCLICK,
|
||||
|
||||
/**
|
||||
* Triggered when a pointer is dragged.
|
||||
* @event module:ol/MapBrowserEvent~MapBrowserEvent#pointerdrag
|
||||
* @api
|
||||
*/
|
||||
POINTERDRAG: 'pointerdrag',
|
||||
|
||||
/**
|
||||
* Triggered when a pointer is moved. Note that on touch devices this is
|
||||
* triggered when the map is panned, so is not the same as mousemove.
|
||||
* @event module:ol/MapBrowserEvent~MapBrowserEvent#pointermove
|
||||
* @api
|
||||
*/
|
||||
POINTERMOVE: 'pointermove',
|
||||
|
||||
POINTERDOWN: 'pointerdown',
|
||||
POINTERUP: 'pointerup',
|
||||
POINTEROVER: 'pointerover',
|
||||
POINTEROUT: 'pointerout',
|
||||
POINTERENTER: 'pointerenter',
|
||||
POINTERLEAVE: 'pointerleave',
|
||||
POINTERCANCEL: 'pointercancel',
|
||||
};
|
||||
|
||||
/***
|
||||
* @typedef {'singleclick'|'click'|'dblclick'|'pointerdrag'|'pointermove'} Types
|
||||
*/
|
||||
36
node_modules/ol/src/MapEvent.js
generated
vendored
Normal file
36
node_modules/ol/src/MapEvent.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @module ol/MapEvent
|
||||
*/
|
||||
import Event from './events/Event.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted as map events are instances of this type.
|
||||
* See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map event.
|
||||
*/
|
||||
class MapEvent extends Event {
|
||||
/**
|
||||
* @param {string} type Event type.
|
||||
* @param {import("./PluggableMap.js").default} map Map.
|
||||
* @param {?import("./PluggableMap.js").FrameState} [opt_frameState] Frame state.
|
||||
*/
|
||||
constructor(type, map, opt_frameState) {
|
||||
super(type);
|
||||
|
||||
/**
|
||||
* The map where the event occurred.
|
||||
* @type {import("./PluggableMap.js").default}
|
||||
* @api
|
||||
*/
|
||||
this.map = map;
|
||||
|
||||
/**
|
||||
* The frame state at the time of the event.
|
||||
* @type {?import("./PluggableMap.js").FrameState}
|
||||
* @api
|
||||
*/
|
||||
this.frameState = opt_frameState !== undefined ? opt_frameState : null;
|
||||
}
|
||||
}
|
||||
|
||||
export default MapEvent;
|
||||
47
node_modules/ol/src/MapEventType.js
generated
vendored
Normal file
47
node_modules/ol/src/MapEventType.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @module ol/MapEventType
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Triggered after a map frame is rendered.
|
||||
* @event module:ol/MapEvent~MapEvent#postrender
|
||||
* @api
|
||||
*/
|
||||
POSTRENDER: 'postrender',
|
||||
|
||||
/**
|
||||
* Triggered when the map starts moving.
|
||||
* @event module:ol/MapEvent~MapEvent#movestart
|
||||
* @api
|
||||
*/
|
||||
MOVESTART: 'movestart',
|
||||
|
||||
/**
|
||||
* Triggered after the map is moved.
|
||||
* @event module:ol/MapEvent~MapEvent#moveend
|
||||
* @api
|
||||
*/
|
||||
MOVEEND: 'moveend',
|
||||
|
||||
/**
|
||||
* Triggered when loading of additional map data (tiles, images, features) starts.
|
||||
* @event module:ol/MapEvent~MapEvent#loadstart
|
||||
* @api
|
||||
*/
|
||||
LOADSTART: 'loadstart',
|
||||
|
||||
/**
|
||||
* Triggered when loading of additional map data has completed.
|
||||
* @event module:ol/MapEvent~MapEvent#loadend
|
||||
* @api
|
||||
*/
|
||||
LOADEND: 'loadend',
|
||||
};
|
||||
|
||||
/***
|
||||
* @typedef {'postrender'|'movestart'|'moveend'|'loadstart'|'loadend'} Types
|
||||
*/
|
||||
13
node_modules/ol/src/MapProperty.js
generated
vendored
Normal file
13
node_modules/ol/src/MapProperty.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @module ol/MapProperty
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export default {
|
||||
LAYERGROUP: 'layergroup',
|
||||
SIZE: 'size',
|
||||
TARGET: 'target',
|
||||
VIEW: 'view',
|
||||
};
|
||||
265
node_modules/ol/src/Object.js
generated
vendored
Normal file
265
node_modules/ol/src/Object.js
generated
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @module ol/Object
|
||||
*/
|
||||
import Event from './events/Event.js';
|
||||
import ObjectEventType from './ObjectEventType.js';
|
||||
import Observable from './Observable.js';
|
||||
import {assign, isEmpty} from './obj.js';
|
||||
import {getUid} from './util.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted by {@link module:ol/Object~BaseObject} instances are instances of this type.
|
||||
*/
|
||||
export class ObjectEvent extends Event {
|
||||
/**
|
||||
* @param {string} type The event type.
|
||||
* @param {string} key The property name.
|
||||
* @param {*} oldValue The old value for `key`.
|
||||
*/
|
||||
constructor(type, key, oldValue) {
|
||||
super(type);
|
||||
|
||||
/**
|
||||
* The name of the property whose value is changing.
|
||||
* @type {string}
|
||||
* @api
|
||||
*/
|
||||
this.key = key;
|
||||
|
||||
/**
|
||||
* The old value. To get the new value use `e.target.get(e.key)` where
|
||||
* `e` is the event object.
|
||||
* @type {*}
|
||||
* @api
|
||||
*/
|
||||
this.oldValue = oldValue;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {import("./Observable").OnSignature<import("./Observable").EventTypes, import("./events/Event.js").default, Return> &
|
||||
* import("./Observable").OnSignature<import("./ObjectEventType").Types, ObjectEvent, Return> &
|
||||
* import("./Observable").CombinedOnSignature<import("./Observable").EventTypes|import("./ObjectEventType").Types, Return>} ObjectOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Most non-trivial classes inherit from this.
|
||||
*
|
||||
* This extends {@link module:ol/Observable~Observable} with observable
|
||||
* properties, where each property is observable as well as the object as a
|
||||
* whole.
|
||||
*
|
||||
* Classes that inherit from this have pre-defined properties, to which you can
|
||||
* add your owns. The pre-defined properties are listed in this documentation as
|
||||
* 'Observable Properties', and have their own accessors; for example,
|
||||
* {@link module:ol/Map~Map} has a `target` property, accessed with
|
||||
* `getTarget()` and changed with `setTarget()`. Not all properties are however
|
||||
* settable. There are also general-purpose accessors `get()` and `set()`. For
|
||||
* example, `get('target')` is equivalent to `getTarget()`.
|
||||
*
|
||||
* The `set` accessors trigger a change event, and you can monitor this by
|
||||
* registering a listener. For example, {@link module:ol/View~View} has a
|
||||
* `center` property, so `view.on('change:center', function(evt) {...});` would
|
||||
* call the function whenever the value of the center property changes. Within
|
||||
* the function, `evt.target` would be the view, so `evt.target.getCenter()`
|
||||
* would return the new center.
|
||||
*
|
||||
* You can add your own observable properties with
|
||||
* `object.set('prop', 'value')`, and retrieve that with `object.get('prop')`.
|
||||
* You can listen for changes on that property value with
|
||||
* `object.on('change:prop', listener)`. You can get a list of all
|
||||
* properties with {@link module:ol/Object~BaseObject#getProperties}.
|
||||
*
|
||||
* Note that the observable properties are separate from standard JS properties.
|
||||
* You can, for example, give your map object a title with
|
||||
* `map.title='New title'` and with `map.set('title', 'Another title')`. The
|
||||
* first will be a `hasOwnProperty`; the second will appear in
|
||||
* `getProperties()`. Only the second is observable.
|
||||
*
|
||||
* Properties can be deleted by using the unset method. E.g.
|
||||
* object.unset('foo').
|
||||
*
|
||||
* @fires ObjectEvent
|
||||
* @api
|
||||
*/
|
||||
class BaseObject extends Observable {
|
||||
/**
|
||||
* @param {Object<string, *>} [opt_values] An object with key-value pairs.
|
||||
*/
|
||||
constructor(opt_values) {
|
||||
super();
|
||||
|
||||
/***
|
||||
* @type {ObjectOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.on;
|
||||
|
||||
/***
|
||||
* @type {ObjectOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.once;
|
||||
|
||||
/***
|
||||
* @type {ObjectOnSignature<void>}
|
||||
*/
|
||||
this.un;
|
||||
|
||||
// Call {@link module:ol/util.getUid} to ensure that the order of objects' ids is
|
||||
// the same as the order in which they were created. This also helps to
|
||||
// ensure that object properties are always added in the same order, which
|
||||
// helps many JavaScript engines generate faster code.
|
||||
getUid(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object<string, *>}
|
||||
*/
|
||||
this.values_ = null;
|
||||
|
||||
if (opt_values !== undefined) {
|
||||
this.setProperties(opt_values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value.
|
||||
* @param {string} key Key name.
|
||||
* @return {*} Value.
|
||||
* @api
|
||||
*/
|
||||
get(key) {
|
||||
let value;
|
||||
if (this.values_ && this.values_.hasOwnProperty(key)) {
|
||||
value = this.values_[key];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of object property names.
|
||||
* @return {Array<string>} List of property names.
|
||||
* @api
|
||||
*/
|
||||
getKeys() {
|
||||
return (this.values_ && Object.keys(this.values_)) || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an object of all property names and values.
|
||||
* @return {Object<string, *>} Object.
|
||||
* @api
|
||||
*/
|
||||
getProperties() {
|
||||
return (this.values_ && assign({}, this.values_)) || {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean} The object has properties.
|
||||
*/
|
||||
hasProperties() {
|
||||
return !!this.values_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key Key name.
|
||||
* @param {*} oldValue Old value.
|
||||
*/
|
||||
notify(key, oldValue) {
|
||||
let eventType;
|
||||
eventType = `change:${key}`;
|
||||
if (this.hasListener(eventType)) {
|
||||
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
|
||||
}
|
||||
eventType = ObjectEventType.PROPERTYCHANGE;
|
||||
if (this.hasListener(eventType)) {
|
||||
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key Key name.
|
||||
* @param {import("./events.js").Listener} listener Listener.
|
||||
*/
|
||||
addChangeListener(key, listener) {
|
||||
this.addEventListener(`change:${key}`, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key Key name.
|
||||
* @param {import("./events.js").Listener} listener Listener.
|
||||
*/
|
||||
removeChangeListener(key, listener) {
|
||||
this.removeEventListener(`change:${key}`, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value.
|
||||
* @param {string} key Key name.
|
||||
* @param {*} value Value.
|
||||
* @param {boolean} [opt_silent] Update without triggering an event.
|
||||
* @api
|
||||
*/
|
||||
set(key, value, opt_silent) {
|
||||
const values = this.values_ || (this.values_ = {});
|
||||
if (opt_silent) {
|
||||
values[key] = value;
|
||||
} else {
|
||||
const oldValue = values[key];
|
||||
values[key] = value;
|
||||
if (oldValue !== value) {
|
||||
this.notify(key, oldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a collection of key-value pairs. Note that this changes any existing
|
||||
* properties and adds new ones (it does not remove any existing properties).
|
||||
* @param {Object<string, *>} values Values.
|
||||
* @param {boolean} [opt_silent] Update without triggering an event.
|
||||
* @api
|
||||
*/
|
||||
setProperties(values, opt_silent) {
|
||||
for (const key in values) {
|
||||
this.set(key, values[key], opt_silent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply any properties from another object without triggering events.
|
||||
* @param {BaseObject} source The source object.
|
||||
* @protected
|
||||
*/
|
||||
applyProperties(source) {
|
||||
if (!source.values_) {
|
||||
return;
|
||||
}
|
||||
assign(this.values_ || (this.values_ = {}), source.values_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets a property.
|
||||
* @param {string} key Key name.
|
||||
* @param {boolean} [opt_silent] Unset without triggering an event.
|
||||
* @api
|
||||
*/
|
||||
unset(key, opt_silent) {
|
||||
if (this.values_ && key in this.values_) {
|
||||
const oldValue = this.values_[key];
|
||||
delete this.values_[key];
|
||||
if (isEmpty(this.values_)) {
|
||||
this.values_ = null;
|
||||
}
|
||||
if (!opt_silent) {
|
||||
this.notify(key, oldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default BaseObject;
|
||||
19
node_modules/ol/src/ObjectEventType.js
generated
vendored
Normal file
19
node_modules/ol/src/ObjectEventType.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @module ol/ObjectEventType
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Triggered when a property is changed.
|
||||
* @event module:ol/Object.ObjectEvent#propertychange
|
||||
* @api
|
||||
*/
|
||||
PROPERTYCHANGE: 'propertychange',
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {'propertychange'} Types
|
||||
*/
|
||||
192
node_modules/ol/src/Observable.js
generated
vendored
Normal file
192
node_modules/ol/src/Observable.js
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
/**
|
||||
* @module ol/Observable
|
||||
*/
|
||||
import EventTarget from './events/Target.js';
|
||||
import EventType from './events/EventType.js';
|
||||
import {listen, listenOnce, unlistenByKey} from './events.js';
|
||||
|
||||
/***
|
||||
* @template {string} Type
|
||||
* @template {Event|import("./events/Event.js").default} EventClass
|
||||
* @template Return
|
||||
* @typedef {(type: Type, listener: (event: EventClass) => ?) => Return} OnSignature
|
||||
*/
|
||||
|
||||
/***
|
||||
* @template {string} Type
|
||||
* @template Return
|
||||
* @typedef {(type: Type[], listener: (event: Event|import("./events/Event").default) => ?) => Return extends void ? void : Return[]} CombinedOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {'change'|'error'} EventTypes
|
||||
*/
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {OnSignature<EventTypes, import("./events/Event.js").default, Return> & CombinedOnSignature<EventTypes, Return>} ObservableOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* An event target providing convenient methods for listener registration
|
||||
* and unregistration. A generic `change` event is always available through
|
||||
* {@link module:ol/Observable~Observable#changed}.
|
||||
*
|
||||
* @fires import("./events/Event.js").default
|
||||
* @api
|
||||
*/
|
||||
class Observable extends EventTarget {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.on =
|
||||
/** @type {ObservableOnSignature<import("./events").EventsKey>} */ (
|
||||
this.onInternal
|
||||
);
|
||||
|
||||
this.once =
|
||||
/** @type {ObservableOnSignature<import("./events").EventsKey>} */ (
|
||||
this.onceInternal
|
||||
);
|
||||
|
||||
this.un = /** @type {ObservableOnSignature<void>} */ (this.unInternal);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.revision_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the revision counter and dispatches a 'change' event.
|
||||
* @api
|
||||
*/
|
||||
changed() {
|
||||
++this.revision_;
|
||||
this.dispatchEvent(EventType.CHANGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version number for this object. Each time the object is modified,
|
||||
* its version number will be incremented.
|
||||
* @return {number} Revision.
|
||||
* @api
|
||||
*/
|
||||
getRevision() {
|
||||
return this.revision_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string|Array<string>} type Type.
|
||||
* @param {function((Event|import("./events/Event").default)): ?} listener Listener.
|
||||
* @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Event key.
|
||||
* @protected
|
||||
*/
|
||||
onInternal(type, listener) {
|
||||
if (Array.isArray(type)) {
|
||||
const len = type.length;
|
||||
const keys = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
keys[i] = listen(this, type[i], listener);
|
||||
}
|
||||
return keys;
|
||||
} else {
|
||||
return listen(this, /** @type {string} */ (type), listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string|Array<string>} type Type.
|
||||
* @param {function((Event|import("./events/Event").default)): ?} listener Listener.
|
||||
* @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Event key.
|
||||
* @protected
|
||||
*/
|
||||
onceInternal(type, listener) {
|
||||
let key;
|
||||
if (Array.isArray(type)) {
|
||||
const len = type.length;
|
||||
key = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
key[i] = listenOnce(this, type[i], listener);
|
||||
}
|
||||
} else {
|
||||
key = listenOnce(this, /** @type {string} */ (type), listener);
|
||||
}
|
||||
/** @type {Object} */ (listener).ol_key = key;
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlisten for a certain type of event.
|
||||
* @param {string|Array<string>} type Type.
|
||||
* @param {function((Event|import("./events/Event").default)): ?} listener Listener.
|
||||
* @protected
|
||||
*/
|
||||
unInternal(type, listener) {
|
||||
const key = /** @type {Object} */ (listener).ol_key;
|
||||
if (key) {
|
||||
unByKey(key);
|
||||
} else if (Array.isArray(type)) {
|
||||
for (let i = 0, ii = type.length; i < ii; ++i) {
|
||||
this.removeEventListener(type[i], listener);
|
||||
}
|
||||
} else {
|
||||
this.removeEventListener(type, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen for a certain type of event.
|
||||
* @function
|
||||
* @param {string|Array<string>} type The event type or array of event types.
|
||||
* @param {function((Event|import("./events/Event").default)): ?} listener The listener function.
|
||||
* @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Unique key for the listener. If
|
||||
* called with an array of event types as the first argument, the return
|
||||
* will be an array of keys.
|
||||
* @api
|
||||
*/
|
||||
Observable.prototype.on;
|
||||
|
||||
/**
|
||||
* Listen once for a certain type of event.
|
||||
* @function
|
||||
* @param {string|Array<string>} type The event type or array of event types.
|
||||
* @param {function((Event|import("./events/Event").default)): ?} listener The listener function.
|
||||
* @return {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} Unique key for the listener. If
|
||||
* called with an array of event types as the first argument, the return
|
||||
* will be an array of keys.
|
||||
* @api
|
||||
*/
|
||||
Observable.prototype.once;
|
||||
|
||||
/**
|
||||
* Unlisten for a certain type of event.
|
||||
* @function
|
||||
* @param {string|Array<string>} type The event type or array of event types.
|
||||
* @param {function((Event|import("./events/Event").default)): ?} listener The listener function.
|
||||
* @api
|
||||
*/
|
||||
Observable.prototype.un;
|
||||
|
||||
/**
|
||||
* Removes an event listener using the key returned by `on()` or `once()`.
|
||||
* @param {import("./events.js").EventsKey|Array<import("./events.js").EventsKey>} key The key returned by `on()`
|
||||
* or `once()` (or an array of keys).
|
||||
* @api
|
||||
*/
|
||||
export function unByKey(key) {
|
||||
if (Array.isArray(key)) {
|
||||
for (let i = 0, ii = key.length; i < ii; ++i) {
|
||||
unlistenByKey(key[i]);
|
||||
}
|
||||
} else {
|
||||
unlistenByKey(/** @type {import("./events.js").EventsKey} */ (key));
|
||||
}
|
||||
}
|
||||
|
||||
export default Observable;
|
||||
603
node_modules/ol/src/Overlay.js
generated
vendored
Normal file
603
node_modules/ol/src/Overlay.js
generated
vendored
Normal file
@@ -0,0 +1,603 @@
|
||||
/**
|
||||
* @module ol/Overlay
|
||||
*/
|
||||
import BaseObject from './Object.js';
|
||||
import MapEventType from './MapEventType.js';
|
||||
import {CLASS_SELECTABLE} from './css.js';
|
||||
import {containsExtent} from './extent.js';
|
||||
import {listen, unlistenByKey} from './events.js';
|
||||
import {outerHeight, outerWidth, removeChildren, removeNode} from './dom.js';
|
||||
|
||||
/**
|
||||
* @typedef {'bottom-left' | 'bottom-center' | 'bottom-right' | 'center-left' | 'center-center' | 'center-right' | 'top-left' | 'top-center' | 'top-right'} Positioning
|
||||
* The overlay position: `'bottom-left'`, `'bottom-center'`, `'bottom-right'`,
|
||||
* `'center-left'`, `'center-center'`, `'center-right'`, `'top-left'`,
|
||||
* `'top-center'`, or `'top-right'`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {number|string} [id] Set the overlay id. The overlay id can be used
|
||||
* with the {@link module:ol/Map~Map#getOverlayById} method.
|
||||
* @property {HTMLElement} [element] The overlay element.
|
||||
* @property {Array<number>} [offset=[0, 0]] Offsets in pixels used when positioning
|
||||
* the overlay. The first element in the
|
||||
* array is the horizontal offset. A positive value shifts the overlay right.
|
||||
* The second element in the array is the vertical offset. A positive value
|
||||
* shifts the overlay down.
|
||||
* @property {import("./coordinate.js").Coordinate} [position] The overlay position
|
||||
* in map projection.
|
||||
* @property {Positioning} [positioning='top-left'] Defines how
|
||||
* the overlay is actually positioned with respect to its `position` property.
|
||||
* Possible values are `'bottom-left'`, `'bottom-center'`, `'bottom-right'`,
|
||||
* `'center-left'`, `'center-center'`, `'center-right'`, `'top-left'`,
|
||||
* `'top-center'`, and `'top-right'`.
|
||||
* @property {boolean} [stopEvent=true] Whether event propagation to the map
|
||||
* viewport should be stopped. If `true` the overlay is placed in the same
|
||||
* container as that of the controls (CSS class name
|
||||
* `ol-overlaycontainer-stopevent`); if `false` it is placed in the container
|
||||
* with CSS class name specified by the `className` property.
|
||||
* @property {boolean} [insertFirst=true] Whether the overlay is inserted first
|
||||
* in the overlay container, or appended. If the overlay is placed in the same
|
||||
* container as that of the controls (see the `stopEvent` option) you will
|
||||
* probably set `insertFirst` to `true` so the overlay is displayed below the
|
||||
* controls.
|
||||
* @property {PanIntoViewOptions|boolean} [autoPan=false] Pan the map when calling
|
||||
* `setPosition`, so that the overlay is entirely visible in the current viewport?
|
||||
* If `true` (deprecated), then `autoPanAnimation` and `autoPanMargin` will be
|
||||
* used to determine the panning parameters; if an object is supplied then other
|
||||
* parameters are ignored.
|
||||
* @property {PanOptions} [autoPanAnimation] The animation options used to pan
|
||||
* the overlay into view. This animation is only used when `autoPan` is enabled.
|
||||
* A `duration` and `easing` may be provided to customize the animation.
|
||||
* Deprecated and ignored if `autoPan` is supplied as an object.
|
||||
* @property {number} [autoPanMargin=20] The margin (in pixels) between the
|
||||
* overlay and the borders of the map when autopanning. Deprecated and ignored
|
||||
* if `autoPan` is supplied as an object.
|
||||
* @property {PanIntoViewOptions} [autoPanOptions] The options to use for the
|
||||
* autoPan. This is only used when `autoPan` is enabled and has preference over
|
||||
* the individual `autoPanMargin` and `autoPanOptions`.
|
||||
* @property {string} [className='ol-overlay-container ol-selectable'] CSS class
|
||||
* name.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PanOptions
|
||||
* @property {number} [duration=1000] The duration of the animation in
|
||||
* milliseconds.
|
||||
* @property {function(number):number} [easing] The easing function to use. Can
|
||||
* be one from {@link module:ol/easing} or a custom function.
|
||||
* Default is {@link module:ol/easing.inAndOut}.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PanIntoViewOptions
|
||||
* @property {PanOptions} [animation={}] The animation parameters for the pan
|
||||
* @property {number} [margin=20] The margin (in pixels) between the
|
||||
* overlay and the borders of the map when panning into view.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
* @protected
|
||||
*/
|
||||
const Property = {
|
||||
ELEMENT: 'element',
|
||||
MAP: 'map',
|
||||
OFFSET: 'offset',
|
||||
POSITION: 'position',
|
||||
POSITIONING: 'positioning',
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {import("./ObjectEventType").Types|'change:element'|'change:map'|'change:offset'|'change:position'|
|
||||
* 'change:positioning'} OverlayObjectEventTypes
|
||||
*/
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {import("./Observable").OnSignature<import("./Observable").EventTypes, import("./events/Event.js").default, Return> &
|
||||
* import("./Observable").OnSignature<OverlayObjectEventTypes, import("./Object").ObjectEvent, Return> &
|
||||
* import("./Observable").CombinedOnSignature<import("./Observable").EventTypes|OverlayObjectEventTypes, Return>} OverlayOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* An element to be displayed over the map and attached to a single map
|
||||
* location. Like {@link module:ol/control/Control~Control}, Overlays are
|
||||
* visible widgets. Unlike Controls, they are not in a fixed position on the
|
||||
* screen, but are tied to a geographical coordinate, so panning the map will
|
||||
* move an Overlay but not a Control.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* import Overlay from 'ol/Overlay';
|
||||
*
|
||||
* var popup = new Overlay({
|
||||
* element: document.getElementById('popup')
|
||||
* });
|
||||
* popup.setPosition(coordinate);
|
||||
* map.addOverlay(popup);
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Overlay extends BaseObject {
|
||||
/**
|
||||
* @param {Options} options Overlay options.
|
||||
*/
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
/***
|
||||
* @type {OverlayOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.on;
|
||||
|
||||
/***
|
||||
* @type {OverlayOnSignature<import("./events").EventsKey>}
|
||||
*/
|
||||
this.once;
|
||||
|
||||
/***
|
||||
* @type {OverlayOnSignature<void>}
|
||||
*/
|
||||
this.un;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Options}
|
||||
*/
|
||||
this.options = options;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {number|string|undefined}
|
||||
*/
|
||||
this.id = options.id;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.insertFirst =
|
||||
options.insertFirst !== undefined ? options.insertFirst : true;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.stopEvent = options.stopEvent !== undefined ? options.stopEvent : true;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.element = document.createElement('div');
|
||||
this.element.className =
|
||||
options.className !== undefined
|
||||
? options.className
|
||||
: 'ol-overlay-container ' + CLASS_SELECTABLE;
|
||||
this.element.style.position = 'absolute';
|
||||
this.element.style.pointerEvents = 'auto';
|
||||
|
||||
let autoPan = options.autoPan;
|
||||
if (autoPan && 'object' !== typeof autoPan) {
|
||||
autoPan = {
|
||||
animation: options.autoPanAnimation,
|
||||
margin: options.autoPanMargin,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @protected
|
||||
* @type {PanIntoViewOptions|false}
|
||||
*/
|
||||
this.autoPan = /** @type {PanIntoViewOptions} */ (autoPan) || false;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {{transform_: string,
|
||||
* visible: boolean}}
|
||||
*/
|
||||
this.rendered = {
|
||||
transform_: '',
|
||||
visible: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {?import("./events.js").EventsKey}
|
||||
*/
|
||||
this.mapPostrenderListenerKey = null;
|
||||
|
||||
this.addChangeListener(Property.ELEMENT, this.handleElementChanged);
|
||||
this.addChangeListener(Property.MAP, this.handleMapChanged);
|
||||
this.addChangeListener(Property.OFFSET, this.handleOffsetChanged);
|
||||
this.addChangeListener(Property.POSITION, this.handlePositionChanged);
|
||||
this.addChangeListener(Property.POSITIONING, this.handlePositioningChanged);
|
||||
|
||||
if (options.element !== undefined) {
|
||||
this.setElement(options.element);
|
||||
}
|
||||
|
||||
this.setOffset(options.offset !== undefined ? options.offset : [0, 0]);
|
||||
|
||||
this.setPositioning(options.positioning || 'top-left');
|
||||
|
||||
if (options.position !== undefined) {
|
||||
this.setPosition(options.position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DOM element of this overlay.
|
||||
* @return {HTMLElement|undefined} The Element containing the overlay.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getElement() {
|
||||
return /** @type {HTMLElement|undefined} */ (this.get(Property.ELEMENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the overlay identifier which is set on constructor.
|
||||
* @return {number|string|undefined} Id.
|
||||
* @api
|
||||
*/
|
||||
getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map associated with this overlay.
|
||||
* @return {import("./PluggableMap.js").default|null} The map that the
|
||||
* overlay is part of.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getMap() {
|
||||
return /** @type {import("./PluggableMap.js").default|null} */ (
|
||||
this.get(Property.MAP) || null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offset of this overlay.
|
||||
* @return {Array<number>} The offset.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getOffset() {
|
||||
return /** @type {Array<number>} */ (this.get(Property.OFFSET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current position of this overlay.
|
||||
* @return {import("./coordinate.js").Coordinate|undefined} The spatial point that the overlay is
|
||||
* anchored at.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getPosition() {
|
||||
return /** @type {import("./coordinate.js").Coordinate|undefined} */ (
|
||||
this.get(Property.POSITION)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current positioning of this overlay.
|
||||
* @return {Positioning} How the overlay is positioned
|
||||
* relative to its point on the map.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getPositioning() {
|
||||
return /** @type {Positioning} */ (this.get(Property.POSITIONING));
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
handleElementChanged() {
|
||||
removeChildren(this.element);
|
||||
const element = this.getElement();
|
||||
if (element) {
|
||||
this.element.appendChild(element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
handleMapChanged() {
|
||||
if (this.mapPostrenderListenerKey) {
|
||||
removeNode(this.element);
|
||||
unlistenByKey(this.mapPostrenderListenerKey);
|
||||
this.mapPostrenderListenerKey = null;
|
||||
}
|
||||
const map = this.getMap();
|
||||
if (map) {
|
||||
this.mapPostrenderListenerKey = listen(
|
||||
map,
|
||||
MapEventType.POSTRENDER,
|
||||
this.render,
|
||||
this
|
||||
);
|
||||
this.updatePixelPosition();
|
||||
const container = this.stopEvent
|
||||
? map.getOverlayContainerStopEvent()
|
||||
: map.getOverlayContainer();
|
||||
if (this.insertFirst) {
|
||||
container.insertBefore(this.element, container.childNodes[0] || null);
|
||||
} else {
|
||||
container.appendChild(this.element);
|
||||
}
|
||||
this.performAutoPan();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
render() {
|
||||
this.updatePixelPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
handleOffsetChanged() {
|
||||
this.updatePixelPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
handlePositionChanged() {
|
||||
this.updatePixelPosition();
|
||||
this.performAutoPan();
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
handlePositioningChanged() {
|
||||
this.updatePixelPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DOM element to be associated with this overlay.
|
||||
* @param {HTMLElement|undefined} element The Element containing the overlay.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setElement(element) {
|
||||
this.set(Property.ELEMENT, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the map to be associated with this overlay.
|
||||
* @param {import("./PluggableMap.js").default|null} map The map that the
|
||||
* overlay is part of. Pass `null` to just remove the overlay from the current map.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setMap(map) {
|
||||
this.set(Property.MAP, map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset for this overlay.
|
||||
* @param {Array<number>} offset Offset.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setOffset(offset) {
|
||||
this.set(Property.OFFSET, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position for this overlay. If the position is `undefined` the
|
||||
* overlay is hidden.
|
||||
* @param {import("./coordinate.js").Coordinate|undefined} position The spatial point that the overlay
|
||||
* is anchored at.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setPosition(position) {
|
||||
this.set(Property.POSITION, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pan the map so that the overlay is entirely visible in the current viewport
|
||||
* (if necessary) using the configured autoPan parameters
|
||||
* @protected
|
||||
*/
|
||||
performAutoPan() {
|
||||
if (this.autoPan) {
|
||||
this.panIntoView(this.autoPan);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pan the map so that the overlay is entirely visible in the current viewport
|
||||
* (if necessary).
|
||||
* @param {PanIntoViewOptions} [opt_panIntoViewOptions] Options for the pan action
|
||||
* @api
|
||||
*/
|
||||
panIntoView(opt_panIntoViewOptions) {
|
||||
const map = this.getMap();
|
||||
|
||||
if (!map || !map.getTargetElement() || !this.get(Property.POSITION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mapRect = this.getRect(map.getTargetElement(), map.getSize());
|
||||
const element = this.getElement();
|
||||
const overlayRect = this.getRect(element, [
|
||||
outerWidth(element),
|
||||
outerHeight(element),
|
||||
]);
|
||||
|
||||
const panIntoViewOptions = opt_panIntoViewOptions || {};
|
||||
|
||||
const myMargin =
|
||||
panIntoViewOptions.margin === undefined ? 20 : panIntoViewOptions.margin;
|
||||
if (!containsExtent(mapRect, overlayRect)) {
|
||||
// the overlay is not completely inside the viewport, so pan the map
|
||||
const offsetLeft = overlayRect[0] - mapRect[0];
|
||||
const offsetRight = mapRect[2] - overlayRect[2];
|
||||
const offsetTop = overlayRect[1] - mapRect[1];
|
||||
const offsetBottom = mapRect[3] - overlayRect[3];
|
||||
|
||||
const delta = [0, 0];
|
||||
if (offsetLeft < 0) {
|
||||
// move map to the left
|
||||
delta[0] = offsetLeft - myMargin;
|
||||
} else if (offsetRight < 0) {
|
||||
// move map to the right
|
||||
delta[0] = Math.abs(offsetRight) + myMargin;
|
||||
}
|
||||
if (offsetTop < 0) {
|
||||
// move map up
|
||||
delta[1] = offsetTop - myMargin;
|
||||
} else if (offsetBottom < 0) {
|
||||
// move map down
|
||||
delta[1] = Math.abs(offsetBottom) + myMargin;
|
||||
}
|
||||
|
||||
if (delta[0] !== 0 || delta[1] !== 0) {
|
||||
const center = /** @type {import("./coordinate.js").Coordinate} */ (
|
||||
map.getView().getCenterInternal()
|
||||
);
|
||||
const centerPx = map.getPixelFromCoordinateInternal(center);
|
||||
if (!centerPx) {
|
||||
return;
|
||||
}
|
||||
const newCenterPx = [centerPx[0] + delta[0], centerPx[1] + delta[1]];
|
||||
|
||||
const panOptions = panIntoViewOptions.animation || {};
|
||||
map.getView().animateInternal({
|
||||
center: map.getCoordinateFromPixelInternal(newCenterPx),
|
||||
duration: panOptions.duration,
|
||||
easing: panOptions.easing,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extent of an element relative to the document
|
||||
* @param {HTMLElement} element The element.
|
||||
* @param {import("./size.js").Size} size The size of the element.
|
||||
* @return {import("./extent.js").Extent} The extent.
|
||||
* @protected
|
||||
*/
|
||||
getRect(element, size) {
|
||||
const box = element.getBoundingClientRect();
|
||||
const offsetX = box.left + window.pageXOffset;
|
||||
const offsetY = box.top + window.pageYOffset;
|
||||
return [offsetX, offsetY, offsetX + size[0], offsetY + size[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the positioning for this overlay.
|
||||
* @param {Positioning} positioning how the overlay is
|
||||
* positioned relative to its point on the map.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setPositioning(positioning) {
|
||||
this.set(Property.POSITIONING, positioning);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify the visibility of the element.
|
||||
* @param {boolean} visible Element visibility.
|
||||
* @protected
|
||||
*/
|
||||
setVisible(visible) {
|
||||
if (this.rendered.visible !== visible) {
|
||||
this.element.style.display = visible ? '' : 'none';
|
||||
this.rendered.visible = visible;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update pixel position.
|
||||
* @protected
|
||||
*/
|
||||
updatePixelPosition() {
|
||||
const map = this.getMap();
|
||||
const position = this.getPosition();
|
||||
if (!map || !map.isRendered() || !position) {
|
||||
this.setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const pixel = map.getPixelFromCoordinate(position);
|
||||
const mapSize = map.getSize();
|
||||
this.updateRenderedPosition(pixel, mapSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./pixel.js").Pixel} pixel The pixel location.
|
||||
* @param {import("./size.js").Size|undefined} mapSize The map size.
|
||||
* @protected
|
||||
*/
|
||||
updateRenderedPosition(pixel, mapSize) {
|
||||
const style = this.element.style;
|
||||
const offset = this.getOffset();
|
||||
|
||||
const positioning = this.getPositioning();
|
||||
|
||||
this.setVisible(true);
|
||||
|
||||
const x = Math.round(pixel[0] + offset[0]) + 'px';
|
||||
const y = Math.round(pixel[1] + offset[1]) + 'px';
|
||||
let posX = '0%';
|
||||
let posY = '0%';
|
||||
if (
|
||||
positioning == 'bottom-right' ||
|
||||
positioning == 'center-right' ||
|
||||
positioning == 'top-right'
|
||||
) {
|
||||
posX = '-100%';
|
||||
} else if (
|
||||
positioning == 'bottom-center' ||
|
||||
positioning == 'center-center' ||
|
||||
positioning == 'top-center'
|
||||
) {
|
||||
posX = '-50%';
|
||||
}
|
||||
if (
|
||||
positioning == 'bottom-left' ||
|
||||
positioning == 'bottom-center' ||
|
||||
positioning == 'bottom-right'
|
||||
) {
|
||||
posY = '-100%';
|
||||
} else if (
|
||||
positioning == 'center-left' ||
|
||||
positioning == 'center-center' ||
|
||||
positioning == 'center-right'
|
||||
) {
|
||||
posY = '-50%';
|
||||
}
|
||||
const transform = `translate(${posX}, ${posY}) translate(${x}, ${y})`;
|
||||
if (this.rendered.transform_ != transform) {
|
||||
this.rendered.transform_ = transform;
|
||||
style.transform = transform;
|
||||
// @ts-ignore IE9
|
||||
style.msTransform = transform;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the options this Overlay has been created with
|
||||
* @return {Options} overlay options
|
||||
*/
|
||||
getOptions() {
|
||||
return this.options;
|
||||
}
|
||||
}
|
||||
|
||||
export default Overlay;
|
||||
1815
node_modules/ol/src/PluggableMap.js
generated
vendored
Normal file
1815
node_modules/ol/src/PluggableMap.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
317
node_modules/ol/src/Tile.js
generated
vendored
Normal file
317
node_modules/ol/src/Tile.js
generated
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
/**
|
||||
* @module ol/Tile
|
||||
*/
|
||||
import EventTarget from './events/Target.js';
|
||||
import EventType from './events/EventType.js';
|
||||
import TileState from './TileState.js';
|
||||
import {abstract} from './util.js';
|
||||
import {easeIn} from './easing.js';
|
||||
|
||||
/**
|
||||
* A function that takes an {@link module:ol/Tile~Tile} for the tile and a
|
||||
* `{string}` for the url as arguments. The default is
|
||||
* ```js
|
||||
* source.setTileLoadFunction(function(tile, src) {
|
||||
* tile.getImage().src = src;
|
||||
* });
|
||||
* ```
|
||||
* For more fine grained control, the load function can use fetch or XMLHttpRequest and involve
|
||||
* error handling:
|
||||
*
|
||||
* ```js
|
||||
* import TileState from 'ol/TileState';
|
||||
*
|
||||
* source.setTileLoadFunction(function(tile, src) {
|
||||
* var xhr = new XMLHttpRequest();
|
||||
* xhr.responseType = 'blob';
|
||||
* xhr.addEventListener('loadend', function (evt) {
|
||||
* var data = this.response;
|
||||
* if (data !== undefined) {
|
||||
* tile.getImage().src = URL.createObjectURL(data);
|
||||
* } else {
|
||||
* tile.setState(TileState.ERROR);
|
||||
* }
|
||||
* });
|
||||
* xhr.addEventListener('error', function () {
|
||||
* tile.setState(TileState.ERROR);
|
||||
* });
|
||||
* xhr.open('GET', src);
|
||||
* xhr.send();
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @typedef {function(Tile, string): void} LoadFunction
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@link module:ol/source/Tile~TileSource} sources use a function of this type to get
|
||||
* the url that provides a tile for a given tile coordinate.
|
||||
*
|
||||
* This function takes an {@link module:ol/tilecoord~TileCoord} for the tile
|
||||
* coordinate, a `{number}` representing the pixel ratio and a
|
||||
* {@link module:ol/proj/Projection~Projection} for the projection as arguments
|
||||
* and returns a `{string}` representing the tile URL, or undefined if no tile
|
||||
* should be requested for the passed tile coordinate.
|
||||
*
|
||||
* @typedef {function(import("./tilecoord.js").TileCoord, number,
|
||||
* import("./proj/Projection.js").default): (string|undefined)} UrlFunction
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {number} [transition=250] A duration for tile opacity
|
||||
* transitions in milliseconds. A duration of 0 disables the opacity transition.
|
||||
* @property {boolean} [interpolate=false] Use interpolated values when resampling. By default,
|
||||
* the nearest neighbor is used when resampling.
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Base class for tiles.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
class Tile extends EventTarget {
|
||||
/**
|
||||
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||
* @param {import("./TileState.js").default} state State.
|
||||
* @param {Options} [opt_options] Tile options.
|
||||
*/
|
||||
constructor(tileCoord, state, opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {import("./tilecoord.js").TileCoord}
|
||||
*/
|
||||
this.tileCoord = tileCoord;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {import("./TileState.js").default}
|
||||
*/
|
||||
this.state = state;
|
||||
|
||||
/**
|
||||
* An "interim" tile for this tile. The interim tile may be used while this
|
||||
* one is loading, for "smooth" transitions when changing params/dimensions
|
||||
* on the source.
|
||||
* @type {Tile}
|
||||
*/
|
||||
this.interimTile = null;
|
||||
|
||||
/**
|
||||
* A key assigned to the tile. This is used by the tile source to determine
|
||||
* if this tile can effectively be used, or if a new tile should be created
|
||||
* and this one be used as an interim tile for this new tile.
|
||||
* @type {string}
|
||||
*/
|
||||
this.key = '';
|
||||
|
||||
/**
|
||||
* The duration for the opacity transition.
|
||||
* @type {number}
|
||||
*/
|
||||
this.transition_ =
|
||||
options.transition === undefined ? 250 : options.transition;
|
||||
|
||||
/**
|
||||
* Lookup of start times for rendering transitions. If the start time is
|
||||
* equal to -1, the transition is complete.
|
||||
* @type {Object<string, number>}
|
||||
*/
|
||||
this.transitionStarts_ = {};
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.interpolate = !!options.interpolate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
changed() {
|
||||
this.dispatchEvent(EventType.CHANGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the tile cache when the tile is removed from the cache due to expiry
|
||||
*/
|
||||
release() {}
|
||||
|
||||
/**
|
||||
* @return {string} Key.
|
||||
*/
|
||||
getKey() {
|
||||
return this.key + '/' + this.tileCoord;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interim tile most suitable for rendering using the chain of interim
|
||||
* tiles. This corresponds to the most recent tile that has been loaded, if no
|
||||
* such tile exists, the original tile is returned.
|
||||
* @return {!Tile} Best tile for rendering.
|
||||
*/
|
||||
getInterimTile() {
|
||||
if (!this.interimTile) {
|
||||
//empty chain
|
||||
return this;
|
||||
}
|
||||
let tile = this.interimTile;
|
||||
|
||||
// find the first loaded tile and return it. Since the chain is sorted in
|
||||
// decreasing order of creation time, there is no need to search the remainder
|
||||
// of the list (all those tiles correspond to older requests and will be
|
||||
// cleaned up by refreshInterimChain)
|
||||
do {
|
||||
if (tile.getState() == TileState.LOADED) {
|
||||
// Show tile immediately instead of fading it in after loading, because
|
||||
// the interim tile is in place already
|
||||
this.transition_ = 0;
|
||||
return tile;
|
||||
}
|
||||
tile = tile.interimTile;
|
||||
} while (tile);
|
||||
|
||||
// we can not find a better tile
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes through the chain of interim tiles and discards sections of the chain
|
||||
* that are no longer relevant.
|
||||
*/
|
||||
refreshInterimChain() {
|
||||
if (!this.interimTile) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tile = this.interimTile;
|
||||
|
||||
/**
|
||||
* @type {Tile}
|
||||
*/
|
||||
let prev = this;
|
||||
|
||||
do {
|
||||
if (tile.getState() == TileState.LOADED) {
|
||||
//we have a loaded tile, we can discard the rest of the list
|
||||
//we would could abort any LOADING tile request
|
||||
//older than this tile (i.e. any LOADING tile following this entry in the chain)
|
||||
tile.interimTile = null;
|
||||
break;
|
||||
} else if (tile.getState() == TileState.LOADING) {
|
||||
//keep this LOADING tile any loaded tiles later in the chain are
|
||||
//older than this tile, so we're still interested in the request
|
||||
prev = tile;
|
||||
} else if (tile.getState() == TileState.IDLE) {
|
||||
//the head of the list is the most current tile, we don't need
|
||||
//to start any other requests for this chain
|
||||
prev.interimTile = tile.interimTile;
|
||||
} else {
|
||||
prev = tile;
|
||||
}
|
||||
tile = prev.interimTile;
|
||||
} while (tile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tile coordinate for this tile.
|
||||
* @return {import("./tilecoord.js").TileCoord} The tile coordinate.
|
||||
* @api
|
||||
*/
|
||||
getTileCoord() {
|
||||
return this.tileCoord;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./TileState.js").default} State.
|
||||
*/
|
||||
getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state of this tile. If you write your own {@link module:ol/Tile~LoadFunction tileLoadFunction} ,
|
||||
* it is important to set the state correctly to {@link module:ol/TileState~ERROR}
|
||||
* when the tile cannot be loaded. Otherwise the tile cannot be removed from
|
||||
* the tile queue and will block other requests.
|
||||
* @param {import("./TileState.js").default} state State.
|
||||
* @api
|
||||
*/
|
||||
setState(state) {
|
||||
if (this.state !== TileState.ERROR && this.state > state) {
|
||||
throw new Error('Tile load sequence violation');
|
||||
}
|
||||
this.state = state;
|
||||
this.changed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the image or retry if loading previously failed.
|
||||
* Loading is taken care of by the tile queue, and calling this method is
|
||||
* only needed for preloading or for reloading in case of an error.
|
||||
* @abstract
|
||||
* @api
|
||||
*/
|
||||
load() {
|
||||
abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the alpha value for rendering.
|
||||
* @param {string} id An id for the renderer.
|
||||
* @param {number} time The render frame time.
|
||||
* @return {number} A number between 0 and 1.
|
||||
*/
|
||||
getAlpha(id, time) {
|
||||
if (!this.transition_) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
let start = this.transitionStarts_[id];
|
||||
if (!start) {
|
||||
start = time;
|
||||
this.transitionStarts_[id] = start;
|
||||
} else if (start === -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const delta = time - start + 1000 / 60; // avoid rendering at 0
|
||||
if (delta >= this.transition_) {
|
||||
return 1;
|
||||
}
|
||||
return easeIn(delta / this.transition_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a tile is in an alpha transition. A tile is considered in
|
||||
* transition if tile.getAlpha() has not yet been called or has been called
|
||||
* and returned 1.
|
||||
* @param {string} id An id for the renderer.
|
||||
* @return {boolean} The tile is in transition.
|
||||
*/
|
||||
inTransition(id) {
|
||||
if (!this.transition_) {
|
||||
return false;
|
||||
}
|
||||
return this.transitionStarts_[id] !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a transition as complete.
|
||||
* @param {string} id An id for the renderer.
|
||||
*/
|
||||
endTransition(id) {
|
||||
if (this.transition_) {
|
||||
this.transitionStarts_[id] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Tile;
|
||||
43
node_modules/ol/src/TileCache.js
generated
vendored
Normal file
43
node_modules/ol/src/TileCache.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @module ol/TileCache
|
||||
*/
|
||||
import LRUCache from './structs/LRUCache.js';
|
||||
import {fromKey, getKey} from './tilecoord.js';
|
||||
|
||||
class TileCache extends LRUCache {
|
||||
/**
|
||||
* @param {!Object<string, boolean>} usedTiles Used tiles.
|
||||
*/
|
||||
expireCache(usedTiles) {
|
||||
while (this.canExpireCache()) {
|
||||
const tile = this.peekLast();
|
||||
if (tile.getKey() in usedTiles) {
|
||||
break;
|
||||
} else {
|
||||
this.pop().release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune all tiles from the cache that don't have the same z as the newest tile.
|
||||
*/
|
||||
pruneExceptNewestZ() {
|
||||
if (this.getCount() === 0) {
|
||||
return;
|
||||
}
|
||||
const key = this.peekFirstKey();
|
||||
const tileCoord = fromKey(key);
|
||||
const z = tileCoord[0];
|
||||
this.forEach(
|
||||
function (tile) {
|
||||
if (tile.tileCoord[0] !== z) {
|
||||
this.remove(getKey(tile.tileCoord));
|
||||
tile.release();
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TileCache;
|
||||
162
node_modules/ol/src/TileQueue.js
generated
vendored
Normal file
162
node_modules/ol/src/TileQueue.js
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @module ol/TileQueue
|
||||
*/
|
||||
import EventType from './events/EventType.js';
|
||||
import PriorityQueue, {DROP} from './structs/PriorityQueue.js';
|
||||
import TileState from './TileState.js';
|
||||
|
||||
/**
|
||||
* @typedef {function(import("./Tile.js").default, string, import("./coordinate.js").Coordinate, number): number} PriorityFunction
|
||||
*/
|
||||
|
||||
class TileQueue extends PriorityQueue {
|
||||
/**
|
||||
* @param {PriorityFunction} tilePriorityFunction Tile priority function.
|
||||
* @param {function(): ?} tileChangeCallback Function called on each tile change event.
|
||||
*/
|
||||
constructor(tilePriorityFunction, tileChangeCallback) {
|
||||
super(
|
||||
/**
|
||||
* @param {Array} element Element.
|
||||
* @return {number} Priority.
|
||||
*/
|
||||
function (element) {
|
||||
return tilePriorityFunction.apply(null, element);
|
||||
},
|
||||
/**
|
||||
* @param {Array} element Element.
|
||||
* @return {string} Key.
|
||||
*/
|
||||
function (element) {
|
||||
return /** @type {import("./Tile.js").default} */ (element[0]).getKey();
|
||||
}
|
||||
);
|
||||
|
||||
/** @private */
|
||||
this.boundHandleTileChange_ = this.handleTileChange.bind(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {function(): ?}
|
||||
*/
|
||||
this.tileChangeCallback_ = tileChangeCallback;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.tilesLoading_ = 0;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object<string,boolean>}
|
||||
*/
|
||||
this.tilesLoadingKeys_ = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array} element Element.
|
||||
* @return {boolean} The element was added to the queue.
|
||||
*/
|
||||
enqueue(element) {
|
||||
const added = super.enqueue(element);
|
||||
if (added) {
|
||||
const tile = element[0];
|
||||
tile.addEventListener(EventType.CHANGE, this.boundHandleTileChange_);
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Number of tiles loading.
|
||||
*/
|
||||
getTilesLoading() {
|
||||
return this.tilesLoading_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./events/Event.js").default} event Event.
|
||||
* @protected
|
||||
*/
|
||||
handleTileChange(event) {
|
||||
const tile = /** @type {import("./Tile.js").default} */ (event.target);
|
||||
const state = tile.getState();
|
||||
if (
|
||||
state === TileState.LOADED ||
|
||||
state === TileState.ERROR ||
|
||||
state === TileState.EMPTY
|
||||
) {
|
||||
tile.removeEventListener(EventType.CHANGE, this.boundHandleTileChange_);
|
||||
const tileKey = tile.getKey();
|
||||
if (tileKey in this.tilesLoadingKeys_) {
|
||||
delete this.tilesLoadingKeys_[tileKey];
|
||||
--this.tilesLoading_;
|
||||
}
|
||||
this.tileChangeCallback_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} maxTotalLoading Maximum number tiles to load simultaneously.
|
||||
* @param {number} maxNewLoads Maximum number of new tiles to load.
|
||||
*/
|
||||
loadMoreTiles(maxTotalLoading, maxNewLoads) {
|
||||
let newLoads = 0;
|
||||
let state, tile, tileKey;
|
||||
while (
|
||||
this.tilesLoading_ < maxTotalLoading &&
|
||||
newLoads < maxNewLoads &&
|
||||
this.getCount() > 0
|
||||
) {
|
||||
tile = /** @type {import("./Tile.js").default} */ (this.dequeue()[0]);
|
||||
tileKey = tile.getKey();
|
||||
state = tile.getState();
|
||||
if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) {
|
||||
this.tilesLoadingKeys_[tileKey] = true;
|
||||
++this.tilesLoading_;
|
||||
++newLoads;
|
||||
tile.load();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default TileQueue;
|
||||
|
||||
/**
|
||||
* @param {import('./PluggableMap.js').FrameState} frameState Frame state.
|
||||
* @param {import("./Tile.js").default} tile Tile.
|
||||
* @param {string} tileSourceKey Tile source key.
|
||||
* @param {import("./coordinate.js").Coordinate} tileCenter Tile center.
|
||||
* @param {number} tileResolution Tile resolution.
|
||||
* @return {number} Tile priority.
|
||||
*/
|
||||
export function getTilePriority(
|
||||
frameState,
|
||||
tile,
|
||||
tileSourceKey,
|
||||
tileCenter,
|
||||
tileResolution
|
||||
) {
|
||||
// Filter out tiles at higher zoom levels than the current zoom level, or that
|
||||
// are outside the visible extent.
|
||||
if (!frameState || !(tileSourceKey in frameState.wantedTiles)) {
|
||||
return DROP;
|
||||
}
|
||||
if (!frameState.wantedTiles[tileSourceKey][tile.getKey()]) {
|
||||
return DROP;
|
||||
}
|
||||
// Prioritize the highest zoom level tiles closest to the focus.
|
||||
// Tiles at higher zoom levels are prioritized using Math.log(tileResolution).
|
||||
// Within a zoom level, tiles are prioritized by the distance in pixels between
|
||||
// the center of the tile and the center of the viewport. The factor of 65536
|
||||
// means that the prioritization should behave as desired for tiles up to
|
||||
// 65536 * Math.log(2) = 45426 pixels from the focus.
|
||||
const center = frameState.viewState.center;
|
||||
const deltaX = tileCenter[0] - center[0];
|
||||
const deltaY = tileCenter[1] - center[1];
|
||||
return (
|
||||
65536 * Math.log(tileResolution) +
|
||||
Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution
|
||||
);
|
||||
}
|
||||
154
node_modules/ol/src/TileRange.js
generated
vendored
Normal file
154
node_modules/ol/src/TileRange.js
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* @module ol/TileRange
|
||||
*/
|
||||
|
||||
/**
|
||||
* A representation of a contiguous block of tiles. A tile range is specified
|
||||
* by its min/max tile coordinates and is inclusive of coordinates.
|
||||
*/
|
||||
class TileRange {
|
||||
/**
|
||||
* @param {number} minX Minimum X.
|
||||
* @param {number} maxX Maximum X.
|
||||
* @param {number} minY Minimum Y.
|
||||
* @param {number} maxY Maximum Y.
|
||||
*/
|
||||
constructor(minX, maxX, minY, maxY) {
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.minX = minX;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxX = maxX;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.minY = minY;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxY = maxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||
* @return {boolean} Contains tile coordinate.
|
||||
*/
|
||||
contains(tileCoord) {
|
||||
return this.containsXY(tileCoord[1], tileCoord[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TileRange} tileRange Tile range.
|
||||
* @return {boolean} Contains.
|
||||
*/
|
||||
containsTileRange(tileRange) {
|
||||
return (
|
||||
this.minX <= tileRange.minX &&
|
||||
tileRange.maxX <= this.maxX &&
|
||||
this.minY <= tileRange.minY &&
|
||||
tileRange.maxY <= this.maxY
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} x Tile coordinate x.
|
||||
* @param {number} y Tile coordinate y.
|
||||
* @return {boolean} Contains coordinate.
|
||||
*/
|
||||
containsXY(x, y) {
|
||||
return this.minX <= x && x <= this.maxX && this.minY <= y && y <= this.maxY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TileRange} tileRange Tile range.
|
||||
* @return {boolean} Equals.
|
||||
*/
|
||||
equals(tileRange) {
|
||||
return (
|
||||
this.minX == tileRange.minX &&
|
||||
this.minY == tileRange.minY &&
|
||||
this.maxX == tileRange.maxX &&
|
||||
this.maxY == tileRange.maxY
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TileRange} tileRange Tile range.
|
||||
*/
|
||||
extend(tileRange) {
|
||||
if (tileRange.minX < this.minX) {
|
||||
this.minX = tileRange.minX;
|
||||
}
|
||||
if (tileRange.maxX > this.maxX) {
|
||||
this.maxX = tileRange.maxX;
|
||||
}
|
||||
if (tileRange.minY < this.minY) {
|
||||
this.minY = tileRange.minY;
|
||||
}
|
||||
if (tileRange.maxY > this.maxY) {
|
||||
this.maxY = tileRange.maxY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Height.
|
||||
*/
|
||||
getHeight() {
|
||||
return this.maxY - this.minY + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./size.js").Size} Size.
|
||||
*/
|
||||
getSize() {
|
||||
return [this.getWidth(), this.getHeight()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Width.
|
||||
*/
|
||||
getWidth() {
|
||||
return this.maxX - this.minX + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TileRange} tileRange Tile range.
|
||||
* @return {boolean} Intersects.
|
||||
*/
|
||||
intersects(tileRange) {
|
||||
return (
|
||||
this.minX <= tileRange.maxX &&
|
||||
this.maxX >= tileRange.minX &&
|
||||
this.minY <= tileRange.maxY &&
|
||||
this.maxY >= tileRange.minY
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} minX Minimum X.
|
||||
* @param {number} maxX Maximum X.
|
||||
* @param {number} minY Minimum Y.
|
||||
* @param {number} maxY Maximum Y.
|
||||
* @param {TileRange} [tileRange] TileRange.
|
||||
* @return {TileRange} Tile range.
|
||||
*/
|
||||
export function createOrUpdate(minX, maxX, minY, maxY, tileRange) {
|
||||
if (tileRange !== undefined) {
|
||||
tileRange.minX = minX;
|
||||
tileRange.maxX = maxX;
|
||||
tileRange.minY = minY;
|
||||
tileRange.maxY = maxY;
|
||||
return tileRange;
|
||||
} else {
|
||||
return new TileRange(minX, maxX, minY, maxY);
|
||||
}
|
||||
}
|
||||
|
||||
export default TileRange;
|
||||
18
node_modules/ol/src/TileState.js
generated
vendored
Normal file
18
node_modules/ol/src/TileState.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @module ol/TileState
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
export default {
|
||||
IDLE: 0,
|
||||
LOADING: 1,
|
||||
LOADED: 2,
|
||||
/**
|
||||
* Indicates that tile loading failed
|
||||
* @type {number}
|
||||
*/
|
||||
ERROR: 3,
|
||||
EMPTY: 4,
|
||||
};
|
||||
166
node_modules/ol/src/VectorRenderTile.js
generated
vendored
Normal file
166
node_modules/ol/src/VectorRenderTile.js
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* @module ol/VectorRenderTile
|
||||
*/
|
||||
import Tile from './Tile.js';
|
||||
import {createCanvasContext2D, releaseCanvas} from './dom.js';
|
||||
import {getUid} from './util.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} ReplayState
|
||||
* @property {boolean} dirty Dirty.
|
||||
* @property {null|import("./render.js").OrderFunction} renderedRenderOrder RenderedRenderOrder.
|
||||
* @property {number} renderedTileRevision RenderedTileRevision.
|
||||
* @property {number} renderedResolution RenderedResolution.
|
||||
* @property {number} renderedRevision RenderedRevision.
|
||||
* @property {number} renderedTileResolution RenderedTileResolution.
|
||||
* @property {number} renderedTileZ RenderedTileZ.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {Array<HTMLCanvasElement>}
|
||||
*/
|
||||
const canvasPool = [];
|
||||
|
||||
class VectorRenderTile extends Tile {
|
||||
/**
|
||||
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||
* @param {import("./TileState.js").default} state State.
|
||||
* @param {import("./tilecoord.js").TileCoord} urlTileCoord Wrapped tile coordinate for source urls.
|
||||
* @param {function(VectorRenderTile):Array<import("./VectorTile").default>} getSourceTiles Function
|
||||
* to get source tiles for this tile.
|
||||
*/
|
||||
constructor(tileCoord, state, urlTileCoord, getSourceTiles) {
|
||||
super(tileCoord, state, {transition: 0});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object<string, CanvasRenderingContext2D>}
|
||||
*/
|
||||
this.context_ = {};
|
||||
|
||||
/**
|
||||
* Executor groups by layer uid. Entries are read/written by the renderer.
|
||||
* @type {Object<string, Array<import("./render/canvas/ExecutorGroup.js").default>>}
|
||||
*/
|
||||
this.executorGroups = {};
|
||||
|
||||
/**
|
||||
* Executor groups for decluttering, by layer uid. Entries are read/written by the renderer.
|
||||
* @type {Object<string, Array<import("./render/canvas/ExecutorGroup.js").default>>}
|
||||
*/
|
||||
this.declutterExecutorGroups = {};
|
||||
|
||||
/**
|
||||
* Number of loading source tiles. Read/written by the source.
|
||||
* @type {number}
|
||||
*/
|
||||
this.loadingSourceTiles = 0;
|
||||
|
||||
/**
|
||||
* @type {Object<number, ImageData>}
|
||||
*/
|
||||
this.hitDetectionImageData = {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!Object<string, ReplayState>}
|
||||
*/
|
||||
this.replayState_ = {};
|
||||
|
||||
/**
|
||||
* @type {Array<import("./VectorTile.js").default>}
|
||||
*/
|
||||
this.sourceTiles = [];
|
||||
|
||||
/**
|
||||
* @type {Object<string, boolean>}
|
||||
*/
|
||||
this.errorTileKeys = {};
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.wantedResolution;
|
||||
|
||||
/**
|
||||
* @type {!function():Array<import("./VectorTile.js").default>}
|
||||
*/
|
||||
this.getSourceTiles = getSourceTiles.bind(undefined, this);
|
||||
|
||||
/**
|
||||
* @type {import("./tilecoord.js").TileCoord}
|
||||
*/
|
||||
this.wrappedTileCoord = urlTileCoord;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./layer/Layer.js").default} layer Layer.
|
||||
* @return {CanvasRenderingContext2D} The rendering context.
|
||||
*/
|
||||
getContext(layer) {
|
||||
const key = getUid(layer);
|
||||
if (!(key in this.context_)) {
|
||||
this.context_[key] = createCanvasContext2D(1, 1, canvasPool);
|
||||
}
|
||||
return this.context_[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./layer/Layer.js").default} layer Layer.
|
||||
* @return {boolean} Tile has a rendering context for the given layer.
|
||||
*/
|
||||
hasContext(layer) {
|
||||
return getUid(layer) in this.context_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Canvas for this tile.
|
||||
* @param {import("./layer/Layer.js").default} layer Layer.
|
||||
* @return {HTMLCanvasElement} Canvas.
|
||||
*/
|
||||
getImage(layer) {
|
||||
return this.hasContext(layer) ? this.getContext(layer).canvas : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./layer/Layer.js").default} layer Layer.
|
||||
* @return {ReplayState} The replay state.
|
||||
*/
|
||||
getReplayState(layer) {
|
||||
const key = getUid(layer);
|
||||
if (!(key in this.replayState_)) {
|
||||
this.replayState_[key] = {
|
||||
dirty: false,
|
||||
renderedRenderOrder: null,
|
||||
renderedResolution: NaN,
|
||||
renderedRevision: -1,
|
||||
renderedTileResolution: NaN,
|
||||
renderedTileRevision: -1,
|
||||
renderedTileZ: -1,
|
||||
};
|
||||
}
|
||||
return this.replayState_[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the tile.
|
||||
*/
|
||||
load() {
|
||||
this.getSourceTiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from the cache due to expiry
|
||||
*/
|
||||
release() {
|
||||
for (const key in this.context_) {
|
||||
const context = this.context_[key];
|
||||
releaseCanvas(context);
|
||||
canvasPool.push(context.canvas);
|
||||
delete this.context_[key];
|
||||
}
|
||||
super.release();
|
||||
}
|
||||
}
|
||||
|
||||
export default VectorRenderTile;
|
||||
138
node_modules/ol/src/VectorTile.js
generated
vendored
Normal file
138
node_modules/ol/src/VectorTile.js
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @module ol/VectorTile
|
||||
*/
|
||||
import Tile from './Tile.js';
|
||||
import TileState from './TileState.js';
|
||||
|
||||
class VectorTile extends Tile {
|
||||
/**
|
||||
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||
* @param {import("./TileState.js").default} state State.
|
||||
* @param {string} src Data source url.
|
||||
* @param {import("./format/Feature.js").default} format Feature format.
|
||||
* @param {import("./Tile.js").LoadFunction} tileLoadFunction Tile load function.
|
||||
* @param {import("./Tile.js").Options} [opt_options] Tile options.
|
||||
*/
|
||||
constructor(tileCoord, state, src, format, tileLoadFunction, opt_options) {
|
||||
super(tileCoord, state, opt_options);
|
||||
|
||||
/**
|
||||
* Extent of this tile; set by the source.
|
||||
* @type {import("./extent.js").Extent}
|
||||
*/
|
||||
this.extent = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./format/Feature.js").default}
|
||||
*/
|
||||
this.format_ = format;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<import("./Feature.js").default>}
|
||||
*/
|
||||
this.features_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./featureloader.js").FeatureLoader}
|
||||
*/
|
||||
this.loader_;
|
||||
|
||||
/**
|
||||
* Feature projection of this tile; set by the source.
|
||||
* @type {import("./proj/Projection.js").default}
|
||||
*/
|
||||
this.projection = null;
|
||||
|
||||
/**
|
||||
* Resolution of this tile; set by the source.
|
||||
* @type {number}
|
||||
*/
|
||||
this.resolution;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./Tile.js").LoadFunction}
|
||||
*/
|
||||
this.tileLoadFunction_ = tileLoadFunction;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.url_ = src;
|
||||
|
||||
this.key = src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the feature format assigned for reading this tile's features.
|
||||
* @return {import("./format/Feature.js").default} Feature format.
|
||||
* @api
|
||||
*/
|
||||
getFormat() {
|
||||
return this.format_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the features for this tile. Geometries will be in the view projection.
|
||||
* @return {Array<import("./Feature.js").FeatureLike>} Features.
|
||||
* @api
|
||||
*/
|
||||
getFeatures() {
|
||||
return this.features_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load not yet loaded URI.
|
||||
*/
|
||||
load() {
|
||||
if (this.state == TileState.IDLE) {
|
||||
this.setState(TileState.LOADING);
|
||||
this.tileLoadFunction_(this, this.url_);
|
||||
if (this.loader_) {
|
||||
this.loader_(this.extent, this.resolution, this.projection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for successful tile load.
|
||||
* @param {Array<import("./Feature.js").default>} features The loaded features.
|
||||
* @param {import("./proj/Projection.js").default} dataProjection Data projection.
|
||||
*/
|
||||
onLoad(features, dataProjection) {
|
||||
this.setFeatures(features);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for tile load errors.
|
||||
*/
|
||||
onError() {
|
||||
this.setState(TileState.ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for use in an {@link module:ol/source/VectorTile~VectorTile}'s `tileLoadFunction`.
|
||||
* Sets the features for the tile.
|
||||
* @param {Array<import("./Feature.js").default>} features Features.
|
||||
* @api
|
||||
*/
|
||||
setFeatures(features) {
|
||||
this.features_ = features;
|
||||
this.setState(TileState.LOADED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the feature loader for reading this tile's features.
|
||||
* @param {import("./featureloader.js").FeatureLoader} loader Feature loader.
|
||||
* @api
|
||||
*/
|
||||
setLoader(loader) {
|
||||
this.loader_ = loader;
|
||||
}
|
||||
}
|
||||
|
||||
export default VectorTile;
|
||||
2148
node_modules/ol/src/View.js
generated
vendored
Normal file
2148
node_modules/ol/src/View.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
node_modules/ol/src/ViewHint.js
generated
vendored
Normal file
11
node_modules/ol/src/ViewHint.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @module ol/ViewHint
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
export default {
|
||||
ANIMATING: 0,
|
||||
INTERACTING: 1,
|
||||
};
|
||||
12
node_modules/ol/src/ViewProperty.js
generated
vendored
Normal file
12
node_modules/ol/src/ViewProperty.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @module ol/ViewProperty
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
export default {
|
||||
CENTER: 'center',
|
||||
RESOLUTION: 'resolution',
|
||||
ROTATION: 'rotation',
|
||||
};
|
||||
259
node_modules/ol/src/array.js
generated
vendored
Normal file
259
node_modules/ol/src/array.js
generated
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* @module ol/array
|
||||
*/
|
||||
|
||||
/**
|
||||
* Performs a binary search on the provided sorted list and returns the index of the item if found. If it can't be found it'll return -1.
|
||||
* https://github.com/darkskyapp/binary-search
|
||||
*
|
||||
* @param {Array<*>} haystack Items to search through.
|
||||
* @param {*} needle The item to look for.
|
||||
* @param {Function} [opt_comparator] Comparator function.
|
||||
* @return {number} The index of the item if found, -1 if not.
|
||||
*/
|
||||
export function binarySearch(haystack, needle, opt_comparator) {
|
||||
let mid, cmp;
|
||||
const comparator = opt_comparator || numberSafeCompareFunction;
|
||||
let low = 0;
|
||||
let high = haystack.length;
|
||||
let found = false;
|
||||
|
||||
while (low < high) {
|
||||
/* Note that "(low + high) >>> 1" may overflow, and results in a typecast
|
||||
* to double (which gives the wrong results). */
|
||||
mid = low + ((high - low) >> 1);
|
||||
cmp = +comparator(haystack[mid], needle);
|
||||
|
||||
if (cmp < 0.0) {
|
||||
/* Too low. */
|
||||
low = mid + 1;
|
||||
} else {
|
||||
/* Key found or too high */
|
||||
high = mid;
|
||||
found = !cmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Key not found. */
|
||||
return found ? low : ~low;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare function for array sort that is safe for numbers.
|
||||
* @param {*} a The first object to be compared.
|
||||
* @param {*} b The second object to be compared.
|
||||
* @return {number} A negative number, zero, or a positive number as the first
|
||||
* argument is less than, equal to, or greater than the second.
|
||||
*/
|
||||
export function numberSafeCompareFunction(a, b) {
|
||||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the array contains the given object.
|
||||
* @param {Array<*>} arr The array to test for the presence of the element.
|
||||
* @param {*} obj The object for which to test.
|
||||
* @return {boolean} The object is in the array.
|
||||
*/
|
||||
export function includes(arr, obj) {
|
||||
return arr.indexOf(obj) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link module:ol/tilegrid/TileGrid~TileGrid#getZForResolution} can use a function
|
||||
* of this type to determine which nearest resolution to use.
|
||||
*
|
||||
* This function takes a `{number}` representing a value between two array entries,
|
||||
* a `{number}` representing the value of the nearest higher entry and
|
||||
* a `{number}` representing the value of the nearest lower entry
|
||||
* as arguments and returns a `{number}`. If a negative number or zero is returned
|
||||
* the lower value will be used, if a positive number is returned the higher value
|
||||
* will be used.
|
||||
* @typedef {function(number, number, number): number} NearestDirectionFunction
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Array<number>} arr Array in descending order.
|
||||
* @param {number} target Target.
|
||||
* @param {number|NearestDirectionFunction} direction
|
||||
* 0 means return the nearest,
|
||||
* > 0 means return the largest nearest,
|
||||
* < 0 means return the smallest nearest.
|
||||
* @return {number} Index.
|
||||
*/
|
||||
export function linearFindNearest(arr, target, direction) {
|
||||
const n = arr.length;
|
||||
if (arr[0] <= target) {
|
||||
return 0;
|
||||
} else if (target <= arr[n - 1]) {
|
||||
return n - 1;
|
||||
} else {
|
||||
let i;
|
||||
if (direction > 0) {
|
||||
for (i = 1; i < n; ++i) {
|
||||
if (arr[i] < target) {
|
||||
return i - 1;
|
||||
}
|
||||
}
|
||||
} else if (direction < 0) {
|
||||
for (i = 1; i < n; ++i) {
|
||||
if (arr[i] <= target) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 1; i < n; ++i) {
|
||||
if (arr[i] == target) {
|
||||
return i;
|
||||
} else if (arr[i] < target) {
|
||||
if (typeof direction === 'function') {
|
||||
if (direction(target, arr[i - 1], arr[i]) > 0) {
|
||||
return i - 1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
} else if (arr[i - 1] - target < target - arr[i]) {
|
||||
return i - 1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return n - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<*>} arr Array.
|
||||
* @param {number} begin Begin index.
|
||||
* @param {number} end End index.
|
||||
*/
|
||||
export function reverseSubArray(arr, begin, end) {
|
||||
while (begin < end) {
|
||||
const tmp = arr[begin];
|
||||
arr[begin] = arr[end];
|
||||
arr[end] = tmp;
|
||||
++begin;
|
||||
--end;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<VALUE>} arr The array to modify.
|
||||
* @param {!Array<VALUE>|VALUE} data The elements or arrays of elements to add to arr.
|
||||
* @template VALUE
|
||||
*/
|
||||
export function extend(arr, data) {
|
||||
const extension = Array.isArray(data) ? data : [data];
|
||||
const length = extension.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
arr[arr.length] = extension[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<VALUE>} arr The array to modify.
|
||||
* @param {VALUE} obj The element to remove.
|
||||
* @template VALUE
|
||||
* @return {boolean} If the element was removed.
|
||||
*/
|
||||
export function remove(arr, obj) {
|
||||
const i = arr.indexOf(obj);
|
||||
const found = i > -1;
|
||||
if (found) {
|
||||
arr.splice(i, 1);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<VALUE>} arr The array to search in.
|
||||
* @param {function(VALUE, number, ?) : boolean} func The function to compare.
|
||||
* @template VALUE
|
||||
* @return {VALUE|null} The element found or null.
|
||||
*/
|
||||
export function find(arr, func) {
|
||||
const length = arr.length >>> 0;
|
||||
let value;
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
value = arr[i];
|
||||
if (func(value, i, arr)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array|Uint8ClampedArray} arr1 The first array to compare.
|
||||
* @param {Array|Uint8ClampedArray} arr2 The second array to compare.
|
||||
* @return {boolean} Whether the two arrays are equal.
|
||||
*/
|
||||
export function equals(arr1, arr2) {
|
||||
const len1 = arr1.length;
|
||||
if (len1 !== arr2.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < len1; i++) {
|
||||
if (arr1[i] !== arr2[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the passed array such that the relative order of equal elements is preserved.
|
||||
* See https://en.wikipedia.org/wiki/Sorting_algorithm#Stability for details.
|
||||
* @param {Array<*>} arr The array to sort (modifies original).
|
||||
* @param {!function(*, *): number} compareFnc Comparison function.
|
||||
* @api
|
||||
*/
|
||||
export function stableSort(arr, compareFnc) {
|
||||
const length = arr.length;
|
||||
const tmp = Array(arr.length);
|
||||
let i;
|
||||
for (i = 0; i < length; i++) {
|
||||
tmp[i] = {index: i, value: arr[i]};
|
||||
}
|
||||
tmp.sort(function (a, b) {
|
||||
return compareFnc(a.value, b.value) || a.index - b.index;
|
||||
});
|
||||
for (i = 0; i < arr.length; i++) {
|
||||
arr[i] = tmp[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<*>} arr The array to search in.
|
||||
* @param {Function} func Comparison function.
|
||||
* @return {number} Return index.
|
||||
*/
|
||||
export function findIndex(arr, func) {
|
||||
let index;
|
||||
const found = !arr.every(function (el, idx) {
|
||||
index = idx;
|
||||
return !func(el, idx, arr);
|
||||
});
|
||||
return found ? index : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<*>} arr The array to test.
|
||||
* @param {Function} [opt_func] Comparison function.
|
||||
* @param {boolean} [opt_strict] Strictly sorted (default false).
|
||||
* @return {boolean} Return index.
|
||||
*/
|
||||
export function isSorted(arr, opt_func, opt_strict) {
|
||||
const compare = opt_func || numberSafeCompareFunction;
|
||||
return arr.every(function (currentVal, index) {
|
||||
if (index === 0) {
|
||||
return true;
|
||||
}
|
||||
const res = compare(arr[index - 1], currentVal);
|
||||
return !(res > 0 || (opt_strict && res === 0));
|
||||
});
|
||||
}
|
||||
14
node_modules/ol/src/asserts.js
generated
vendored
Normal file
14
node_modules/ol/src/asserts.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @module ol/asserts
|
||||
*/
|
||||
import AssertionError from './AssertionError.js';
|
||||
|
||||
/**
|
||||
* @param {*} assertion Assertion we expected to be truthy.
|
||||
* @param {number} errorCode Error code.
|
||||
*/
|
||||
export function assert(assertion, errorCode) {
|
||||
if (!assertion) {
|
||||
throw new AssertionError(errorCode);
|
||||
}
|
||||
}
|
||||
79
node_modules/ol/src/centerconstraint.js
generated
vendored
Normal file
79
node_modules/ol/src/centerconstraint.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @module ol/centerconstraint
|
||||
*/
|
||||
import {clamp} from './math.js';
|
||||
|
||||
/**
|
||||
* @typedef {function((import("./coordinate.js").Coordinate|undefined), number, import("./size.js").Size, boolean=, Array<number>=): (import("./coordinate.js").Coordinate|undefined)} Type
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {boolean} onlyCenter If true, the constraint will only apply to the view center.
|
||||
* @param {boolean} smooth If true, the view will be able to go slightly out of the given extent
|
||||
* (only during interaction and animation).
|
||||
* @return {Type} The constraint.
|
||||
*/
|
||||
export function createExtent(extent, onlyCenter, smooth) {
|
||||
return (
|
||||
/**
|
||||
* @param {import("./coordinate.js").Coordinate|undefined} center Center.
|
||||
* @param {number|undefined} resolution Resolution.
|
||||
* @param {import("./size.js").Size} size Viewport size; unused if `onlyCenter` was specified.
|
||||
* @param {boolean} [opt_isMoving] True if an interaction or animation is in progress.
|
||||
* @param {Array<number>} [opt_centerShift] Shift between map center and viewport center.
|
||||
* @return {import("./coordinate.js").Coordinate|undefined} Center.
|
||||
*/
|
||||
function (center, resolution, size, opt_isMoving, opt_centerShift) {
|
||||
if (!center) {
|
||||
return undefined;
|
||||
}
|
||||
if (!resolution && !onlyCenter) {
|
||||
return center;
|
||||
}
|
||||
const viewWidth = onlyCenter ? 0 : size[0] * resolution;
|
||||
const viewHeight = onlyCenter ? 0 : size[1] * resolution;
|
||||
const shiftX = opt_centerShift ? opt_centerShift[0] : 0;
|
||||
const shiftY = opt_centerShift ? opt_centerShift[1] : 0;
|
||||
let minX = extent[0] + viewWidth / 2 + shiftX;
|
||||
let maxX = extent[2] - viewWidth / 2 + shiftX;
|
||||
let minY = extent[1] + viewHeight / 2 + shiftY;
|
||||
let maxY = extent[3] - viewHeight / 2 + shiftY;
|
||||
|
||||
// note: when zooming out of bounds, min and max values for x and y may
|
||||
// end up inverted (min > max); this has to be accounted for
|
||||
if (minX > maxX) {
|
||||
minX = (maxX + minX) / 2;
|
||||
maxX = minX;
|
||||
}
|
||||
if (minY > maxY) {
|
||||
minY = (maxY + minY) / 2;
|
||||
maxY = minY;
|
||||
}
|
||||
|
||||
let x = clamp(center[0], minX, maxX);
|
||||
let y = clamp(center[1], minY, maxY);
|
||||
|
||||
// during an interaction, allow some overscroll
|
||||
if (opt_isMoving && smooth && resolution) {
|
||||
const ratio = 30 * resolution;
|
||||
x +=
|
||||
-ratio * Math.log(1 + Math.max(0, minX - center[0]) / ratio) +
|
||||
ratio * Math.log(1 + Math.max(0, center[0] - maxX) / ratio);
|
||||
y +=
|
||||
-ratio * Math.log(1 + Math.max(0, minY - center[1]) / ratio) +
|
||||
ratio * Math.log(1 + Math.max(0, center[1] - maxY) / ratio);
|
||||
}
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./coordinate.js").Coordinate} [center] Center.
|
||||
* @return {import("./coordinate.js").Coordinate|undefined} Center.
|
||||
*/
|
||||
export function none(center) {
|
||||
return center;
|
||||
}
|
||||
231
node_modules/ol/src/color.js
generated
vendored
Normal file
231
node_modules/ol/src/color.js
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* @module ol/color
|
||||
*/
|
||||
import {assert} from './asserts.js';
|
||||
import {clamp} from './math.js';
|
||||
|
||||
/**
|
||||
* A color represented as a short array [red, green, blue, alpha].
|
||||
* red, green, and blue should be integers in the range 0..255 inclusive.
|
||||
* alpha should be a float in the range 0..1 inclusive. If no alpha value is
|
||||
* given then `1` will be used.
|
||||
* @typedef {Array<number>} Color
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* This RegExp matches # followed by 3, 4, 6, or 8 hex digits.
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
const HEX_COLOR_RE_ = /^#([a-f0-9]{3}|[a-f0-9]{4}(?:[a-f0-9]{2}){0,2})$/i;
|
||||
|
||||
/**
|
||||
* Regular expression for matching potential named color style strings.
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
* @private
|
||||
*/
|
||||
const NAMED_COLOR_RE_ = /^([a-z]*)$|^hsla?\(.*\)$/i;
|
||||
|
||||
/**
|
||||
* Return the color as an rgba string.
|
||||
* @param {Color|string} color Color.
|
||||
* @return {string} Rgba string.
|
||||
* @api
|
||||
*/
|
||||
export function asString(color) {
|
||||
if (typeof color === 'string') {
|
||||
return color;
|
||||
} else {
|
||||
return toString(color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return named color as an rgba string.
|
||||
* @param {string} color Named color.
|
||||
* @return {string} Rgb string.
|
||||
*/
|
||||
function fromNamed(color) {
|
||||
const el = document.createElement('div');
|
||||
el.style.color = color;
|
||||
if (el.style.color !== '') {
|
||||
document.body.appendChild(el);
|
||||
const rgb = getComputedStyle(el).color;
|
||||
document.body.removeChild(el);
|
||||
return rgb;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @return {Color} Color.
|
||||
*/
|
||||
export const fromString = (function () {
|
||||
// We maintain a small cache of parsed strings. To provide cheap LRU-like
|
||||
// semantics, whenever the cache grows too large we simply delete an
|
||||
// arbitrary 25% of the entries.
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
const MAX_CACHE_SIZE = 1024;
|
||||
|
||||
/**
|
||||
* @type {Object<string, Color>}
|
||||
*/
|
||||
const cache = {};
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
let cacheSize = 0;
|
||||
|
||||
return (
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @return {Color} Color.
|
||||
*/
|
||||
function (s) {
|
||||
let color;
|
||||
if (cache.hasOwnProperty(s)) {
|
||||
color = cache[s];
|
||||
} else {
|
||||
if (cacheSize >= MAX_CACHE_SIZE) {
|
||||
let i = 0;
|
||||
for (const key in cache) {
|
||||
if ((i++ & 3) === 0) {
|
||||
delete cache[key];
|
||||
--cacheSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
color = fromStringInternal_(s);
|
||||
cache[s] = color;
|
||||
++cacheSize;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
);
|
||||
})();
|
||||
|
||||
/**
|
||||
* Return the color as an array. This function maintains a cache of calculated
|
||||
* arrays which means the result should not be modified.
|
||||
* @param {Color|string} color Color.
|
||||
* @return {Color} Color.
|
||||
* @api
|
||||
*/
|
||||
export function asArray(color) {
|
||||
if (Array.isArray(color)) {
|
||||
return color;
|
||||
} else {
|
||||
return fromString(color);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @private
|
||||
* @return {Color} Color.
|
||||
*/
|
||||
function fromStringInternal_(s) {
|
||||
let r, g, b, a, color;
|
||||
|
||||
if (NAMED_COLOR_RE_.exec(s)) {
|
||||
s = fromNamed(s);
|
||||
}
|
||||
|
||||
if (HEX_COLOR_RE_.exec(s)) {
|
||||
// hex
|
||||
const n = s.length - 1; // number of hex digits
|
||||
let d; // number of digits per channel
|
||||
if (n <= 4) {
|
||||
d = 1;
|
||||
} else {
|
||||
d = 2;
|
||||
}
|
||||
const hasAlpha = n === 4 || n === 8;
|
||||
r = parseInt(s.substr(1 + 0 * d, d), 16);
|
||||
g = parseInt(s.substr(1 + 1 * d, d), 16);
|
||||
b = parseInt(s.substr(1 + 2 * d, d), 16);
|
||||
if (hasAlpha) {
|
||||
a = parseInt(s.substr(1 + 3 * d, d), 16);
|
||||
} else {
|
||||
a = 255;
|
||||
}
|
||||
if (d == 1) {
|
||||
r = (r << 4) + r;
|
||||
g = (g << 4) + g;
|
||||
b = (b << 4) + b;
|
||||
if (hasAlpha) {
|
||||
a = (a << 4) + a;
|
||||
}
|
||||
}
|
||||
color = [r, g, b, a / 255];
|
||||
} else if (s.indexOf('rgba(') == 0) {
|
||||
// rgba()
|
||||
color = s.slice(5, -1).split(',').map(Number);
|
||||
normalize(color);
|
||||
} else if (s.indexOf('rgb(') == 0) {
|
||||
// rgb()
|
||||
color = s.slice(4, -1).split(',').map(Number);
|
||||
color.push(1);
|
||||
normalize(color);
|
||||
} else {
|
||||
assert(false, 14); // Invalid color
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO this function is only used in the test, we probably shouldn't export it
|
||||
* @param {Color} color Color.
|
||||
* @return {Color} Clamped color.
|
||||
*/
|
||||
export function normalize(color) {
|
||||
color[0] = clamp((color[0] + 0.5) | 0, 0, 255);
|
||||
color[1] = clamp((color[1] + 0.5) | 0, 0, 255);
|
||||
color[2] = clamp((color[2] + 0.5) | 0, 0, 255);
|
||||
color[3] = clamp(color[3], 0, 1);
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Color} color Color.
|
||||
* @return {string} String.
|
||||
*/
|
||||
export function toString(color) {
|
||||
let r = color[0];
|
||||
if (r != (r | 0)) {
|
||||
r = (r + 0.5) | 0;
|
||||
}
|
||||
let g = color[1];
|
||||
if (g != (g | 0)) {
|
||||
g = (g + 0.5) | 0;
|
||||
}
|
||||
let b = color[2];
|
||||
if (b != (b | 0)) {
|
||||
b = (b + 0.5) | 0;
|
||||
}
|
||||
const a = color[3] === undefined ? 1 : Math.round(color[3] * 100) / 100;
|
||||
return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} s String.
|
||||
* @return {boolean} Whether the string is actually a valid color
|
||||
*/
|
||||
export function isStringColor(s) {
|
||||
if (NAMED_COLOR_RE_.test(s)) {
|
||||
s = fromNamed(s);
|
||||
}
|
||||
return (
|
||||
HEX_COLOR_RE_.test(s) || s.indexOf('rgba(') === 0 || s.indexOf('rgb(') === 0
|
||||
);
|
||||
}
|
||||
29
node_modules/ol/src/colorlike.js
generated
vendored
Normal file
29
node_modules/ol/src/colorlike.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @module ol/colorlike
|
||||
*/
|
||||
import {toString} from './color.js';
|
||||
|
||||
/**
|
||||
* A type accepted by CanvasRenderingContext2D.fillStyle
|
||||
* or CanvasRenderingContext2D.strokeStyle.
|
||||
* Represents a color, pattern, or gradient. The origin for patterns and
|
||||
* gradients as fill style is an increment of 512 css pixels from map coordinate
|
||||
* `[0, 0]`. For seamless repeat patterns, width and height of the pattern image
|
||||
* must be a factor of two (2, 4, 8, ..., 512).
|
||||
*
|
||||
* @typedef {string|CanvasPattern|CanvasGradient} ColorLike
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {import("./color.js").Color|ColorLike} color Color.
|
||||
* @return {ColorLike} The color as an {@link ol/colorlike~ColorLike}.
|
||||
* @api
|
||||
*/
|
||||
export function asColorLike(color) {
|
||||
if (Array.isArray(color)) {
|
||||
return toString(color);
|
||||
} else {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
72
node_modules/ol/src/control.js
generated
vendored
Normal file
72
node_modules/ol/src/control.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @module ol/control
|
||||
*/
|
||||
import Attribution from './control/Attribution.js';
|
||||
import Collection from './Collection.js';
|
||||
import Rotate from './control/Rotate.js';
|
||||
import Zoom from './control/Zoom.js';
|
||||
|
||||
export {default as Attribution} from './control/Attribution.js';
|
||||
export {default as Control} from './control/Control.js';
|
||||
export {default as FullScreen} from './control/FullScreen.js';
|
||||
export {default as MousePosition} from './control/MousePosition.js';
|
||||
export {default as OverviewMap} from './control/OverviewMap.js';
|
||||
export {default as Rotate} from './control/Rotate.js';
|
||||
export {default as ScaleLine} from './control/ScaleLine.js';
|
||||
export {default as Zoom} from './control/Zoom.js';
|
||||
export {default as ZoomSlider} from './control/ZoomSlider.js';
|
||||
export {default as ZoomToExtent} from './control/ZoomToExtent.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} DefaultsOptions
|
||||
* @property {boolean} [attribution=true] Include
|
||||
* {@link module:ol/control/Attribution~Attribution}.
|
||||
* @property {import("./control/Attribution.js").Options} [attributionOptions]
|
||||
* Options for {@link module:ol/control/Attribution~Attribution}.
|
||||
* @property {boolean} [rotate=true] Include
|
||||
* {@link module:ol/control/Rotate~Rotate}.
|
||||
* @property {import("./control/Rotate.js").Options} [rotateOptions] Options
|
||||
* for {@link module:ol/control/Rotate~Rotate}.
|
||||
* @property {boolean} [zoom] Include {@link module:ol/control/Zoom~Zoom}.
|
||||
* @property {import("./control/Zoom.js").Options} [zoomOptions] Options for
|
||||
* {@link module:ol/control/Zoom~Zoom}.
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set of controls included in maps by default. Unless configured otherwise,
|
||||
* this returns a collection containing an instance of each of the following
|
||||
* controls:
|
||||
* * {@link module:ol/control/Zoom~Zoom}
|
||||
* * {@link module:ol/control/Rotate~Rotate}
|
||||
* * {@link module:ol/control/Attribution~Attribution}
|
||||
*
|
||||
* @param {DefaultsOptions} [opt_options]
|
||||
* Defaults options.
|
||||
* @return {Collection<import("./control/Control.js").default>}
|
||||
* Controls.
|
||||
* @api
|
||||
*/
|
||||
export function defaults(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const controls = new Collection();
|
||||
|
||||
const zoomControl = options.zoom !== undefined ? options.zoom : true;
|
||||
if (zoomControl) {
|
||||
controls.push(new Zoom(options.zoomOptions));
|
||||
}
|
||||
|
||||
const rotateControl = options.rotate !== undefined ? options.rotate : true;
|
||||
if (rotateControl) {
|
||||
controls.push(new Rotate(options.rotateOptions));
|
||||
}
|
||||
|
||||
const attributionControl =
|
||||
options.attribution !== undefined ? options.attribution : true;
|
||||
if (attributionControl) {
|
||||
controls.push(new Attribution(options.attributionOptions));
|
||||
}
|
||||
|
||||
return controls;
|
||||
}
|
||||
375
node_modules/ol/src/control/Attribution.js
generated
vendored
Normal file
375
node_modules/ol/src/control/Attribution.js
generated
vendored
Normal file
@@ -0,0 +1,375 @@
|
||||
/**
|
||||
* @module ol/control/Attribution
|
||||
*/
|
||||
import Control from './Control.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import {CLASS_COLLAPSED, CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {equals} from '../array.js';
|
||||
import {inView} from '../layer/Layer.js';
|
||||
import {removeChildren, replaceNode} from '../dom.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-attribution'] CSS class name.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you
|
||||
* want the control to be rendered outside of the map's
|
||||
* viewport.
|
||||
* @property {boolean} [collapsible] Specify if attributions can
|
||||
* be collapsed. If not specified, sources control this behavior with their
|
||||
* `attributionsCollapsible` setting.
|
||||
* @property {boolean} [collapsed=true] Specify if attributions should
|
||||
* be collapsed at startup.
|
||||
* @property {string} [tipLabel='Attributions'] Text label to use for the button tip.
|
||||
* @property {string|HTMLElement} [label='i'] Text label to use for the
|
||||
* collapsed attributions button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [expandClassName=className + '-expand'] CSS class name for the
|
||||
* collapsed attributions button.
|
||||
* @property {string|HTMLElement} [collapseLabel='›'] Text label to use
|
||||
* for the expanded attributions button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [collapseClassName=className + '-collapse'] CSS class name for the
|
||||
* expanded attributions button.
|
||||
* @property {function(import("../MapEvent.js").default):void} [render] Function called when
|
||||
* the control should be re-rendered. This is called in a `requestAnimationFrame`
|
||||
* callback.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Control to show all the attributions associated with the layer sources
|
||||
* in the map. This control is one of the default controls included in maps.
|
||||
* By default it will show in the bottom right portion of the map, but this can
|
||||
* be changed by using a css selector for `.ol-attribution`.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Attribution extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] Attribution options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
element: document.createElement('div'),
|
||||
render: options.render,
|
||||
target: options.target,
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.ulElement_ = document.createElement('ul');
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsed_ =
|
||||
options.collapsed !== undefined ? options.collapsed : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.userCollapsed_ = this.collapsed_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.overrideCollapsible_ = options.collapsible !== undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsible_ =
|
||||
options.collapsible !== undefined ? options.collapsible : true;
|
||||
|
||||
if (!this.collapsible_) {
|
||||
this.collapsed_ = false;
|
||||
}
|
||||
|
||||
const className =
|
||||
options.className !== undefined ? options.className : 'ol-attribution';
|
||||
|
||||
const tipLabel =
|
||||
options.tipLabel !== undefined ? options.tipLabel : 'Attributions';
|
||||
|
||||
const expandClassName =
|
||||
options.expandClassName !== undefined
|
||||
? options.expandClassName
|
||||
: className + '-expand';
|
||||
|
||||
const collapseLabel =
|
||||
options.collapseLabel !== undefined ? options.collapseLabel : '\u203A';
|
||||
|
||||
const collapseClassName =
|
||||
options.collapseClassName !== undefined
|
||||
? options.collapseClassName
|
||||
: className + '-collapse';
|
||||
|
||||
if (typeof collapseLabel === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.collapseLabel_ = document.createElement('span');
|
||||
this.collapseLabel_.textContent = collapseLabel;
|
||||
this.collapseLabel_.className = collapseClassName;
|
||||
} else {
|
||||
this.collapseLabel_ = collapseLabel;
|
||||
}
|
||||
|
||||
const label = options.label !== undefined ? options.label : 'i';
|
||||
|
||||
if (typeof label === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.textContent = label;
|
||||
this.label_.className = expandClassName;
|
||||
} else {
|
||||
this.label_ = label;
|
||||
}
|
||||
|
||||
const activeLabel =
|
||||
this.collapsible_ && !this.collapsed_ ? this.collapseLabel_ : this.label_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.toggleButton_ = document.createElement('button');
|
||||
this.toggleButton_.setAttribute('type', 'button');
|
||||
this.toggleButton_.setAttribute('aria-expanded', String(!this.collapsed_));
|
||||
this.toggleButton_.title = tipLabel;
|
||||
this.toggleButton_.appendChild(activeLabel);
|
||||
|
||||
this.toggleButton_.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleClick_.bind(this),
|
||||
false
|
||||
);
|
||||
|
||||
const cssClasses =
|
||||
className +
|
||||
' ' +
|
||||
CLASS_UNSELECTABLE +
|
||||
' ' +
|
||||
CLASS_CONTROL +
|
||||
(this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') +
|
||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||
const element = this.element;
|
||||
element.className = cssClasses;
|
||||
element.appendChild(this.toggleButton_);
|
||||
element.appendChild(this.ulElement_);
|
||||
|
||||
/**
|
||||
* A list of currently rendered resolutions.
|
||||
* @type {Array<string>}
|
||||
* @private
|
||||
*/
|
||||
this.renderedAttributions_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect a list of visible attributions and set the collapsible state.
|
||||
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @return {Array<string>} Attributions.
|
||||
* @private
|
||||
*/
|
||||
collectSourceAttributions_(frameState) {
|
||||
/**
|
||||
* Used to determine if an attribution already exists.
|
||||
* @type {!Object<string, boolean>}
|
||||
*/
|
||||
const lookup = {};
|
||||
|
||||
/**
|
||||
* A list of visible attributions.
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
const visibleAttributions = [];
|
||||
|
||||
let collapsible = true;
|
||||
const layerStatesArray = frameState.layerStatesArray;
|
||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
const layerState = layerStatesArray[i];
|
||||
if (!inView(layerState, frameState.viewState)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const source = /** @type {import("../layer/Layer.js").default} */ (
|
||||
layerState.layer
|
||||
).getSource();
|
||||
if (!source) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const attributionGetter = source.getAttributions();
|
||||
if (!attributionGetter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const attributions = attributionGetter(frameState);
|
||||
if (!attributions) {
|
||||
continue;
|
||||
}
|
||||
|
||||
collapsible =
|
||||
collapsible && source.getAttributionsCollapsible() !== false;
|
||||
|
||||
if (Array.isArray(attributions)) {
|
||||
for (let j = 0, jj = attributions.length; j < jj; ++j) {
|
||||
if (!(attributions[j] in lookup)) {
|
||||
visibleAttributions.push(attributions[j]);
|
||||
lookup[attributions[j]] = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(attributions in lookup)) {
|
||||
visibleAttributions.push(attributions);
|
||||
lookup[attributions] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this.overrideCollapsible_) {
|
||||
this.setCollapsible(collapsible);
|
||||
}
|
||||
return visibleAttributions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {?import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||
*/
|
||||
updateElement_(frameState) {
|
||||
if (!frameState) {
|
||||
if (this.renderedVisible_) {
|
||||
this.element.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const attributions = this.collectSourceAttributions_(frameState);
|
||||
|
||||
const visible = attributions.length > 0;
|
||||
if (this.renderedVisible_ != visible) {
|
||||
this.element.style.display = visible ? '' : 'none';
|
||||
this.renderedVisible_ = visible;
|
||||
}
|
||||
|
||||
if (equals(attributions, this.renderedAttributions_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeChildren(this.ulElement_);
|
||||
|
||||
// append the attributions
|
||||
for (let i = 0, ii = attributions.length; i < ii; ++i) {
|
||||
const element = document.createElement('li');
|
||||
element.innerHTML = attributions[i];
|
||||
this.ulElement_.appendChild(element);
|
||||
}
|
||||
|
||||
this.renderedAttributions_ = attributions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
this.handleToggle_();
|
||||
this.userCollapsed_ = this.collapsed_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleToggle_() {
|
||||
this.element.classList.toggle(CLASS_COLLAPSED);
|
||||
if (this.collapsed_) {
|
||||
replaceNode(this.collapseLabel_, this.label_);
|
||||
} else {
|
||||
replaceNode(this.label_, this.collapseLabel_);
|
||||
}
|
||||
this.collapsed_ = !this.collapsed_;
|
||||
this.toggleButton_.setAttribute('aria-expanded', String(!this.collapsed_));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if the attribution is collapsible, `false` otherwise.
|
||||
* @return {boolean} True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
getCollapsible() {
|
||||
return this.collapsible_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the attribution should be collapsible.
|
||||
* @param {boolean} collapsible True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
setCollapsible(collapsible) {
|
||||
if (this.collapsible_ === collapsible) {
|
||||
return;
|
||||
}
|
||||
this.collapsible_ = collapsible;
|
||||
this.element.classList.toggle('ol-uncollapsible');
|
||||
if (this.userCollapsed_) {
|
||||
this.handleToggle_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse or expand the attribution according to the passed parameter. Will
|
||||
* not do anything if the attribution isn't collapsible or if the current
|
||||
* collapsed state is already the one requested.
|
||||
* @param {boolean} collapsed True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
setCollapsed(collapsed) {
|
||||
this.userCollapsed_ = collapsed;
|
||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||
return;
|
||||
}
|
||||
this.handleToggle_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` when the attribution is currently collapsed or `false`
|
||||
* otherwise.
|
||||
* @return {boolean} True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
getCollapsed() {
|
||||
return this.collapsed_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the attribution element.
|
||||
* @param {import("../MapEvent.js").default} mapEvent Map event.
|
||||
* @override
|
||||
*/
|
||||
render(mapEvent) {
|
||||
this.updateElement_(mapEvent.frameState);
|
||||
}
|
||||
}
|
||||
|
||||
export default Attribution;
|
||||
161
node_modules/ol/src/control/Control.js
generated
vendored
Normal file
161
node_modules/ol/src/control/Control.js
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* @module ol/control/Control
|
||||
*/
|
||||
import BaseObject from '../Object.js';
|
||||
import MapEventType from '../MapEventType.js';
|
||||
import {VOID} from '../functions.js';
|
||||
import {listen, unlistenByKey} from '../events.js';
|
||||
import {removeNode} from '../dom.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {HTMLElement} [element] The element is the control's
|
||||
* container element. This only needs to be specified if you're developing
|
||||
* a custom control.
|
||||
* @property {function(import("../MapEvent.js").default):void} [render] Function called when
|
||||
* the control should be re-rendered. This is called in a `requestAnimationFrame`
|
||||
* callback.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want
|
||||
* the control to be rendered outside of the map's viewport.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A control is a visible widget with a DOM element in a fixed position on the
|
||||
* screen. They can involve user input (buttons), or be informational only;
|
||||
* the position is determined using CSS. By default these are placed in the
|
||||
* container with CSS class name `ol-overlaycontainer-stopevent`, but can use
|
||||
* any outside DOM element.
|
||||
*
|
||||
* This is the base class for controls. You can use it for simple custom
|
||||
* controls by creating the element with listeners, creating an instance:
|
||||
* ```js
|
||||
* var myControl = new Control({element: myElement});
|
||||
* ```
|
||||
* and then adding this to the map.
|
||||
*
|
||||
* The main advantage of having this as a control rather than a simple separate
|
||||
* DOM element is that preventing propagation is handled for you. Controls
|
||||
* will also be objects in a {@link module:ol/Collection~Collection}, so you can use their methods.
|
||||
*
|
||||
* You can also extend this base for your own control class. See
|
||||
* examples/custom-controls for an example of how to do this.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Control extends BaseObject {
|
||||
/**
|
||||
* @param {Options} options Control options.
|
||||
*/
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
const element = options.element;
|
||||
if (element && !options.target && !element.style.pointerEvents) {
|
||||
element.style.pointerEvents = 'auto';
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.element = element ? element : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.target_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../PluggableMap.js").default|null}
|
||||
*/
|
||||
this.map_ = null;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {!Array<import("../events.js").EventsKey>}
|
||||
*/
|
||||
this.listenerKeys = [];
|
||||
|
||||
if (options.render) {
|
||||
this.render = options.render;
|
||||
}
|
||||
|
||||
if (options.target) {
|
||||
this.setTarget(options.target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up.
|
||||
*/
|
||||
disposeInternal() {
|
||||
removeNode(this.element);
|
||||
super.disposeInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map associated with this control.
|
||||
* @return {import("../PluggableMap.js").default|null} Map.
|
||||
* @api
|
||||
*/
|
||||
getMap() {
|
||||
return this.map_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Pass `null` to just remove the control from the current map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {import("../PluggableMap.js").default|null} map Map.
|
||||
* @api
|
||||
*/
|
||||
setMap(map) {
|
||||
if (this.map_) {
|
||||
removeNode(this.element);
|
||||
}
|
||||
for (let i = 0, ii = this.listenerKeys.length; i < ii; ++i) {
|
||||
unlistenByKey(this.listenerKeys[i]);
|
||||
}
|
||||
this.listenerKeys.length = 0;
|
||||
this.map_ = map;
|
||||
if (map) {
|
||||
const target = this.target_
|
||||
? this.target_
|
||||
: map.getOverlayContainerStopEvent();
|
||||
target.appendChild(this.element);
|
||||
if (this.render !== VOID) {
|
||||
this.listenerKeys.push(
|
||||
listen(map, MapEventType.POSTRENDER, this.render, this)
|
||||
);
|
||||
}
|
||||
map.render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the control.
|
||||
* @param {import("../MapEvent.js").default} mapEvent Map event.
|
||||
* @api
|
||||
*/
|
||||
render(mapEvent) {}
|
||||
|
||||
/**
|
||||
* This function is used to set a target element for the control. It has no
|
||||
* effect if it is called after the control has been added to the map (i.e.
|
||||
* after `setMap` is called on the control). If no `target` is set in the
|
||||
* options passed to the control constructor and if `setTarget` is not called
|
||||
* then the control is added to the map's overlay container.
|
||||
* @param {HTMLElement|string} target Target.
|
||||
* @api
|
||||
*/
|
||||
setTarget(target) {
|
||||
this.target_ =
|
||||
typeof target === 'string' ? document.getElementById(target) : target;
|
||||
}
|
||||
}
|
||||
|
||||
export default Control;
|
||||
405
node_modules/ol/src/control/FullScreen.js
generated
vendored
Normal file
405
node_modules/ol/src/control/FullScreen.js
generated
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
/**
|
||||
* @module ol/control/FullScreen
|
||||
*/
|
||||
import Control from './Control.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import MapProperty from '../MapProperty.js';
|
||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE, CLASS_UNSUPPORTED} from '../css.js';
|
||||
import {listen, unlistenByKey} from '../events.js';
|
||||
import {replaceNode} from '../dom.js';
|
||||
|
||||
const events = [
|
||||
'fullscreenchange',
|
||||
'webkitfullscreenchange',
|
||||
'MSFullscreenChange',
|
||||
];
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
*/
|
||||
const FullScreenEventType = {
|
||||
/**
|
||||
* Triggered after the map entered fullscreen.
|
||||
* @event FullScreenEventType#enterfullscreen
|
||||
* @api
|
||||
*/
|
||||
ENTERFULLSCREEN: 'enterfullscreen',
|
||||
|
||||
/**
|
||||
* Triggered after the map leave fullscreen.
|
||||
* @event FullScreenEventType#leavefullscreen
|
||||
* @api
|
||||
*/
|
||||
LEAVEFULLSCREEN: 'leavefullscreen',
|
||||
};
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {import("../Observable").OnSignature<import("../Observable").EventTypes|
|
||||
* 'enterfullscreen'|'leavefullscreen', import("../events/Event.js").default, Return> &
|
||||
* import("../Observable").OnSignature<import("../ObjectEventType").Types, import("../Object").ObjectEvent, Return> &
|
||||
* import("../Observable").CombinedOnSignature<import("../Observable").EventTypes|
|
||||
* 'enterfullscreen'|'leavefullscreen'|import("../ObjectEventType").Types, Return>} FullScreenOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-full-screen'] CSS class name.
|
||||
* @property {string|Text|HTMLElement} [label='\u2922'] Text label to use for the button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string|Text|HTMLElement} [labelActive='\u00d7'] Text label to use for the
|
||||
* button when full-screen is active.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [activeClassName=className + '-true'] CSS class name for the button
|
||||
* when full-screen is active.
|
||||
* @property {string} [inactiveClassName=className + '-false'] CSS class name for the button
|
||||
* when full-screen is inactive.
|
||||
* @property {string} [tipLabel='Toggle full-screen'] Text label to use for the button tip.
|
||||
* @property {boolean} [keys=false] Full keyboard access.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the
|
||||
* control to be rendered outside of the map's viewport.
|
||||
* @property {HTMLElement|string} [source] The element to be displayed
|
||||
* fullscreen. When not provided, the element containing the map viewport will
|
||||
* be displayed fullscreen.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Provides a button that when clicked fills up the full screen with the map.
|
||||
* The full screen source element is by default the element containing the map viewport unless
|
||||
* overridden by providing the `source` option. In which case, the dom
|
||||
* element introduced using this parameter will be displayed in full screen.
|
||||
*
|
||||
* When in full screen mode, a close button is shown to exit full screen mode.
|
||||
* The [Fullscreen API](https://www.w3.org/TR/fullscreen/) is used to
|
||||
* toggle the map in full screen mode.
|
||||
*
|
||||
* @fires FullScreenEventType#enterfullscreen
|
||||
* @fires FullScreenEventType#leavefullscreen
|
||||
* @api
|
||||
*/
|
||||
class FullScreen extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
element: document.createElement('div'),
|
||||
target: options.target,
|
||||
});
|
||||
|
||||
/***
|
||||
* @type {FullScreenOnSignature<import("../events").EventsKey>}
|
||||
*/
|
||||
this.on;
|
||||
|
||||
/***
|
||||
* @type {FullScreenOnSignature<import("../events").EventsKey>}
|
||||
*/
|
||||
this.once;
|
||||
|
||||
/***
|
||||
* @type {FullScreenOnSignature<void>}
|
||||
*/
|
||||
this.un;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.keys_ = options.keys !== undefined ? options.keys : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement|string|undefined}
|
||||
*/
|
||||
this.source_ = options.source;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isInFullscreen_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.boundHandleMapTargetChange_ = this.handleMapTargetChange_.bind(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.cssClassName_ =
|
||||
options.className !== undefined ? options.className : 'ol-full-screen';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<import("../events.js").EventsKey>}
|
||||
*/
|
||||
this.documentListeners_ = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
this.activeClassName_ =
|
||||
options.activeClassName !== undefined
|
||||
? options.activeClassName.split(' ')
|
||||
: [this.cssClassName_ + '-true'];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
this.inactiveClassName_ =
|
||||
options.inactiveClassName !== undefined
|
||||
? options.inactiveClassName.split(' ')
|
||||
: [this.cssClassName_ + '-false'];
|
||||
|
||||
const label = options.label !== undefined ? options.label : '\u2922';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Text|HTMLElement}
|
||||
*/
|
||||
this.labelNode_ =
|
||||
typeof label === 'string' ? document.createTextNode(label) : label;
|
||||
|
||||
const labelActive =
|
||||
options.labelActive !== undefined ? options.labelActive : '\u00d7';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Text|HTMLElement}
|
||||
*/
|
||||
this.labelActiveNode_ =
|
||||
typeof labelActive === 'string'
|
||||
? document.createTextNode(labelActive)
|
||||
: labelActive;
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.button_ = document.createElement('button');
|
||||
this.button_.title = tipLabel;
|
||||
this.button_.setAttribute('type', 'button');
|
||||
this.button_.appendChild(this.labelNode_);
|
||||
this.button_.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleClick_.bind(this),
|
||||
false
|
||||
);
|
||||
this.setClassName_(this.button_, this.isInFullscreen_);
|
||||
|
||||
this.element.className = `${this.cssClassName_} ${CLASS_UNSELECTABLE} ${CLASS_CONTROL}`;
|
||||
this.element.appendChild(this.button_);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
this.handleFullScreen_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleFullScreen_() {
|
||||
const map = this.getMap();
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
const doc = map.getOwnerDocument();
|
||||
if (!isFullScreenSupported(doc)) {
|
||||
return;
|
||||
}
|
||||
if (isFullScreen(doc)) {
|
||||
exitFullScreen(doc);
|
||||
} else {
|
||||
let element;
|
||||
if (this.source_) {
|
||||
element =
|
||||
typeof this.source_ === 'string'
|
||||
? doc.getElementById(this.source_)
|
||||
: this.source_;
|
||||
} else {
|
||||
element = map.getTargetElement();
|
||||
}
|
||||
if (this.keys_) {
|
||||
requestFullScreenWithKeys(element);
|
||||
} else {
|
||||
requestFullScreen(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleFullScreenChange_() {
|
||||
const map = this.getMap();
|
||||
if (!map) {
|
||||
return;
|
||||
}
|
||||
const wasInFullscreen = this.isInFullscreen_;
|
||||
this.isInFullscreen_ = isFullScreen(map.getOwnerDocument());
|
||||
if (wasInFullscreen !== this.isInFullscreen_) {
|
||||
this.setClassName_(this.button_, this.isInFullscreen_);
|
||||
if (this.isInFullscreen_) {
|
||||
replaceNode(this.labelActiveNode_, this.labelNode_);
|
||||
this.dispatchEvent(FullScreenEventType.ENTERFULLSCREEN);
|
||||
} else {
|
||||
replaceNode(this.labelNode_, this.labelActiveNode_);
|
||||
this.dispatchEvent(FullScreenEventType.LEAVEFULLSCREEN);
|
||||
}
|
||||
map.updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} element Target element
|
||||
* @param {boolean} fullscreen True if fullscreen class name should be active
|
||||
* @private
|
||||
*/
|
||||
setClassName_(element, fullscreen) {
|
||||
if (fullscreen) {
|
||||
element.classList.remove(...this.inactiveClassName_);
|
||||
element.classList.add(...this.activeClassName_);
|
||||
} else {
|
||||
element.classList.remove(...this.activeClassName_);
|
||||
element.classList.add(...this.inactiveClassName_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Pass `null` to just remove the control from the current map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {import("../PluggableMap.js").default|null} map Map.
|
||||
* @api
|
||||
*/
|
||||
setMap(map) {
|
||||
const oldMap = this.getMap();
|
||||
if (oldMap) {
|
||||
oldMap.removeChangeListener(
|
||||
MapProperty.TARGET,
|
||||
this.boundHandleMapTargetChange_
|
||||
);
|
||||
}
|
||||
|
||||
super.setMap(map);
|
||||
|
||||
this.handleMapTargetChange_();
|
||||
if (map) {
|
||||
map.addChangeListener(
|
||||
MapProperty.TARGET,
|
||||
this.boundHandleMapTargetChange_
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleMapTargetChange_() {
|
||||
const listeners = this.documentListeners_;
|
||||
for (let i = 0, ii = listeners.length; i < ii; ++i) {
|
||||
unlistenByKey(listeners[i]);
|
||||
}
|
||||
listeners.length = 0;
|
||||
|
||||
const map = this.getMap();
|
||||
if (map) {
|
||||
const doc = map.getOwnerDocument();
|
||||
if (isFullScreenSupported(doc)) {
|
||||
this.element.classList.remove(CLASS_UNSUPPORTED);
|
||||
} else {
|
||||
this.element.classList.add(CLASS_UNSUPPORTED);
|
||||
}
|
||||
|
||||
for (let i = 0, ii = events.length; i < ii; ++i) {
|
||||
listeners.push(
|
||||
listen(doc, events[i], this.handleFullScreenChange_, this)
|
||||
);
|
||||
}
|
||||
this.handleFullScreenChange_();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc The root document to check.
|
||||
* @return {boolean} Fullscreen is supported by the current platform.
|
||||
*/
|
||||
function isFullScreenSupported(doc) {
|
||||
const body = doc.body;
|
||||
return !!(
|
||||
body['webkitRequestFullscreen'] ||
|
||||
(body['msRequestFullscreen'] && doc['msFullscreenEnabled']) ||
|
||||
(body.requestFullscreen && doc.fullscreenEnabled)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc The root document to check.
|
||||
* @return {boolean} Element is currently in fullscreen.
|
||||
*/
|
||||
function isFullScreen(doc) {
|
||||
return !!(
|
||||
doc['webkitIsFullScreen'] ||
|
||||
doc['msFullscreenElement'] ||
|
||||
doc.fullscreenElement
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to fullscreen an element.
|
||||
* @param {HTMLElement} element Element to request fullscreen
|
||||
*/
|
||||
function requestFullScreen(element) {
|
||||
if (element.requestFullscreen) {
|
||||
element.requestFullscreen();
|
||||
} else if (element['msRequestFullscreen']) {
|
||||
element['msRequestFullscreen']();
|
||||
} else if (element['webkitRequestFullscreen']) {
|
||||
element['webkitRequestFullscreen']();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to fullscreen an element with keyboard input.
|
||||
* @param {HTMLElement} element Element to request fullscreen
|
||||
*/
|
||||
function requestFullScreenWithKeys(element) {
|
||||
if (element['webkitRequestFullscreen']) {
|
||||
element['webkitRequestFullscreen']();
|
||||
} else {
|
||||
requestFullScreen(element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit fullscreen.
|
||||
* @param {Document} doc The document to exit fullscren from
|
||||
*/
|
||||
function exitFullScreen(doc) {
|
||||
if (doc.exitFullscreen) {
|
||||
doc.exitFullscreen();
|
||||
} else if (doc['msExitFullscreen']) {
|
||||
doc['msExitFullscreen']();
|
||||
} else if (doc['webkitExitFullscreen']) {
|
||||
doc['webkitExitFullscreen']();
|
||||
}
|
||||
}
|
||||
|
||||
export default FullScreen;
|
||||
321
node_modules/ol/src/control/MousePosition.js
generated
vendored
Normal file
321
node_modules/ol/src/control/MousePosition.js
generated
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* @module ol/control/MousePosition
|
||||
*/
|
||||
|
||||
import Control from './Control.js';
|
||||
import EventType from '../pointer/EventType.js';
|
||||
import {
|
||||
get as getProjection,
|
||||
getTransformFromProjections,
|
||||
getUserProjection,
|
||||
identityTransform,
|
||||
} from '../proj.js';
|
||||
import {listen} from '../events.js';
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
const PROJECTION = 'projection';
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
const COORDINATE_FORMAT = 'coordinateFormat';
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {import("../Observable").OnSignature<import("../Observable").EventTypes, import("../events/Event.js").default, Return> &
|
||||
* import("../Observable").OnSignature<import("../ObjectEventType").Types|
|
||||
* 'change:coordinateFormat'|'change:projection', import("../Object").ObjectEvent, Return> &
|
||||
* import("../Observable").CombinedOnSignature<import("../Observable").EventTypes|import("../ObjectEventType").Types|
|
||||
* 'change:coordinateFormat'|'change:projection', Return>} MousePositionOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-mouse-position'] CSS class name.
|
||||
* @property {import("../coordinate.js").CoordinateFormat} [coordinateFormat] Coordinate format.
|
||||
* @property {import("../proj.js").ProjectionLike} [projection] Projection. Default is the view projection.
|
||||
* @property {function(import("../MapEvent.js").default):void} [render] Function called when the
|
||||
* control should be re-rendered. This is called in a `requestAnimationFrame`
|
||||
* callback.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the
|
||||
* control to be rendered outside of the map's viewport.
|
||||
* @property {string|boolean} [placeholder] Markup to show when the mouse position is not
|
||||
* available (e.g. when the pointer leaves the map viewport). By default, a non-breaking space
|
||||
* is rendered when the mouse leaves the viewport. To render something else, provide a string
|
||||
* to be used as the text content (e.g. 'no position' or '' for an empty string). Set the placeholder
|
||||
* to `false` to retain the last position when the mouse leaves the viewport. In a future release, this
|
||||
* will be the default behavior.
|
||||
* @property {string} [undefinedHTML=' '] This option is deprecated. Use the `placeholder` option instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A control to show the 2D coordinates of the mouse cursor. By default, these
|
||||
* are in the view projection, but can be in any supported projection.
|
||||
* By default the control is shown in the top right corner of the map, but this
|
||||
* can be changed by using the css selector `.ol-mouse-position`.
|
||||
*
|
||||
* On touch devices, which usually do not have a mouse cursor, the coordinates
|
||||
* of the currently touched position are shown.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class MousePosition extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] Mouse position options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const element = document.createElement('div');
|
||||
element.className =
|
||||
options.className !== undefined ? options.className : 'ol-mouse-position';
|
||||
|
||||
super({
|
||||
element: element,
|
||||
render: options.render,
|
||||
target: options.target,
|
||||
});
|
||||
|
||||
/***
|
||||
* @type {MousePositionOnSignature<import("../events").EventsKey>}
|
||||
*/
|
||||
this.on;
|
||||
|
||||
/***
|
||||
* @type {MousePositionOnSignature<import("../events").EventsKey>}
|
||||
*/
|
||||
this.once;
|
||||
|
||||
/***
|
||||
* @type {MousePositionOnSignature<void>}
|
||||
*/
|
||||
this.un;
|
||||
|
||||
this.addChangeListener(PROJECTION, this.handleProjectionChanged_);
|
||||
|
||||
if (options.coordinateFormat) {
|
||||
this.setCoordinateFormat(options.coordinateFormat);
|
||||
}
|
||||
if (options.projection) {
|
||||
this.setProjection(options.projection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change this to `false` when removing the deprecated `undefinedHTML` option.
|
||||
* @type {boolean}
|
||||
*/
|
||||
let renderOnMouseOut = true;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
let placeholder = ' ';
|
||||
|
||||
if ('undefinedHTML' in options) {
|
||||
// deprecated behavior
|
||||
if (options.undefinedHTML !== undefined) {
|
||||
placeholder = options.undefinedHTML;
|
||||
}
|
||||
renderOnMouseOut = !!placeholder;
|
||||
} else if ('placeholder' in options) {
|
||||
if (options.placeholder === false) {
|
||||
renderOnMouseOut = false;
|
||||
} else {
|
||||
placeholder = String(options.placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.placeholder_ = placeholder;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderOnMouseOut_ = renderOnMouseOut;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.renderedHTML_ = element.innerHTML;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.mapProjection_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?import("../proj.js").TransformFunction}
|
||||
*/
|
||||
this.transform_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleProjectionChanged_() {
|
||||
this.transform_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the coordinate format type used to render the current position or
|
||||
* undefined.
|
||||
* @return {import("../coordinate.js").CoordinateFormat|undefined} The format to render the current
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getCoordinateFormat() {
|
||||
return /** @type {import("../coordinate.js").CoordinateFormat|undefined} */ (
|
||||
this.get(COORDINATE_FORMAT)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the projection that is used to report the mouse position.
|
||||
* @return {import("../proj/Projection.js").default|undefined} The projection to report mouse
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getProjection() {
|
||||
return /** @type {import("../proj/Projection.js").default|undefined} */ (
|
||||
this.get(PROJECTION)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event Browser event.
|
||||
* @protected
|
||||
*/
|
||||
handleMouseMove(event) {
|
||||
const map = this.getMap();
|
||||
this.updateHTML_(map.getEventPixel(event));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event} event Browser event.
|
||||
* @protected
|
||||
*/
|
||||
handleMouseOut(event) {
|
||||
this.updateHTML_(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Pass `null` to just remove the control from the current map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {import("../PluggableMap.js").default|null} map Map.
|
||||
* @api
|
||||
*/
|
||||
setMap(map) {
|
||||
super.setMap(map);
|
||||
if (map) {
|
||||
const viewport = map.getViewport();
|
||||
this.listenerKeys.push(
|
||||
listen(viewport, EventType.POINTERMOVE, this.handleMouseMove, this)
|
||||
);
|
||||
if (this.renderOnMouseOut_) {
|
||||
this.listenerKeys.push(
|
||||
listen(viewport, EventType.POINTEROUT, this.handleMouseOut, this)
|
||||
);
|
||||
}
|
||||
this.updateHTML_(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the coordinate format type used to render the current position.
|
||||
* @param {import("../coordinate.js").CoordinateFormat} format The format to render the current
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setCoordinateFormat(format) {
|
||||
this.set(COORDINATE_FORMAT, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the projection that is used to report the mouse position.
|
||||
* @param {import("../proj.js").ProjectionLike} projection The projection to report mouse
|
||||
* position in.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setProjection(projection) {
|
||||
this.set(PROJECTION, getProjection(projection));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?import("../pixel.js").Pixel} pixel Pixel.
|
||||
* @private
|
||||
*/
|
||||
updateHTML_(pixel) {
|
||||
let html = this.placeholder_;
|
||||
if (pixel && this.mapProjection_) {
|
||||
if (!this.transform_) {
|
||||
const projection = this.getProjection();
|
||||
if (projection) {
|
||||
this.transform_ = getTransformFromProjections(
|
||||
this.mapProjection_,
|
||||
projection
|
||||
);
|
||||
} else {
|
||||
this.transform_ = identityTransform;
|
||||
}
|
||||
}
|
||||
const map = this.getMap();
|
||||
const coordinate = map.getCoordinateFromPixelInternal(pixel);
|
||||
if (coordinate) {
|
||||
const userProjection = getUserProjection();
|
||||
if (userProjection) {
|
||||
this.transform_ = getTransformFromProjections(
|
||||
this.mapProjection_,
|
||||
userProjection
|
||||
);
|
||||
}
|
||||
this.transform_(coordinate, coordinate);
|
||||
const coordinateFormat = this.getCoordinateFormat();
|
||||
if (coordinateFormat) {
|
||||
html = coordinateFormat(coordinate);
|
||||
} else {
|
||||
html = coordinate.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this.renderedHTML_ || html !== this.renderedHTML_) {
|
||||
this.element.innerHTML = html;
|
||||
this.renderedHTML_ = html;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the projection. Rendering of the coordinates is done in
|
||||
* `handleMouseMove` and `handleMouseUp`.
|
||||
* @param {import("../MapEvent.js").default} mapEvent Map event.
|
||||
* @override
|
||||
*/
|
||||
render(mapEvent) {
|
||||
const frameState = mapEvent.frameState;
|
||||
if (!frameState) {
|
||||
this.mapProjection_ = null;
|
||||
} else {
|
||||
if (this.mapProjection_ != frameState.viewState.projection) {
|
||||
this.mapProjection_ = frameState.viewState.projection;
|
||||
this.transform_ = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default MousePosition;
|
||||
682
node_modules/ol/src/control/OverviewMap.js
generated
vendored
Normal file
682
node_modules/ol/src/control/OverviewMap.js
generated
vendored
Normal file
@@ -0,0 +1,682 @@
|
||||
/**
|
||||
* @module ol/control/OverviewMap
|
||||
*/
|
||||
import CompositeMapRenderer from '../renderer/Composite.js';
|
||||
import Control from './Control.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import MapEventType from '../MapEventType.js';
|
||||
import MapProperty from '../MapProperty.js';
|
||||
import ObjectEventType from '../ObjectEventType.js';
|
||||
import Overlay from '../Overlay.js';
|
||||
import PluggableMap from '../PluggableMap.js';
|
||||
import View from '../View.js';
|
||||
import ViewProperty from '../ViewProperty.js';
|
||||
import {CLASS_COLLAPSED, CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {
|
||||
containsExtent,
|
||||
equals as equalsExtent,
|
||||
getBottomRight,
|
||||
getTopLeft,
|
||||
scaleFromCenter,
|
||||
} from '../extent.js';
|
||||
import {listen, listenOnce} from '../events.js';
|
||||
import {fromExtent as polygonFromExtent} from '../geom/Polygon.js';
|
||||
import {replaceNode} from '../dom.js';
|
||||
|
||||
/**
|
||||
* Maximum width and/or height extent ratio that determines when the overview
|
||||
* map should be zoomed out.
|
||||
* @type {number}
|
||||
*/
|
||||
const MAX_RATIO = 0.75;
|
||||
|
||||
/**
|
||||
* Minimum width and/or height extent ratio that determines when the overview
|
||||
* map should be zoomed in.
|
||||
* @type {number}
|
||||
*/
|
||||
const MIN_RATIO = 0.1;
|
||||
|
||||
class ControlledMap extends PluggableMap {
|
||||
createRenderer() {
|
||||
return new CompositeMapRenderer(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-overviewmap'] CSS class name.
|
||||
* @property {boolean} [collapsed=true] Whether the control should start collapsed or not (expanded).
|
||||
* @property {string|HTMLElement} [collapseLabel='‹'] Text label to use for the
|
||||
* expanded overviewmap button. Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {boolean} [collapsible=true] Whether the control can be collapsed or not.
|
||||
* @property {string|HTMLElement} [label='›'] Text label to use for the collapsed
|
||||
* overviewmap button. Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {Array<import("../layer/Base.js").default>|import("../Collection.js").default<import("../layer/Base.js").default>} [layers]
|
||||
* Layers for the overview map.
|
||||
* @property {function(import("../MapEvent.js").default):void} [render] Function called when the control
|
||||
* should be re-rendered. This is called in a `requestAnimationFrame` callback.
|
||||
* @property {boolean} [rotateWithView=false] Whether the control view should rotate with the main map view.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the control
|
||||
* to be rendered outside of the map's viewport.
|
||||
* @property {string} [tipLabel='Overview map'] Text label to use for the button tip.
|
||||
* @property {View} [view] Custom view for the overview map (should use same projection as main map). If not provided,
|
||||
* a default view with the same projection as the main map will be used.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a new control with a map acting as an overview map for another
|
||||
* defined map.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class OverviewMap extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] OverviewMap options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
element: document.createElement('div'),
|
||||
render: options.render,
|
||||
target: options.target,
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.boundHandleRotationChanged_ = this.handleRotationChanged_.bind(this);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.collapsed_ =
|
||||
options.collapsed !== undefined ? options.collapsed : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.collapsible_ =
|
||||
options.collapsible !== undefined ? options.collapsible : true;
|
||||
|
||||
if (!this.collapsible_) {
|
||||
this.collapsed_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.rotateWithView_ =
|
||||
options.rotateWithView !== undefined ? options.rotateWithView : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../extent.js").Extent|undefined}
|
||||
*/
|
||||
this.viewExtent_ = undefined;
|
||||
|
||||
const className =
|
||||
options.className !== undefined ? options.className : 'ol-overviewmap';
|
||||
|
||||
const tipLabel =
|
||||
options.tipLabel !== undefined ? options.tipLabel : 'Overview map';
|
||||
|
||||
const collapseLabel =
|
||||
options.collapseLabel !== undefined ? options.collapseLabel : '\u2039';
|
||||
|
||||
if (typeof collapseLabel === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.collapseLabel_ = document.createElement('span');
|
||||
this.collapseLabel_.textContent = collapseLabel;
|
||||
} else {
|
||||
this.collapseLabel_ = collapseLabel;
|
||||
}
|
||||
|
||||
const label = options.label !== undefined ? options.label : '\u203A';
|
||||
|
||||
if (typeof label === 'string') {
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.textContent = label;
|
||||
} else {
|
||||
this.label_ = label;
|
||||
}
|
||||
|
||||
const activeLabel =
|
||||
this.collapsible_ && !this.collapsed_ ? this.collapseLabel_ : this.label_;
|
||||
const button = document.createElement('button');
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(activeLabel);
|
||||
|
||||
button.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleClick_.bind(this),
|
||||
false
|
||||
);
|
||||
|
||||
/**
|
||||
* @type {HTMLElement}
|
||||
* @private
|
||||
*/
|
||||
this.ovmapDiv_ = document.createElement('div');
|
||||
this.ovmapDiv_.className = 'ol-overviewmap-map';
|
||||
|
||||
/**
|
||||
* Explicitly given view to be used instead of a view derived from the main map.
|
||||
* @type {View}
|
||||
* @private
|
||||
*/
|
||||
this.view_ = options.view;
|
||||
|
||||
/**
|
||||
* @type {ControlledMap}
|
||||
* @private
|
||||
*/
|
||||
this.ovmap_ = new ControlledMap({
|
||||
view: options.view,
|
||||
});
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (options.layers) {
|
||||
options.layers.forEach(function (layer) {
|
||||
ovmap.addLayer(layer);
|
||||
});
|
||||
}
|
||||
|
||||
const box = document.createElement('div');
|
||||
box.className = 'ol-overviewmap-box';
|
||||
box.style.boxSizing = 'border-box';
|
||||
|
||||
/**
|
||||
* @type {import("../Overlay.js").default}
|
||||
* @private
|
||||
*/
|
||||
this.boxOverlay_ = new Overlay({
|
||||
position: [0, 0],
|
||||
positioning: 'center-center',
|
||||
element: box,
|
||||
});
|
||||
this.ovmap_.addOverlay(this.boxOverlay_);
|
||||
|
||||
const cssClasses =
|
||||
className +
|
||||
' ' +
|
||||
CLASS_UNSELECTABLE +
|
||||
' ' +
|
||||
CLASS_CONTROL +
|
||||
(this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') +
|
||||
(this.collapsible_ ? '' : ' ol-uncollapsible');
|
||||
const element = this.element;
|
||||
element.className = cssClasses;
|
||||
element.appendChild(this.ovmapDiv_);
|
||||
element.appendChild(button);
|
||||
|
||||
/* Interactive map */
|
||||
|
||||
const scope = this;
|
||||
|
||||
const overlay = this.boxOverlay_;
|
||||
const overlayBox = this.boxOverlay_.getElement();
|
||||
|
||||
/* Functions definition */
|
||||
|
||||
const computeDesiredMousePosition = function (mousePosition) {
|
||||
return {
|
||||
clientX: mousePosition.clientX,
|
||||
clientY: mousePosition.clientY,
|
||||
};
|
||||
};
|
||||
|
||||
const move = function (event) {
|
||||
const position = /** @type {?} */ (computeDesiredMousePosition(event));
|
||||
const coordinates = ovmap.getEventCoordinateInternal(
|
||||
/** @type {MouseEvent} */ (position)
|
||||
);
|
||||
|
||||
overlay.setPosition(coordinates);
|
||||
};
|
||||
|
||||
const endMoving = function (event) {
|
||||
const coordinates = ovmap.getEventCoordinateInternal(event);
|
||||
|
||||
scope.getMap().getView().setCenterInternal(coordinates);
|
||||
|
||||
window.removeEventListener('mousemove', move);
|
||||
window.removeEventListener('mouseup', endMoving);
|
||||
};
|
||||
|
||||
/* Binding */
|
||||
|
||||
overlayBox.addEventListener('mousedown', function () {
|
||||
window.addEventListener('mousemove', move);
|
||||
window.addEventListener('mouseup', endMoving);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Pass `null` to just remove the control from the current map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {import("../PluggableMap.js").default|null} map Map.
|
||||
* @api
|
||||
*/
|
||||
setMap(map) {
|
||||
const oldMap = this.getMap();
|
||||
if (map === oldMap) {
|
||||
return;
|
||||
}
|
||||
if (oldMap) {
|
||||
const oldView = oldMap.getView();
|
||||
if (oldView) {
|
||||
this.unbindView_(oldView);
|
||||
}
|
||||
this.ovmap_.setTarget(null);
|
||||
}
|
||||
super.setMap(map);
|
||||
|
||||
if (map) {
|
||||
this.ovmap_.setTarget(this.ovmapDiv_);
|
||||
this.listenerKeys.push(
|
||||
listen(
|
||||
map,
|
||||
ObjectEventType.PROPERTYCHANGE,
|
||||
this.handleMapPropertyChange_,
|
||||
this
|
||||
)
|
||||
);
|
||||
|
||||
const view = map.getView();
|
||||
if (view) {
|
||||
this.bindView_(view);
|
||||
if (view.isDef()) {
|
||||
this.ovmap_.updateSize();
|
||||
this.resetExtent_();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.ovmap_.isRendered()) {
|
||||
this.updateBoxAfterOvmapIsRendered_();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle map property changes. This only deals with changes to the map's view.
|
||||
* @param {import("../Object.js").ObjectEvent} event The propertychange event.
|
||||
* @private
|
||||
*/
|
||||
handleMapPropertyChange_(event) {
|
||||
if (event.key === MapProperty.VIEW) {
|
||||
const oldView = /** @type {import("../View.js").default} */ (
|
||||
event.oldValue
|
||||
);
|
||||
if (oldView) {
|
||||
this.unbindView_(oldView);
|
||||
}
|
||||
const newView = this.getMap().getView();
|
||||
this.bindView_(newView);
|
||||
} else if (
|
||||
!this.ovmap_.isRendered() &&
|
||||
(event.key === MapProperty.TARGET || event.key === MapProperty.SIZE)
|
||||
) {
|
||||
this.ovmap_.updateSize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register listeners for view property changes.
|
||||
* @param {import("../View.js").default} view The view.
|
||||
* @private
|
||||
*/
|
||||
bindView_(view) {
|
||||
if (!this.view_) {
|
||||
// Unless an explicit view definition was given, derive default from whatever main map uses.
|
||||
const newView = new View({
|
||||
projection: view.getProjection(),
|
||||
});
|
||||
this.ovmap_.setView(newView);
|
||||
}
|
||||
|
||||
view.addChangeListener(
|
||||
ViewProperty.ROTATION,
|
||||
this.boundHandleRotationChanged_
|
||||
);
|
||||
// Sync once with the new view
|
||||
this.handleRotationChanged_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister listeners for view property changes.
|
||||
* @param {import("../View.js").default} view The view.
|
||||
* @private
|
||||
*/
|
||||
unbindView_(view) {
|
||||
view.removeChangeListener(
|
||||
ViewProperty.ROTATION,
|
||||
this.boundHandleRotationChanged_
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle rotation changes to the main map.
|
||||
* @private
|
||||
*/
|
||||
handleRotationChanged_() {
|
||||
if (this.rotateWithView_) {
|
||||
this.ovmap_.getView().setRotation(this.getMap().getView().getRotation());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the overview map extent if the box size (width or
|
||||
* height) is less than the size of the overview map size times minRatio
|
||||
* or is greater than the size of the overview size times maxRatio.
|
||||
*
|
||||
* If the map extent was not reset, the box size can fits in the defined
|
||||
* ratio sizes. This method then checks if is contained inside the overview
|
||||
* map current extent. If not, recenter the overview map to the current
|
||||
* main map center location.
|
||||
* @private
|
||||
*/
|
||||
validateExtent_() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (!map.isRendered() || !ovmap.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mapSize = /** @type {import("../size.js").Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
const extent = view.calculateExtentInternal(mapSize);
|
||||
|
||||
if (this.viewExtent_ && equalsExtent(extent, this.viewExtent_)) {
|
||||
// repeats of the same extent may indicate constraint conflicts leading to an endless cycle
|
||||
return;
|
||||
}
|
||||
this.viewExtent_ = extent;
|
||||
|
||||
const ovmapSize = /** @type {import("../size.js").Size} */ (
|
||||
ovmap.getSize()
|
||||
);
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
const ovextent = ovview.calculateExtentInternal(ovmapSize);
|
||||
|
||||
const topLeftPixel = ovmap.getPixelFromCoordinateInternal(
|
||||
getTopLeft(extent)
|
||||
);
|
||||
const bottomRightPixel = ovmap.getPixelFromCoordinateInternal(
|
||||
getBottomRight(extent)
|
||||
);
|
||||
|
||||
const boxWidth = Math.abs(topLeftPixel[0] - bottomRightPixel[0]);
|
||||
const boxHeight = Math.abs(topLeftPixel[1] - bottomRightPixel[1]);
|
||||
|
||||
const ovmapWidth = ovmapSize[0];
|
||||
const ovmapHeight = ovmapSize[1];
|
||||
|
||||
if (
|
||||
boxWidth < ovmapWidth * MIN_RATIO ||
|
||||
boxHeight < ovmapHeight * MIN_RATIO ||
|
||||
boxWidth > ovmapWidth * MAX_RATIO ||
|
||||
boxHeight > ovmapHeight * MAX_RATIO
|
||||
) {
|
||||
this.resetExtent_();
|
||||
} else if (!containsExtent(ovextent, extent)) {
|
||||
this.recenter_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the overview map extent to half calculated min and max ratio times
|
||||
* the extent of the main map.
|
||||
* @private
|
||||
*/
|
||||
resetExtent_() {
|
||||
if (MAX_RATIO === 0 || MIN_RATIO === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
const mapSize = /** @type {import("../size.js").Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
const extent = view.calculateExtentInternal(mapSize);
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
// get how many times the current map overview could hold different
|
||||
// box sizes using the min and max ratio, pick the step in the middle used
|
||||
// to calculate the extent from the main map to set it to the overview map,
|
||||
const steps = Math.log(MAX_RATIO / MIN_RATIO) / Math.LN2;
|
||||
const ratio = 1 / (Math.pow(2, steps / 2) * MIN_RATIO);
|
||||
scaleFromCenter(extent, ratio);
|
||||
ovview.fitInternal(polygonFromExtent(extent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the center of the overview map to the map center without changing its
|
||||
* resolution.
|
||||
* @private
|
||||
*/
|
||||
recenter_() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
const view = map.getView();
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
ovview.setCenterInternal(view.getCenterInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the box using the main map extent
|
||||
* @private
|
||||
*/
|
||||
updateBox_() {
|
||||
const map = this.getMap();
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (!map.isRendered() || !ovmap.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mapSize = /** @type {import("../size.js").Size} */ (map.getSize());
|
||||
|
||||
const view = map.getView();
|
||||
|
||||
const ovview = ovmap.getView();
|
||||
|
||||
const rotation = this.rotateWithView_ ? 0 : -view.getRotation();
|
||||
|
||||
const overlay = this.boxOverlay_;
|
||||
const box = this.boxOverlay_.getElement();
|
||||
const center = view.getCenterInternal();
|
||||
const resolution = view.getResolution();
|
||||
const ovresolution = ovview.getResolution();
|
||||
const width = (mapSize[0] * resolution) / ovresolution;
|
||||
const height = (mapSize[1] * resolution) / ovresolution;
|
||||
|
||||
// set position using center coordinates
|
||||
overlay.setPosition(center);
|
||||
|
||||
// set box size calculated from map extent size and overview map resolution
|
||||
if (box) {
|
||||
box.style.width = width + 'px';
|
||||
box.style.height = height + 'px';
|
||||
const transform = 'rotate(' + rotation + 'rad)';
|
||||
box.style.transform = transform;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
updateBoxAfterOvmapIsRendered_() {
|
||||
if (this.ovmapPostrenderKey_) {
|
||||
return;
|
||||
}
|
||||
this.ovmapPostrenderKey_ = listenOnce(
|
||||
this.ovmap_,
|
||||
MapEventType.POSTRENDER,
|
||||
function (event) {
|
||||
delete this.ovmapPostrenderKey_;
|
||||
this.updateBox_();
|
||||
},
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
this.handleToggle_();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleToggle_() {
|
||||
this.element.classList.toggle(CLASS_COLLAPSED);
|
||||
if (this.collapsed_) {
|
||||
replaceNode(this.collapseLabel_, this.label_);
|
||||
} else {
|
||||
replaceNode(this.label_, this.collapseLabel_);
|
||||
}
|
||||
this.collapsed_ = !this.collapsed_;
|
||||
|
||||
// manage overview map if it had not been rendered before and control
|
||||
// is expanded
|
||||
const ovmap = this.ovmap_;
|
||||
if (!this.collapsed_) {
|
||||
if (ovmap.isRendered()) {
|
||||
this.viewExtent_ = undefined;
|
||||
ovmap.render();
|
||||
return;
|
||||
}
|
||||
ovmap.updateSize();
|
||||
this.resetExtent_();
|
||||
this.updateBoxAfterOvmapIsRendered_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if the overview map is collapsible, `false` otherwise.
|
||||
* @return {boolean} True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
getCollapsible() {
|
||||
return this.collapsible_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the overview map should be collapsible.
|
||||
* @param {boolean} collapsible True if the widget is collapsible.
|
||||
* @api
|
||||
*/
|
||||
setCollapsible(collapsible) {
|
||||
if (this.collapsible_ === collapsible) {
|
||||
return;
|
||||
}
|
||||
this.collapsible_ = collapsible;
|
||||
this.element.classList.toggle('ol-uncollapsible');
|
||||
if (!collapsible && this.collapsed_) {
|
||||
this.handleToggle_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse or expand the overview map according to the passed parameter. Will
|
||||
* not do anything if the overview map isn't collapsible or if the current
|
||||
* collapsed state is already the one requested.
|
||||
* @param {boolean} collapsed True if the widget is collapsed.
|
||||
* @api
|
||||
*/
|
||||
setCollapsed(collapsed) {
|
||||
if (!this.collapsible_ || this.collapsed_ === collapsed) {
|
||||
return;
|
||||
}
|
||||
this.handleToggle_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the overview map is collapsed.
|
||||
* @return {boolean} The overview map is collapsed.
|
||||
* @api
|
||||
*/
|
||||
getCollapsed() {
|
||||
return this.collapsed_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if the overview map view can rotate, `false` otherwise.
|
||||
* @return {boolean} True if the control view can rotate.
|
||||
* @api
|
||||
*/
|
||||
getRotateWithView() {
|
||||
return this.rotateWithView_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the overview map view should rotate with the main map view.
|
||||
* @param {boolean} rotateWithView True if the control view should rotate.
|
||||
* @api
|
||||
*/
|
||||
setRotateWithView(rotateWithView) {
|
||||
if (this.rotateWithView_ === rotateWithView) {
|
||||
return;
|
||||
}
|
||||
this.rotateWithView_ = rotateWithView;
|
||||
if (this.getMap().getView().getRotation() !== 0) {
|
||||
if (this.rotateWithView_) {
|
||||
this.handleRotationChanged_();
|
||||
} else {
|
||||
this.ovmap_.getView().setRotation(0);
|
||||
}
|
||||
this.viewExtent_ = undefined;
|
||||
this.validateExtent_();
|
||||
this.updateBox_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the overview map.
|
||||
* @return {import("../PluggableMap.js").default} Overview map.
|
||||
* @api
|
||||
*/
|
||||
getOverviewMap() {
|
||||
return this.ovmap_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the overview map element.
|
||||
* @param {import("../MapEvent.js").default} mapEvent Map event.
|
||||
* @override
|
||||
*/
|
||||
render(mapEvent) {
|
||||
this.validateExtent_();
|
||||
this.updateBox_();
|
||||
}
|
||||
}
|
||||
|
||||
export default OverviewMap;
|
||||
182
node_modules/ol/src/control/Rotate.js
generated
vendored
Normal file
182
node_modules/ol/src/control/Rotate.js
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* @module ol/control/Rotate
|
||||
*/
|
||||
import Control from './Control.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import {CLASS_CONTROL, CLASS_HIDDEN, CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {easeOut} from '../easing.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-rotate'] CSS class name.
|
||||
* @property {string|HTMLElement} [label='⇧'] Text label to use for the rotate button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [tipLabel='Reset rotation'] Text label to use for the rotate tip.
|
||||
* @property {string} [compassClassName='ol-compass'] CSS class name for the compass.
|
||||
* @property {number} [duration=250] Animation duration in milliseconds.
|
||||
* @property {boolean} [autoHide=true] Hide the control when rotation is 0.
|
||||
* @property {function(import("../MapEvent.js").default):void} [render] Function called when the control should
|
||||
* be re-rendered. This is called in a `requestAnimationFrame` callback.
|
||||
* @property {function():void} [resetNorth] Function called when the control is clicked.
|
||||
* This will override the default `resetNorth`.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the control to be
|
||||
* rendered outside of the map's viewport.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A button control to reset rotation to 0.
|
||||
* To style this control use css selector `.ol-rotate`. A `.ol-hidden` css
|
||||
* selector is added to the button when the rotation is 0.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Rotate extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] Rotate options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
element: document.createElement('div'),
|
||||
render: options.render,
|
||||
target: options.target,
|
||||
});
|
||||
|
||||
const className =
|
||||
options.className !== undefined ? options.className : 'ol-rotate';
|
||||
|
||||
const label = options.label !== undefined ? options.label : '\u21E7';
|
||||
|
||||
const compassClassName =
|
||||
options.compassClassName !== undefined
|
||||
? options.compassClassName
|
||||
: 'ol-compass';
|
||||
|
||||
/**
|
||||
* @type {HTMLElement}
|
||||
* @private
|
||||
*/
|
||||
this.label_ = null;
|
||||
|
||||
if (typeof label === 'string') {
|
||||
this.label_ = document.createElement('span');
|
||||
this.label_.className = compassClassName;
|
||||
this.label_.textContent = label;
|
||||
} else {
|
||||
this.label_ = label;
|
||||
this.label_.classList.add(compassClassName);
|
||||
}
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Reset rotation';
|
||||
|
||||
const button = document.createElement('button');
|
||||
button.className = className + '-reset';
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(this.label_);
|
||||
|
||||
button.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleClick_.bind(this),
|
||||
false
|
||||
);
|
||||
|
||||
const cssClasses =
|
||||
className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = this.element;
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
|
||||
this.callResetNorth_ = options.resetNorth ? options.resetNorth : undefined;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.autoHide_ = options.autoHide !== undefined ? options.autoHide : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.rotation_ = undefined;
|
||||
|
||||
if (this.autoHide_) {
|
||||
this.element.classList.add(CLASS_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
if (this.callResetNorth_ !== undefined) {
|
||||
this.callResetNorth_();
|
||||
} else {
|
||||
this.resetNorth_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
resetNorth_() {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
if (!view) {
|
||||
// the map does not have a view, so we can't act
|
||||
// upon it
|
||||
return;
|
||||
}
|
||||
const rotation = view.getRotation();
|
||||
if (rotation !== undefined) {
|
||||
if (this.duration_ > 0 && rotation % (2 * Math.PI) !== 0) {
|
||||
view.animate({
|
||||
rotation: 0,
|
||||
duration: this.duration_,
|
||||
easing: easeOut,
|
||||
});
|
||||
} else {
|
||||
view.setRotation(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the rotate control element.
|
||||
* @param {import("../MapEvent.js").default} mapEvent Map event.
|
||||
* @override
|
||||
*/
|
||||
render(mapEvent) {
|
||||
const frameState = mapEvent.frameState;
|
||||
if (!frameState) {
|
||||
return;
|
||||
}
|
||||
const rotation = frameState.viewState.rotation;
|
||||
if (rotation != this.rotation_) {
|
||||
const transform = 'rotate(' + rotation + 'rad)';
|
||||
if (this.autoHide_) {
|
||||
const contains = this.element.classList.contains(CLASS_HIDDEN);
|
||||
if (!contains && rotation === 0) {
|
||||
this.element.classList.add(CLASS_HIDDEN);
|
||||
} else if (contains && rotation !== 0) {
|
||||
this.element.classList.remove(CLASS_HIDDEN);
|
||||
}
|
||||
}
|
||||
this.label_.style.transform = transform;
|
||||
}
|
||||
this.rotation_ = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
export default Rotate;
|
||||
532
node_modules/ol/src/control/ScaleLine.js
generated
vendored
Normal file
532
node_modules/ol/src/control/ScaleLine.js
generated
vendored
Normal file
@@ -0,0 +1,532 @@
|
||||
/**
|
||||
* @module ol/control/ScaleLine
|
||||
*/
|
||||
import Control from './Control.js';
|
||||
import ProjUnits from '../proj/Units.js';
|
||||
import {CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {METERS_PER_UNIT, getPointResolution} from '../proj.js';
|
||||
import {assert} from '../asserts.js';
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
const UNITS_PROP = 'units';
|
||||
|
||||
/**
|
||||
* Units for the scale line. Supported values are `'degrees'`, `'imperial'`,
|
||||
* `'nautical'`, `'metric'`, `'us'`.
|
||||
* @enum {string}
|
||||
*/
|
||||
export const Units = {
|
||||
DEGREES: 'degrees',
|
||||
IMPERIAL: 'imperial',
|
||||
NAUTICAL: 'nautical',
|
||||
METRIC: 'metric',
|
||||
US: 'us',
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array<number>}
|
||||
*/
|
||||
const LEADING_DIGITS = [1, 2, 5];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {number}
|
||||
*/
|
||||
const DEFAULT_DPI = 25.4 / 0.28;
|
||||
|
||||
/***
|
||||
* @template Return
|
||||
* @typedef {import("../Observable").OnSignature<import("../Observable").EventTypes, import("../events/Event.js").default, Return> &
|
||||
* import("../Observable").OnSignature<import("../ObjectEventType").Types|
|
||||
* 'change:units', import("../Object").ObjectEvent, Return> &
|
||||
* import("../Observable").CombinedOnSignature<import("../Observable").EventTypes|import("../ObjectEventType").Types
|
||||
* |'change:units', Return>} ScaleLineOnSignature
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-scale-line'] CSS Class name.
|
||||
* @property {number} [minWidth=64] Minimum width in pixels at the OGC default dpi. The width will be
|
||||
* adjusted to match the dpi used.
|
||||
* @property {number} [maxWidth] Maximum width in pixels at the OGC default dpi. The width will be
|
||||
* adjusted to match the dpi used.
|
||||
* @property {function(import("../MapEvent.js").default):void} [render] Function called when the control
|
||||
* should be re-rendered. This is called in a `requestAnimationFrame` callback.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the control
|
||||
* to be rendered outside of the map's viewport.
|
||||
* @property {import("./ScaleLine.js").Units|string} [units='metric'] Units.
|
||||
* @property {boolean} [bar=false] Render scalebars instead of a line.
|
||||
* @property {number} [steps=4] Number of steps the scalebar should use. Use even numbers
|
||||
* for best results. Only applies when `bar` is `true`.
|
||||
* @property {boolean} [text=false] Render the text scale above of the scalebar. Only applies
|
||||
* when `bar` is `true`.
|
||||
* @property {number|undefined} [dpi=undefined] dpi of output device such as printer. Only applies
|
||||
* when `bar` is `true`. If undefined the OGC default screen pixel size of 0.28mm will be assumed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A control displaying rough y-axis distances, calculated for the center of the
|
||||
* viewport. For conformal projections (e.g. EPSG:3857, the default view
|
||||
* projection in OpenLayers), the scale is valid for all directions.
|
||||
* No scale line will be shown when the y-axis distance of a pixel at the
|
||||
* viewport center cannot be calculated in the view projection.
|
||||
* By default the scale line will show in the bottom left portion of the map,
|
||||
* but this can be changed by using the css selector `.ol-scale-line`.
|
||||
* When specifying `bar` as `true`, a scalebar will be rendered instead
|
||||
* of a scaleline.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ScaleLine extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] Scale line options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const className =
|
||||
options.className !== undefined
|
||||
? options.className
|
||||
: options.bar
|
||||
? 'ol-scale-bar'
|
||||
: 'ol-scale-line';
|
||||
|
||||
super({
|
||||
element: document.createElement('div'),
|
||||
render: options.render,
|
||||
target: options.target,
|
||||
});
|
||||
|
||||
/***
|
||||
* @type {ScaleLineOnSignature<import("../events").EventsKey>}
|
||||
*/
|
||||
this.on;
|
||||
|
||||
/***
|
||||
* @type {ScaleLineOnSignature<import("../events").EventsKey>}
|
||||
*/
|
||||
this.once;
|
||||
|
||||
/***
|
||||
* @type {ScaleLineOnSignature<void>}
|
||||
*/
|
||||
this.un;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.innerElement_ = document.createElement('div');
|
||||
this.innerElement_.className = className + '-inner';
|
||||
|
||||
this.element.className = className + ' ' + CLASS_UNSELECTABLE;
|
||||
this.element.appendChild(this.innerElement_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?import("../View.js").State}
|
||||
*/
|
||||
this.viewState_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.minWidth_ = options.minWidth !== undefined ? options.minWidth : 64;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.maxWidth_ = options.maxWidth;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.renderedVisible_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.renderedWidth_ = undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.renderedHTML_ = '';
|
||||
|
||||
this.addChangeListener(UNITS_PROP, this.handleUnitsChanged_);
|
||||
|
||||
this.setUnits(options.units || Units.METRIC);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.scaleBar_ = options.bar || false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.scaleBarSteps_ = options.steps || 4;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.scaleBarText_ = options.text || false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
this.dpi_ = options.dpi || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the units to use in the scale line.
|
||||
* @return {import("./ScaleLine.js").Units} The units
|
||||
* to use in the scale line.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getUnits() {
|
||||
return this.get(UNITS_PROP);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
handleUnitsChanged_() {
|
||||
this.updateElement_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the units to use in the scale line.
|
||||
* @param {import("./ScaleLine.js").Units} units The units to use in the scale line.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setUnits(units) {
|
||||
this.set(UNITS_PROP, units);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the dpi of output device such as printer.
|
||||
* @param {number|undefined} dpi The dpi of output device.
|
||||
* @api
|
||||
*/
|
||||
setDpi(dpi) {
|
||||
this.dpi_ = dpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
updateElement_() {
|
||||
const viewState = this.viewState_;
|
||||
|
||||
if (!viewState) {
|
||||
if (this.renderedVisible_) {
|
||||
this.element.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const center = viewState.center;
|
||||
const projection = viewState.projection;
|
||||
const units = this.getUnits();
|
||||
const pointResolutionUnits =
|
||||
units == Units.DEGREES ? ProjUnits.DEGREES : ProjUnits.METERS;
|
||||
let pointResolution = getPointResolution(
|
||||
projection,
|
||||
viewState.resolution,
|
||||
center,
|
||||
pointResolutionUnits
|
||||
);
|
||||
|
||||
const minWidth =
|
||||
(this.minWidth_ * (this.dpi_ || DEFAULT_DPI)) / DEFAULT_DPI;
|
||||
|
||||
const maxWidth =
|
||||
this.maxWidth_ !== undefined
|
||||
? (this.maxWidth_ * (this.dpi_ || DEFAULT_DPI)) / DEFAULT_DPI
|
||||
: undefined;
|
||||
|
||||
let nominalCount = minWidth * pointResolution;
|
||||
let suffix = '';
|
||||
if (units == Units.DEGREES) {
|
||||
const metersPerDegree = METERS_PER_UNIT[ProjUnits.DEGREES];
|
||||
nominalCount *= metersPerDegree;
|
||||
if (nominalCount < metersPerDegree / 60) {
|
||||
suffix = '\u2033'; // seconds
|
||||
pointResolution *= 3600;
|
||||
} else if (nominalCount < metersPerDegree) {
|
||||
suffix = '\u2032'; // minutes
|
||||
pointResolution *= 60;
|
||||
} else {
|
||||
suffix = '\u00b0'; // degrees
|
||||
}
|
||||
} else if (units == Units.IMPERIAL) {
|
||||
if (nominalCount < 0.9144) {
|
||||
suffix = 'in';
|
||||
pointResolution /= 0.0254;
|
||||
} else if (nominalCount < 1609.344) {
|
||||
suffix = 'ft';
|
||||
pointResolution /= 0.3048;
|
||||
} else {
|
||||
suffix = 'mi';
|
||||
pointResolution /= 1609.344;
|
||||
}
|
||||
} else if (units == Units.NAUTICAL) {
|
||||
pointResolution /= 1852;
|
||||
suffix = 'NM';
|
||||
} else if (units == Units.METRIC) {
|
||||
if (nominalCount < 0.001) {
|
||||
suffix = 'μm';
|
||||
pointResolution *= 1000000;
|
||||
} else if (nominalCount < 1) {
|
||||
suffix = 'mm';
|
||||
pointResolution *= 1000;
|
||||
} else if (nominalCount < 1000) {
|
||||
suffix = 'm';
|
||||
} else {
|
||||
suffix = 'km';
|
||||
pointResolution /= 1000;
|
||||
}
|
||||
} else if (units == Units.US) {
|
||||
if (nominalCount < 0.9144) {
|
||||
suffix = 'in';
|
||||
pointResolution *= 39.37;
|
||||
} else if (nominalCount < 1609.344) {
|
||||
suffix = 'ft';
|
||||
pointResolution /= 0.30480061;
|
||||
} else {
|
||||
suffix = 'mi';
|
||||
pointResolution /= 1609.3472;
|
||||
}
|
||||
} else {
|
||||
assert(false, 33); // Invalid units
|
||||
}
|
||||
|
||||
let i = 3 * Math.floor(Math.log(minWidth * pointResolution) / Math.log(10));
|
||||
let count, width, decimalCount;
|
||||
let previousCount, previousWidth, previousDecimalCount;
|
||||
while (true) {
|
||||
decimalCount = Math.floor(i / 3);
|
||||
const decimal = Math.pow(10, decimalCount);
|
||||
count = LEADING_DIGITS[((i % 3) + 3) % 3] * decimal;
|
||||
width = Math.round(count / pointResolution);
|
||||
if (isNaN(width)) {
|
||||
this.element.style.display = 'none';
|
||||
this.renderedVisible_ = false;
|
||||
return;
|
||||
}
|
||||
if (maxWidth !== undefined && width >= maxWidth) {
|
||||
count = previousCount;
|
||||
width = previousWidth;
|
||||
decimalCount = previousDecimalCount;
|
||||
break;
|
||||
} else if (width >= minWidth) {
|
||||
break;
|
||||
}
|
||||
previousCount = count;
|
||||
previousWidth = width;
|
||||
previousDecimalCount = decimalCount;
|
||||
++i;
|
||||
}
|
||||
let html;
|
||||
if (this.scaleBar_) {
|
||||
html = this.createScaleBar(width, count, suffix);
|
||||
} else {
|
||||
html = count.toFixed(decimalCount < 0 ? -decimalCount : 0) + ' ' + suffix;
|
||||
}
|
||||
|
||||
if (this.renderedHTML_ != html) {
|
||||
this.innerElement_.innerHTML = html;
|
||||
this.renderedHTML_ = html;
|
||||
}
|
||||
|
||||
if (this.renderedWidth_ != width) {
|
||||
this.innerElement_.style.width = width + 'px';
|
||||
this.renderedWidth_ = width;
|
||||
}
|
||||
|
||||
if (!this.renderedVisible_) {
|
||||
this.element.style.display = '';
|
||||
this.renderedVisible_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {number} width The current width of the scalebar.
|
||||
* @param {number} scale The current scale.
|
||||
* @param {string} suffix The suffix to append to the scale text.
|
||||
* @return {string} The stringified HTML of the scalebar.
|
||||
*/
|
||||
createScaleBar(width, scale, suffix) {
|
||||
const mapScale =
|
||||
'1 : ' + Math.round(this.getScaleForResolution()).toLocaleString();
|
||||
const scaleSteps = [];
|
||||
const stepWidth = width / this.scaleBarSteps_;
|
||||
let backgroundColor = 'ol-scale-singlebar-odd';
|
||||
for (let i = 0; i < this.scaleBarSteps_; i++) {
|
||||
if (i === 0) {
|
||||
// create the first marker at position 0
|
||||
scaleSteps.push(this.createMarker('absolute', i));
|
||||
}
|
||||
scaleSteps.push(
|
||||
'<div>' +
|
||||
'<div ' +
|
||||
'class="ol-scale-singlebar ' +
|
||||
backgroundColor +
|
||||
'" ' +
|
||||
'style=' +
|
||||
'"width: ' +
|
||||
stepWidth +
|
||||
'px;"' +
|
||||
'>' +
|
||||
'</div>' +
|
||||
this.createMarker('relative', i) +
|
||||
/*render text every second step, except when only 2 steps */
|
||||
(i % 2 === 0 || this.scaleBarSteps_ === 2
|
||||
? this.createStepText(i, width, false, scale, suffix)
|
||||
: '') +
|
||||
'</div>'
|
||||
);
|
||||
if (i === this.scaleBarSteps_ - 1) {
|
||||
{
|
||||
/*render text at the end */
|
||||
}
|
||||
scaleSteps.push(this.createStepText(i + 1, width, true, scale, suffix));
|
||||
}
|
||||
// switch style of steps
|
||||
backgroundColor =
|
||||
backgroundColor === 'ol-scale-singlebar-odd'
|
||||
? 'ol-scale-singlebar-even'
|
||||
: 'ol-scale-singlebar-odd';
|
||||
}
|
||||
|
||||
let scaleBarText;
|
||||
if (this.scaleBarText_) {
|
||||
scaleBarText =
|
||||
'<div ' +
|
||||
'class="ol-scale-text" ' +
|
||||
'style="width: ' +
|
||||
width +
|
||||
'px;">' +
|
||||
mapScale +
|
||||
'</div>';
|
||||
} else {
|
||||
scaleBarText = '';
|
||||
}
|
||||
const container =
|
||||
'<div ' +
|
||||
'style="display: flex;">' +
|
||||
scaleBarText +
|
||||
scaleSteps.join('') +
|
||||
'</div>';
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a marker at given position
|
||||
* @param {string} position The position, absolute or relative
|
||||
* @param {number} i The iterator
|
||||
* @return {string} The stringified div containing the marker
|
||||
*/
|
||||
createMarker(position, i) {
|
||||
const top = position === 'absolute' ? 3 : -10;
|
||||
return (
|
||||
'<div ' +
|
||||
'class="ol-scale-step-marker" ' +
|
||||
'style="position: ' +
|
||||
position +
|
||||
';' +
|
||||
'top: ' +
|
||||
top +
|
||||
'px;"' +
|
||||
'></div>'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the label for a marker marker at given position
|
||||
* @param {number} i The iterator
|
||||
* @param {number} width The width the scalebar will currently use
|
||||
* @param {boolean} isLast Flag indicating if we add the last step text
|
||||
* @param {number} scale The current scale for the whole scalebar
|
||||
* @param {string} suffix The suffix for the scale
|
||||
* @return {string} The stringified div containing the step text
|
||||
*/
|
||||
createStepText(i, width, isLast, scale, suffix) {
|
||||
const length =
|
||||
i === 0 ? 0 : Math.round((scale / this.scaleBarSteps_) * i * 100) / 100;
|
||||
const lengthString = length + (i === 0 ? '' : ' ' + suffix);
|
||||
const margin = i === 0 ? -3 : (width / this.scaleBarSteps_) * -1;
|
||||
const minWidth = i === 0 ? 0 : (width / this.scaleBarSteps_) * 2;
|
||||
return (
|
||||
'<div ' +
|
||||
'class="ol-scale-step-text" ' +
|
||||
'style="' +
|
||||
'margin-left: ' +
|
||||
margin +
|
||||
'px;' +
|
||||
'text-align: ' +
|
||||
(i === 0 ? 'left' : 'center') +
|
||||
'; ' +
|
||||
'min-width: ' +
|
||||
minWidth +
|
||||
'px;' +
|
||||
'left: ' +
|
||||
(isLast ? width + 'px' : 'unset') +
|
||||
';"' +
|
||||
'>' +
|
||||
lengthString +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate scale for the given resolution and units.
|
||||
* @return {number} The appropriate scale.
|
||||
*/
|
||||
getScaleForResolution() {
|
||||
const resolution = getPointResolution(
|
||||
this.viewState_.projection,
|
||||
this.viewState_.resolution,
|
||||
this.viewState_.center,
|
||||
ProjUnits.METERS
|
||||
);
|
||||
const dpi = this.dpi_ || DEFAULT_DPI;
|
||||
const inchesPerMeter = 1000 / 25.4;
|
||||
return parseFloat(resolution.toString()) * inchesPerMeter * dpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the scale line element.
|
||||
* @param {import("../MapEvent.js").default} mapEvent Map event.
|
||||
* @override
|
||||
*/
|
||||
render(mapEvent) {
|
||||
const frameState = mapEvent.frameState;
|
||||
if (!frameState) {
|
||||
this.viewState_ = null;
|
||||
} else {
|
||||
this.viewState_ = frameState.viewState;
|
||||
}
|
||||
this.updateElement_();
|
||||
}
|
||||
}
|
||||
|
||||
export default ScaleLine;
|
||||
160
node_modules/ol/src/control/Zoom.js
generated
vendored
Normal file
160
node_modules/ol/src/control/Zoom.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* @module ol/control/Zoom
|
||||
*/
|
||||
import Control from './Control.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {easeOut} from '../easing.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {number} [duration=250] Animation duration in milliseconds.
|
||||
* @property {string} [className='ol-zoom'] CSS class name.
|
||||
* @property {string} [zoomInClassName=className + '-in'] CSS class name for the zoom-in button.
|
||||
* @property {string} [zoomOutClassName=className + '-out'] CSS class name for the zoom-out button.
|
||||
* @property {string|HTMLElement} [zoomInLabel='+'] Text label to use for the zoom-in
|
||||
* button. Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string|HTMLElement} [zoomOutLabel='–'] Text label to use for the zoom-out button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [zoomInTipLabel='Zoom in'] Text label to use for the button tip.
|
||||
* @property {string} [zoomOutTipLabel='Zoom out'] Text label to use for the button tip.
|
||||
* @property {number} [delta=1] The zoom delta applied on each click.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the control to be
|
||||
* rendered outside of the map's viewport.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A control with 2 buttons, one for zoom in and one for zoom out.
|
||||
* This control is one of the default controls of a map. To style this control
|
||||
* use css selectors `.ol-zoom-in` and `.ol-zoom-out`.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Zoom extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] Zoom options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
element: document.createElement('div'),
|
||||
target: options.target,
|
||||
});
|
||||
|
||||
const className =
|
||||
options.className !== undefined ? options.className : 'ol-zoom';
|
||||
|
||||
const delta = options.delta !== undefined ? options.delta : 1;
|
||||
|
||||
const zoomInClassName =
|
||||
options.zoomInClassName !== undefined
|
||||
? options.zoomInClassName
|
||||
: className + '-in';
|
||||
|
||||
const zoomOutClassName =
|
||||
options.zoomOutClassName !== undefined
|
||||
? options.zoomOutClassName
|
||||
: className + '-out';
|
||||
|
||||
const zoomInLabel =
|
||||
options.zoomInLabel !== undefined ? options.zoomInLabel : '+';
|
||||
const zoomOutLabel =
|
||||
options.zoomOutLabel !== undefined ? options.zoomOutLabel : '\u2013';
|
||||
|
||||
const zoomInTipLabel =
|
||||
options.zoomInTipLabel !== undefined ? options.zoomInTipLabel : 'Zoom in';
|
||||
const zoomOutTipLabel =
|
||||
options.zoomOutTipLabel !== undefined
|
||||
? options.zoomOutTipLabel
|
||||
: 'Zoom out';
|
||||
|
||||
const inElement = document.createElement('button');
|
||||
inElement.className = zoomInClassName;
|
||||
inElement.setAttribute('type', 'button');
|
||||
inElement.title = zoomInTipLabel;
|
||||
inElement.appendChild(
|
||||
typeof zoomInLabel === 'string'
|
||||
? document.createTextNode(zoomInLabel)
|
||||
: zoomInLabel
|
||||
);
|
||||
|
||||
inElement.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleClick_.bind(this, delta),
|
||||
false
|
||||
);
|
||||
|
||||
const outElement = document.createElement('button');
|
||||
outElement.className = zoomOutClassName;
|
||||
outElement.setAttribute('type', 'button');
|
||||
outElement.title = zoomOutTipLabel;
|
||||
outElement.appendChild(
|
||||
typeof zoomOutLabel === 'string'
|
||||
? document.createTextNode(zoomOutLabel)
|
||||
: zoomOutLabel
|
||||
);
|
||||
|
||||
outElement.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleClick_.bind(this, -delta),
|
||||
false
|
||||
);
|
||||
|
||||
const cssClasses =
|
||||
className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = this.element;
|
||||
element.className = cssClasses;
|
||||
element.appendChild(inElement);
|
||||
element.appendChild(outElement);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 250;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} delta Zoom delta.
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(delta, event) {
|
||||
event.preventDefault();
|
||||
this.zoomByDelta_(delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} delta Zoom delta.
|
||||
* @private
|
||||
*/
|
||||
zoomByDelta_(delta) {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
if (!view) {
|
||||
// the map does not have a view, so we can't act
|
||||
// upon it
|
||||
return;
|
||||
}
|
||||
const currentZoom = view.getZoom();
|
||||
if (currentZoom !== undefined) {
|
||||
const newZoom = view.getConstrainedZoom(currentZoom + delta);
|
||||
if (this.duration_ > 0) {
|
||||
if (view.getAnimating()) {
|
||||
view.cancelAnimations();
|
||||
}
|
||||
view.animate({
|
||||
zoom: newZoom,
|
||||
duration: this.duration_,
|
||||
easing: easeOut,
|
||||
});
|
||||
} else {
|
||||
view.setZoom(newZoom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Zoom;
|
||||
388
node_modules/ol/src/control/ZoomSlider.js
generated
vendored
Normal file
388
node_modules/ol/src/control/ZoomSlider.js
generated
vendored
Normal file
@@ -0,0 +1,388 @@
|
||||
/**
|
||||
* @module ol/control/ZoomSlider
|
||||
*/
|
||||
|
||||
import Control from './Control.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import PointerEventType from '../pointer/EventType.js';
|
||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {clamp} from '../math.js';
|
||||
import {easeOut} from '../easing.js';
|
||||
import {listen, unlistenByKey} from '../events.js';
|
||||
import {stopPropagation} from '../events/Event.js';
|
||||
|
||||
/**
|
||||
* The enum for available directions.
|
||||
*
|
||||
* @enum {number}
|
||||
*/
|
||||
const Direction = {
|
||||
VERTICAL: 0,
|
||||
HORIZONTAL: 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-zoomslider'] CSS class name.
|
||||
* @property {number} [duration=200] Animation duration in milliseconds.
|
||||
* @property {function(import("../MapEvent.js").default):void} [render] Function called when the control
|
||||
* should be re-rendered. This is called in a `requestAnimationFrame` callback.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A slider type of control for zooming.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* map.addControl(new ZoomSlider());
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ZoomSlider extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] Zoom slider options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
element: document.createElement('div'),
|
||||
render: options.render,
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {!Array<import("../events.js").EventsKey>}
|
||||
* @private
|
||||
*/
|
||||
this.dragListenerKeys_ = [];
|
||||
|
||||
/**
|
||||
* Will hold the current resolution of the view.
|
||||
*
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.currentResolution_ = undefined;
|
||||
|
||||
/**
|
||||
* The direction of the slider. Will be determined from actual display of the
|
||||
* container and defaults to Direction.VERTICAL.
|
||||
*
|
||||
* @type {Direction}
|
||||
* @private
|
||||
*/
|
||||
this.direction_ = Direction.VERTICAL;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.dragging_;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.heightLimit_ = 0;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.widthLimit_ = 0;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.startX_;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.startY_;
|
||||
|
||||
/**
|
||||
* The calculated thumb size (border box plus margins). Set when initSlider_
|
||||
* is called.
|
||||
* @type {import("../size.js").Size}
|
||||
* @private
|
||||
*/
|
||||
this.thumbSize_ = null;
|
||||
|
||||
/**
|
||||
* Whether the slider is initialized.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.sliderInitialized_ = false;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.duration_ = options.duration !== undefined ? options.duration : 200;
|
||||
|
||||
const className =
|
||||
options.className !== undefined ? options.className : 'ol-zoomslider';
|
||||
const thumbElement = document.createElement('button');
|
||||
thumbElement.setAttribute('type', 'button');
|
||||
thumbElement.className = className + '-thumb ' + CLASS_UNSELECTABLE;
|
||||
const containerElement = this.element;
|
||||
containerElement.className =
|
||||
className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
containerElement.appendChild(thumbElement);
|
||||
|
||||
containerElement.addEventListener(
|
||||
PointerEventType.POINTERDOWN,
|
||||
this.handleDraggerStart_.bind(this),
|
||||
false
|
||||
);
|
||||
containerElement.addEventListener(
|
||||
PointerEventType.POINTERMOVE,
|
||||
this.handleDraggerDrag_.bind(this),
|
||||
false
|
||||
);
|
||||
containerElement.addEventListener(
|
||||
PointerEventType.POINTERUP,
|
||||
this.handleDraggerEnd_.bind(this),
|
||||
false
|
||||
);
|
||||
|
||||
containerElement.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleContainerClick_.bind(this),
|
||||
false
|
||||
);
|
||||
thumbElement.addEventListener(EventType.CLICK, stopPropagation, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Pass `null` to just remove the control from the current map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {import("../PluggableMap.js").default|null} map Map.
|
||||
* @api
|
||||
*/
|
||||
setMap(map) {
|
||||
super.setMap(map);
|
||||
if (map) {
|
||||
map.render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the slider element. This will determine and set this controls
|
||||
* direction_ and also constrain the dragging of the thumb to always be within
|
||||
* the bounds of the container.
|
||||
*
|
||||
* @return {boolean} Initialization successful
|
||||
* @private
|
||||
*/
|
||||
initSlider_() {
|
||||
const container = this.element;
|
||||
let containerWidth = container.offsetWidth;
|
||||
let containerHeight = container.offsetHeight;
|
||||
if (containerWidth === 0 && containerHeight === 0) {
|
||||
return (this.sliderInitialized_ = false);
|
||||
}
|
||||
|
||||
const containerStyle = getComputedStyle(container);
|
||||
containerWidth -=
|
||||
parseFloat(containerStyle['paddingRight']) +
|
||||
parseFloat(containerStyle['paddingLeft']);
|
||||
containerHeight -=
|
||||
parseFloat(containerStyle['paddingTop']) +
|
||||
parseFloat(containerStyle['paddingBottom']);
|
||||
const thumb = /** @type {HTMLElement} */ (container.firstElementChild);
|
||||
const thumbStyle = getComputedStyle(thumb);
|
||||
const thumbWidth =
|
||||
thumb.offsetWidth +
|
||||
parseFloat(thumbStyle['marginRight']) +
|
||||
parseFloat(thumbStyle['marginLeft']);
|
||||
const thumbHeight =
|
||||
thumb.offsetHeight +
|
||||
parseFloat(thumbStyle['marginTop']) +
|
||||
parseFloat(thumbStyle['marginBottom']);
|
||||
this.thumbSize_ = [thumbWidth, thumbHeight];
|
||||
|
||||
if (containerWidth > containerHeight) {
|
||||
this.direction_ = Direction.HORIZONTAL;
|
||||
this.widthLimit_ = containerWidth - thumbWidth;
|
||||
} else {
|
||||
this.direction_ = Direction.VERTICAL;
|
||||
this.heightLimit_ = containerHeight - thumbHeight;
|
||||
}
|
||||
return (this.sliderInitialized_ = true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PointerEvent} event The browser event to handle.
|
||||
* @private
|
||||
*/
|
||||
handleContainerClick_(event) {
|
||||
const view = this.getMap().getView();
|
||||
|
||||
const relativePosition = this.getRelativePosition_(
|
||||
event.offsetX - this.thumbSize_[0] / 2,
|
||||
event.offsetY - this.thumbSize_[1] / 2
|
||||
);
|
||||
|
||||
const resolution = this.getResolutionForPosition_(relativePosition);
|
||||
const zoom = view.getConstrainedZoom(view.getZoomForResolution(resolution));
|
||||
|
||||
view.animateInternal({
|
||||
zoom: zoom,
|
||||
duration: this.duration_,
|
||||
easing: easeOut,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dragger start events.
|
||||
* @param {PointerEvent} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
handleDraggerStart_(event) {
|
||||
if (!this.dragging_ && event.target === this.element.firstElementChild) {
|
||||
const element = /** @type {HTMLElement} */ (
|
||||
this.element.firstElementChild
|
||||
);
|
||||
this.getMap().getView().beginInteraction();
|
||||
this.startX_ = event.clientX - parseFloat(element.style.left);
|
||||
this.startY_ = event.clientY - parseFloat(element.style.top);
|
||||
this.dragging_ = true;
|
||||
|
||||
if (this.dragListenerKeys_.length === 0) {
|
||||
const drag = this.handleDraggerDrag_;
|
||||
const end = this.handleDraggerEnd_;
|
||||
const doc = this.getMap().getOwnerDocument();
|
||||
this.dragListenerKeys_.push(
|
||||
listen(doc, PointerEventType.POINTERMOVE, drag, this),
|
||||
listen(doc, PointerEventType.POINTERUP, end, this)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dragger drag events.
|
||||
*
|
||||
* @param {PointerEvent} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
handleDraggerDrag_(event) {
|
||||
if (this.dragging_) {
|
||||
const deltaX = event.clientX - this.startX_;
|
||||
const deltaY = event.clientY - this.startY_;
|
||||
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
|
||||
this.currentResolution_ =
|
||||
this.getResolutionForPosition_(relativePosition);
|
||||
this.getMap().getView().setResolution(this.currentResolution_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dragger end events.
|
||||
* @param {PointerEvent} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
handleDraggerEnd_(event) {
|
||||
if (this.dragging_) {
|
||||
const view = this.getMap().getView();
|
||||
view.endInteraction();
|
||||
|
||||
this.dragging_ = false;
|
||||
this.startX_ = undefined;
|
||||
this.startY_ = undefined;
|
||||
this.dragListenerKeys_.forEach(unlistenByKey);
|
||||
this.dragListenerKeys_.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Positions the thumb inside its container according to the given resolution.
|
||||
*
|
||||
* @param {number} res The res.
|
||||
* @private
|
||||
*/
|
||||
setThumbPosition_(res) {
|
||||
const position = this.getPositionForResolution_(res);
|
||||
const thumb = /** @type {HTMLElement} */ (this.element.firstElementChild);
|
||||
|
||||
if (this.direction_ == Direction.HORIZONTAL) {
|
||||
thumb.style.left = this.widthLimit_ * position + 'px';
|
||||
} else {
|
||||
thumb.style.top = this.heightLimit_ * position + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the relative position of the thumb given x and y offsets. The
|
||||
* relative position scales from 0 to 1. The x and y offsets are assumed to be
|
||||
* in pixel units within the dragger limits.
|
||||
*
|
||||
* @param {number} x Pixel position relative to the left of the slider.
|
||||
* @param {number} y Pixel position relative to the top of the slider.
|
||||
* @return {number} The relative position of the thumb.
|
||||
* @private
|
||||
*/
|
||||
getRelativePosition_(x, y) {
|
||||
let amount;
|
||||
if (this.direction_ === Direction.HORIZONTAL) {
|
||||
amount = x / this.widthLimit_;
|
||||
} else {
|
||||
amount = y / this.heightLimit_;
|
||||
}
|
||||
return clamp(amount, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the corresponding resolution of the thumb given its relative
|
||||
* position (where 0 is the minimum and 1 is the maximum).
|
||||
*
|
||||
* @param {number} position The relative position of the thumb.
|
||||
* @return {number} The corresponding resolution.
|
||||
* @private
|
||||
*/
|
||||
getResolutionForPosition_(position) {
|
||||
const fn = this.getMap().getView().getResolutionForValueFunction();
|
||||
return fn(1 - position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the relative position of the slider for the given resolution. A
|
||||
* relative position of 0 corresponds to the minimum view resolution. A
|
||||
* relative position of 1 corresponds to the maximum view resolution.
|
||||
*
|
||||
* @param {number} res The resolution.
|
||||
* @return {number} The relative position value (between 0 and 1).
|
||||
* @private
|
||||
*/
|
||||
getPositionForResolution_(res) {
|
||||
const fn = this.getMap().getView().getValueForResolutionFunction();
|
||||
return clamp(1 - fn(res), 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the zoomslider element.
|
||||
* @param {import("../MapEvent.js").default} mapEvent Map event.
|
||||
* @override
|
||||
*/
|
||||
render(mapEvent) {
|
||||
if (!mapEvent.frameState) {
|
||||
return;
|
||||
}
|
||||
if (!this.sliderInitialized_ && !this.initSlider_()) {
|
||||
return;
|
||||
}
|
||||
const res = mapEvent.frameState.viewState.resolution;
|
||||
this.currentResolution_ = res;
|
||||
this.setThumbPosition_(res);
|
||||
}
|
||||
}
|
||||
|
||||
export default ZoomSlider;
|
||||
94
node_modules/ol/src/control/ZoomToExtent.js
generated
vendored
Normal file
94
node_modules/ol/src/control/ZoomToExtent.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @module ol/control/ZoomToExtent
|
||||
*/
|
||||
import Control from './Control.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {fromExtent as polygonFromExtent} from '../geom/Polygon.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-zoom-extent'] Class name.
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the control
|
||||
* to be rendered outside of the map's viewport.
|
||||
* @property {string|HTMLElement} [label='E'] Text label to use for the button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [tipLabel='Fit to extent'] Text label to use for the button tip.
|
||||
* @property {import("../extent.js").Extent} [extent] The extent to zoom to. If undefined the validity
|
||||
* extent of the view projection is used.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A button control which, when pressed, changes the map view to a specific
|
||||
* extent. To style this control use the css selector `.ol-zoom-extent`.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class ZoomToExtent extends Control {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
element: document.createElement('div'),
|
||||
target: options.target,
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {?import("../extent.js").Extent|null}
|
||||
* @protected
|
||||
*/
|
||||
this.extent = options.extent ? options.extent : null;
|
||||
|
||||
const className =
|
||||
options.className !== undefined ? options.className : 'ol-zoom-extent';
|
||||
|
||||
const label = options.label !== undefined ? options.label : 'E';
|
||||
const tipLabel =
|
||||
options.tipLabel !== undefined ? options.tipLabel : 'Fit to extent';
|
||||
const button = document.createElement('button');
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(
|
||||
typeof label === 'string' ? document.createTextNode(label) : label
|
||||
);
|
||||
|
||||
button.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleClick_.bind(this),
|
||||
false
|
||||
);
|
||||
|
||||
const cssClasses =
|
||||
className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
const element = this.element;
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event The event to handle
|
||||
* @private
|
||||
*/
|
||||
handleClick_(event) {
|
||||
event.preventDefault();
|
||||
this.handleZoomToExtent();
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
handleZoomToExtent() {
|
||||
const map = this.getMap();
|
||||
const view = map.getView();
|
||||
const extent = !this.extent
|
||||
? view.getProjection().getExtent()
|
||||
: this.extent;
|
||||
view.fitInternal(polygonFromExtent(extent));
|
||||
}
|
||||
}
|
||||
|
||||
export default ZoomToExtent;
|
||||
442
node_modules/ol/src/coordinate.js
generated
vendored
Normal file
442
node_modules/ol/src/coordinate.js
generated
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
/**
|
||||
* @module ol/coordinate
|
||||
*/
|
||||
import {getWidth} from './extent.js';
|
||||
import {modulo} from './math.js';
|
||||
import {padNumber} from './string.js';
|
||||
|
||||
/**
|
||||
* An array of numbers representing an xy coordinate. Example: `[16, 48]`.
|
||||
* @typedef {Array<number>} Coordinate
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* A function that takes a {@link module:ol/coordinate~Coordinate} and
|
||||
* transforms it into a `{string}`.
|
||||
*
|
||||
* @typedef {function((Coordinate|undefined)): string} CoordinateFormat
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add `delta` to `coordinate`. `coordinate` is modified in place and returned
|
||||
* by the function.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* import {add} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* add(coord, [-2, 4]);
|
||||
* // coord is now [5.85, 51.983333]
|
||||
*
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @param {Coordinate} delta Delta.
|
||||
* @return {Coordinate} The input coordinate adjusted by
|
||||
* the given delta.
|
||||
* @api
|
||||
*/
|
||||
export function add(coordinate, delta) {
|
||||
coordinate[0] += +delta[0];
|
||||
coordinate[1] += +delta[1];
|
||||
return coordinate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the point closest to the passed coordinate on the passed circle.
|
||||
*
|
||||
* @param {Coordinate} coordinate The coordinate.
|
||||
* @param {import("./geom/Circle.js").default} circle The circle.
|
||||
* @return {Coordinate} Closest point on the circumference.
|
||||
*/
|
||||
export function closestOnCircle(coordinate, circle) {
|
||||
const r = circle.getRadius();
|
||||
const center = circle.getCenter();
|
||||
const x0 = center[0];
|
||||
const y0 = center[1];
|
||||
const x1 = coordinate[0];
|
||||
const y1 = coordinate[1];
|
||||
|
||||
let dx = x1 - x0;
|
||||
const dy = y1 - y0;
|
||||
if (dx === 0 && dy === 0) {
|
||||
dx = 1;
|
||||
}
|
||||
const d = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
const x = x0 + (r * dx) / d;
|
||||
const y = y0 + (r * dy) / d;
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the point closest to the passed coordinate on the passed segment.
|
||||
* This is the foot of the perpendicular of the coordinate to the segment when
|
||||
* the foot is on the segment, or the closest segment coordinate when the foot
|
||||
* is outside the segment.
|
||||
*
|
||||
* @param {Coordinate} coordinate The coordinate.
|
||||
* @param {Array<Coordinate>} segment The two coordinates
|
||||
* of the segment.
|
||||
* @return {Coordinate} The foot of the perpendicular of
|
||||
* the coordinate to the segment.
|
||||
*/
|
||||
export function closestOnSegment(coordinate, segment) {
|
||||
const x0 = coordinate[0];
|
||||
const y0 = coordinate[1];
|
||||
const start = segment[0];
|
||||
const end = segment[1];
|
||||
const x1 = start[0];
|
||||
const y1 = start[1];
|
||||
const x2 = end[0];
|
||||
const y2 = end[1];
|
||||
const dx = x2 - x1;
|
||||
const dy = y2 - y1;
|
||||
const along =
|
||||
dx === 0 && dy === 0
|
||||
? 0
|
||||
: (dx * (x0 - x1) + dy * (y0 - y1)) / (dx * dx + dy * dy || 0);
|
||||
let x, y;
|
||||
if (along <= 0) {
|
||||
x = x1;
|
||||
y = y1;
|
||||
} else if (along >= 1) {
|
||||
x = x2;
|
||||
y = y2;
|
||||
} else {
|
||||
x = x1 + along * dx;
|
||||
y = y1 + along * dy;
|
||||
}
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link module:ol/coordinate~CoordinateFormat} function that can be
|
||||
* used to format
|
||||
* a {Coordinate} to a string.
|
||||
*
|
||||
* Example without specifying the fractional digits:
|
||||
*
|
||||
* import {createStringXY} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var stringifyFunc = createStringXY();
|
||||
* var out = stringifyFunc(coord);
|
||||
* // out is now '8, 48'
|
||||
*
|
||||
* Example with explicitly specifying 2 fractional digits:
|
||||
*
|
||||
* import {createStringXY} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var stringifyFunc = createStringXY(2);
|
||||
* var out = stringifyFunc(coord);
|
||||
* // out is now '7.85, 47.98'
|
||||
*
|
||||
* @param {number} [opt_fractionDigits] The number of digits to include
|
||||
* after the decimal point. Default is `0`.
|
||||
* @return {CoordinateFormat} Coordinate format.
|
||||
* @api
|
||||
*/
|
||||
export function createStringXY(opt_fractionDigits) {
|
||||
return (
|
||||
/**
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @return {string} String XY.
|
||||
*/
|
||||
function (coordinate) {
|
||||
return toStringXY(coordinate, opt_fractionDigits);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} hemispheres Hemispheres.
|
||||
* @param {number} degrees Degrees.
|
||||
* @param {number} [opt_fractionDigits] The number of digits to include
|
||||
* after the decimal point. Default is `0`.
|
||||
* @return {string} String.
|
||||
*/
|
||||
export function degreesToStringHDMS(hemispheres, degrees, opt_fractionDigits) {
|
||||
const normalizedDegrees = modulo(degrees + 180, 360) - 180;
|
||||
const x = Math.abs(3600 * normalizedDegrees);
|
||||
const dflPrecision = opt_fractionDigits || 0;
|
||||
const precision = Math.pow(10, dflPrecision);
|
||||
|
||||
let deg = Math.floor(x / 3600);
|
||||
let min = Math.floor((x - deg * 3600) / 60);
|
||||
let sec = x - deg * 3600 - min * 60;
|
||||
sec = Math.ceil(sec * precision) / precision;
|
||||
|
||||
if (sec >= 60) {
|
||||
sec = 0;
|
||||
min += 1;
|
||||
}
|
||||
|
||||
if (min >= 60) {
|
||||
min = 0;
|
||||
deg += 1;
|
||||
}
|
||||
|
||||
return (
|
||||
deg +
|
||||
'\u00b0 ' +
|
||||
padNumber(min, 2) +
|
||||
'\u2032 ' +
|
||||
padNumber(sec, 2, dflPrecision) +
|
||||
'\u2033' +
|
||||
(normalizedDegrees == 0
|
||||
? ''
|
||||
: ' ' + hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the given {@link module:ol/coordinate~Coordinate} to a string
|
||||
* using the given string template. The strings `{x}` and `{y}` in the template
|
||||
* will be replaced with the first and second coordinate values respectively.
|
||||
*
|
||||
* Example without specifying the fractional digits:
|
||||
*
|
||||
* import {format} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var template = 'Coordinate is ({x}|{y}).';
|
||||
* var out = format(coord, template);
|
||||
* // out is now 'Coordinate is (8|48).'
|
||||
*
|
||||
* Example explicitly specifying the fractional digits:
|
||||
*
|
||||
* import {format} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var template = 'Coordinate is ({x}|{y}).';
|
||||
* var out = format(coord, template, 2);
|
||||
* // out is now 'Coordinate is (7.85|47.98).'
|
||||
*
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @param {string} template A template string with `{x}` and `{y}` placeholders
|
||||
* that will be replaced by first and second coordinate values.
|
||||
* @param {number} [opt_fractionDigits] The number of digits to include
|
||||
* after the decimal point. Default is `0`.
|
||||
* @return {string} Formatted coordinate.
|
||||
* @api
|
||||
*/
|
||||
export function format(coordinate, template, opt_fractionDigits) {
|
||||
if (coordinate) {
|
||||
return template
|
||||
.replace('{x}', coordinate[0].toFixed(opt_fractionDigits))
|
||||
.replace('{y}', coordinate[1].toFixed(opt_fractionDigits));
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Coordinate} coordinate1 First coordinate.
|
||||
* @param {Coordinate} coordinate2 Second coordinate.
|
||||
* @return {boolean} The two coordinates are equal.
|
||||
*/
|
||||
export function equals(coordinate1, coordinate2) {
|
||||
let equals = true;
|
||||
for (let i = coordinate1.length - 1; i >= 0; --i) {
|
||||
if (coordinate1[i] != coordinate2[i]) {
|
||||
equals = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return equals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate `coordinate` by `angle`. `coordinate` is modified in place and
|
||||
* returned by the function.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* import {rotate} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var rotateRadians = Math.PI / 2; // 90 degrees
|
||||
* rotate(coord, rotateRadians);
|
||||
* // coord is now [-47.983333, 7.85]
|
||||
*
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @param {number} angle Angle in radian.
|
||||
* @return {Coordinate} Coordinate.
|
||||
* @api
|
||||
*/
|
||||
export function rotate(coordinate, angle) {
|
||||
const cosAngle = Math.cos(angle);
|
||||
const sinAngle = Math.sin(angle);
|
||||
const x = coordinate[0] * cosAngle - coordinate[1] * sinAngle;
|
||||
const y = coordinate[1] * cosAngle + coordinate[0] * sinAngle;
|
||||
coordinate[0] = x;
|
||||
coordinate[1] = y;
|
||||
return coordinate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale `coordinate` by `scale`. `coordinate` is modified in place and returned
|
||||
* by the function.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* import {scale as scaleCoordinate} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var scale = 1.2;
|
||||
* scaleCoordinate(coord, scale);
|
||||
* // coord is now [9.42, 57.5799996]
|
||||
*
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @param {number} scale Scale factor.
|
||||
* @return {Coordinate} Coordinate.
|
||||
*/
|
||||
export function scale(coordinate, scale) {
|
||||
coordinate[0] *= scale;
|
||||
coordinate[1] *= scale;
|
||||
return coordinate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Coordinate} coord1 First coordinate.
|
||||
* @param {Coordinate} coord2 Second coordinate.
|
||||
* @return {number} Squared distance between coord1 and coord2.
|
||||
*/
|
||||
export function squaredDistance(coord1, coord2) {
|
||||
const dx = coord1[0] - coord2[0];
|
||||
const dy = coord1[1] - coord2[1];
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Coordinate} coord1 First coordinate.
|
||||
* @param {Coordinate} coord2 Second coordinate.
|
||||
* @return {number} Distance between coord1 and coord2.
|
||||
*/
|
||||
export function distance(coord1, coord2) {
|
||||
return Math.sqrt(squaredDistance(coord1, coord2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the squared distance from a coordinate to a line segment.
|
||||
*
|
||||
* @param {Coordinate} coordinate Coordinate of the point.
|
||||
* @param {Array<Coordinate>} segment Line segment (2
|
||||
* coordinates).
|
||||
* @return {number} Squared distance from the point to the line segment.
|
||||
*/
|
||||
export function squaredDistanceToSegment(coordinate, segment) {
|
||||
return squaredDistance(coordinate, closestOnSegment(coordinate, segment));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a geographic coordinate with the hemisphere, degrees, minutes, and
|
||||
* seconds.
|
||||
*
|
||||
* Example without specifying fractional digits:
|
||||
*
|
||||
* import {toStringHDMS} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var out = toStringHDMS(coord);
|
||||
* // out is now '47° 58′ 60″ N 7° 50′ 60″ E'
|
||||
*
|
||||
* Example explicitly specifying 1 fractional digit:
|
||||
*
|
||||
* import {toStringHDMS} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var out = toStringHDMS(coord, 1);
|
||||
* // out is now '47° 58′ 60.0″ N 7° 50′ 60.0″ E'
|
||||
*
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @param {number} [opt_fractionDigits] The number of digits to include
|
||||
* after the decimal point. Default is `0`.
|
||||
* @return {string} Hemisphere, degrees, minutes and seconds.
|
||||
* @api
|
||||
*/
|
||||
export function toStringHDMS(coordinate, opt_fractionDigits) {
|
||||
if (coordinate) {
|
||||
return (
|
||||
degreesToStringHDMS('NS', coordinate[1], opt_fractionDigits) +
|
||||
' ' +
|
||||
degreesToStringHDMS('EW', coordinate[0], opt_fractionDigits)
|
||||
);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a coordinate as a comma delimited string.
|
||||
*
|
||||
* Example without specifying fractional digits:
|
||||
*
|
||||
* import {toStringXY} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var out = toStringXY(coord);
|
||||
* // out is now '8, 48'
|
||||
*
|
||||
* Example explicitly specifying 1 fractional digit:
|
||||
*
|
||||
* import {toStringXY} from 'ol/coordinate';
|
||||
*
|
||||
* var coord = [7.85, 47.983333];
|
||||
* var out = toStringXY(coord, 1);
|
||||
* // out is now '7.8, 48.0'
|
||||
*
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @param {number} [opt_fractionDigits] The number of digits to include
|
||||
* after the decimal point. Default is `0`.
|
||||
* @return {string} XY.
|
||||
* @api
|
||||
*/
|
||||
export function toStringXY(coordinate, opt_fractionDigits) {
|
||||
return format(coordinate, '{x}, {y}', opt_fractionDigits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the provided coordinate in-place to be within the real world
|
||||
* extent. The lower projection extent boundary is inclusive, the upper one
|
||||
* exclusive.
|
||||
*
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @param {import("./proj/Projection.js").default} projection Projection.
|
||||
* @return {Coordinate} The coordinate within the real world extent.
|
||||
*/
|
||||
export function wrapX(coordinate, projection) {
|
||||
if (projection.canWrapX()) {
|
||||
const worldWidth = getWidth(projection.getExtent());
|
||||
const worldsAway = getWorldsAway(coordinate, projection, worldWidth);
|
||||
if (worldsAway) {
|
||||
coordinate[0] -= worldsAway * worldWidth;
|
||||
}
|
||||
}
|
||||
return coordinate;
|
||||
}
|
||||
/**
|
||||
* @param {Coordinate} coordinate Coordinate.
|
||||
* @param {import("./proj/Projection.js").default} projection Projection.
|
||||
* @param {number} [opt_sourceExtentWidth] Width of the source extent.
|
||||
* @return {number} Offset in world widths.
|
||||
*/
|
||||
export function getWorldsAway(coordinate, projection, opt_sourceExtentWidth) {
|
||||
const projectionExtent = projection.getExtent();
|
||||
let worldsAway = 0;
|
||||
if (
|
||||
projection.canWrapX() &&
|
||||
(coordinate[0] < projectionExtent[0] || coordinate[0] > projectionExtent[2])
|
||||
) {
|
||||
const sourceExtentWidth =
|
||||
opt_sourceExtentWidth || getWidth(projectionExtent);
|
||||
worldsAway = Math.floor(
|
||||
(coordinate[0] - projectionExtent[0]) / sourceExtentWidth
|
||||
);
|
||||
}
|
||||
return worldsAway;
|
||||
}
|
||||
116
node_modules/ol/src/css.js
generated
vendored
Normal file
116
node_modules/ol/src/css.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @module ol/css
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} FontParameters
|
||||
* @property {string} style Style.
|
||||
* @property {string} variant Variant.
|
||||
* @property {string} weight Weight.
|
||||
* @property {string} size Size.
|
||||
* @property {string} lineHeight LineHeight.
|
||||
* @property {string} family Family.
|
||||
* @property {Array<string>} families Families.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The CSS class for hidden feature.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
export const CLASS_HIDDEN = 'ol-hidden';
|
||||
|
||||
/**
|
||||
* The CSS class that we'll give the DOM elements to have them selectable.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
export const CLASS_SELECTABLE = 'ol-selectable';
|
||||
|
||||
/**
|
||||
* The CSS class that we'll give the DOM elements to have them unselectable.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
export const CLASS_UNSELECTABLE = 'ol-unselectable';
|
||||
|
||||
/**
|
||||
* The CSS class for unsupported feature.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
export const CLASS_UNSUPPORTED = 'ol-unsupported';
|
||||
|
||||
/**
|
||||
* The CSS class for controls.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
export const CLASS_CONTROL = 'ol-control';
|
||||
|
||||
/**
|
||||
* The CSS class that we'll give the DOM elements that are collapsed, i.e.
|
||||
* to those elements which usually can be expanded.
|
||||
*
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
export const CLASS_COLLAPSED = 'ol-collapsed';
|
||||
|
||||
/**
|
||||
* From https://stackoverflow.com/questions/10135697/regex-to-parse-any-css-font
|
||||
* @type {RegExp}
|
||||
*/
|
||||
const fontRegEx = new RegExp(
|
||||
[
|
||||
'^\\s*(?=(?:(?:[-a-z]+\\s*){0,2}(italic|oblique))?)',
|
||||
'(?=(?:(?:[-a-z]+\\s*){0,2}(small-caps))?)',
|
||||
'(?=(?:(?:[-a-z]+\\s*){0,2}(bold(?:er)?|lighter|[1-9]00 ))?)',
|
||||
'(?:(?:normal|\\1|\\2|\\3)\\s*){0,3}((?:xx?-)?',
|
||||
'(?:small|large)|medium|smaller|larger|[\\.\\d]+(?:\\%|in|[cem]m|ex|p[ctx]))',
|
||||
'(?:\\s*\\/\\s*(normal|[\\.\\d]+(?:\\%|in|[cem]m|ex|p[ctx])?))',
|
||||
'?\\s*([-,\\"\\\'\\sa-z]+?)\\s*$',
|
||||
].join(''),
|
||||
'i'
|
||||
);
|
||||
const fontRegExMatchIndex = [
|
||||
'style',
|
||||
'variant',
|
||||
'weight',
|
||||
'size',
|
||||
'lineHeight',
|
||||
'family',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the list of font families from a font spec. Note that this doesn't work
|
||||
* for font families that have commas in them.
|
||||
* @param {string} fontSpec The CSS font property.
|
||||
* @return {FontParameters|null} The font parameters (or null if the input spec is invalid).
|
||||
*/
|
||||
export const getFontParameters = function (fontSpec) {
|
||||
const match = fontSpec.match(fontRegEx);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
const style = /** @type {FontParameters} */ ({
|
||||
lineHeight: 'normal',
|
||||
size: '1.2em',
|
||||
style: 'normal',
|
||||
weight: 'normal',
|
||||
variant: 'normal',
|
||||
});
|
||||
for (let i = 0, ii = fontRegExMatchIndex.length; i < ii; ++i) {
|
||||
const value = match[i + 1];
|
||||
if (value !== undefined) {
|
||||
style[fontRegExMatchIndex[i]] = value;
|
||||
}
|
||||
}
|
||||
style.families = style.family.split(/,\s?/);
|
||||
return style;
|
||||
};
|
||||
154
node_modules/ol/src/dom.js
generated
vendored
Normal file
154
node_modules/ol/src/dom.js
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
import {WORKER_OFFSCREEN_CANVAS} from './has.js';
|
||||
|
||||
/**
|
||||
* @module ol/dom
|
||||
*/
|
||||
|
||||
//FIXME Move this function to the canvas module
|
||||
/**
|
||||
* Create an html canvas element and returns its 2d context.
|
||||
* @param {number} [opt_width] Canvas width.
|
||||
* @param {number} [opt_height] Canvas height.
|
||||
* @param {Array<HTMLCanvasElement>} [opt_canvasPool] Canvas pool to take existing canvas from.
|
||||
* @param {CanvasRenderingContext2DSettings} [opt_Context2DSettings] CanvasRenderingContext2DSettings
|
||||
* @return {CanvasRenderingContext2D} The context.
|
||||
*/
|
||||
export function createCanvasContext2D(
|
||||
opt_width,
|
||||
opt_height,
|
||||
opt_canvasPool,
|
||||
opt_Context2DSettings
|
||||
) {
|
||||
/** @type {HTMLCanvasElement|OffscreenCanvas} */
|
||||
let canvas;
|
||||
if (opt_canvasPool && opt_canvasPool.length) {
|
||||
canvas = opt_canvasPool.shift();
|
||||
} else if (WORKER_OFFSCREEN_CANVAS) {
|
||||
canvas = new OffscreenCanvas(opt_width || 300, opt_height || 300);
|
||||
} else {
|
||||
canvas = document.createElement('canvas');
|
||||
}
|
||||
if (opt_width) {
|
||||
canvas.width = opt_width;
|
||||
}
|
||||
if (opt_height) {
|
||||
canvas.height = opt_height;
|
||||
}
|
||||
//FIXME Allow OffscreenCanvasRenderingContext2D as return type
|
||||
return /** @type {CanvasRenderingContext2D} */ (
|
||||
canvas.getContext('2d', opt_Context2DSettings)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases canvas memory to avoid exceeding memory limits in Safari.
|
||||
* See https://pqina.nl/blog/total-canvas-memory-use-exceeds-the-maximum-limit/
|
||||
* @param {CanvasRenderingContext2D} context Context.
|
||||
*/
|
||||
export function releaseCanvas(context) {
|
||||
const canvas = context.canvas;
|
||||
canvas.width = 1;
|
||||
canvas.height = 1;
|
||||
context.clearRect(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current computed width for the given element including margin,
|
||||
* padding and border.
|
||||
* Equivalent to jQuery's `$(el).outerWidth(true)`.
|
||||
* @param {!HTMLElement} element Element.
|
||||
* @return {number} The width.
|
||||
*/
|
||||
export function outerWidth(element) {
|
||||
let width = element.offsetWidth;
|
||||
const style = getComputedStyle(element);
|
||||
width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current computed height for the given element including margin,
|
||||
* padding and border.
|
||||
* Equivalent to jQuery's `$(el).outerHeight(true)`.
|
||||
* @param {!HTMLElement} element Element.
|
||||
* @return {number} The height.
|
||||
*/
|
||||
export function outerHeight(element) {
|
||||
let height = element.offsetHeight;
|
||||
const style = getComputedStyle(element);
|
||||
height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} newNode Node to replace old node
|
||||
* @param {Node} oldNode The node to be replaced
|
||||
*/
|
||||
export function replaceNode(newNode, oldNode) {
|
||||
const parent = oldNode.parentNode;
|
||||
if (parent) {
|
||||
parent.replaceChild(newNode, oldNode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node The node to remove.
|
||||
* @return {Node|null} The node that was removed or null.
|
||||
*/
|
||||
export function removeNode(node) {
|
||||
return node && node.parentNode ? node.parentNode.removeChild(node) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node The node to remove the children from.
|
||||
*/
|
||||
export function removeChildren(node) {
|
||||
while (node.lastChild) {
|
||||
node.removeChild(node.lastChild);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the children of a parent node so they match the
|
||||
* provided list of children. This function aims to efficiently
|
||||
* remove, add, and reorder child nodes while maintaining a simple
|
||||
* implementation (it is not guaranteed to minimize DOM operations).
|
||||
* @param {Node} node The parent node whose children need reworking.
|
||||
* @param {Array<Node>} children The desired children.
|
||||
*/
|
||||
export function replaceChildren(node, children) {
|
||||
const oldChildren = node.childNodes;
|
||||
|
||||
for (let i = 0; true; ++i) {
|
||||
const oldChild = oldChildren[i];
|
||||
const newChild = children[i];
|
||||
|
||||
// check if our work is done
|
||||
if (!oldChild && !newChild) {
|
||||
break;
|
||||
}
|
||||
|
||||
// check if children match
|
||||
if (oldChild === newChild) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if a new child needs to be added
|
||||
if (!oldChild) {
|
||||
node.appendChild(newChild);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if an old child needs to be removed
|
||||
if (!newChild) {
|
||||
node.removeChild(oldChild);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// reorder
|
||||
node.insertBefore(newChild, oldChild);
|
||||
}
|
||||
}
|
||||
59
node_modules/ol/src/easing.js
generated
vendored
Normal file
59
node_modules/ol/src/easing.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @module ol/easing
|
||||
*/
|
||||
|
||||
/**
|
||||
* Start slow and speed up.
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
export function easeIn(t) {
|
||||
return Math.pow(t, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start fast and slow down.
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
export function easeOut(t) {
|
||||
return 1 - easeIn(1 - t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start slow, speed up, and then slow down again.
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
export function inAndOut(t) {
|
||||
return 3 * t * t - 2 * t * t * t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maintain a constant speed over time.
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
export function linear(t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start slow, speed up, and at the very end slow down again. This has the
|
||||
* same general behavior as {@link module:ol/easing.inAndOut}, but the final
|
||||
* slowdown is delayed.
|
||||
* @param {number} t Input between 0 and 1.
|
||||
* @return {number} Output between 0 and 1.
|
||||
* @api
|
||||
*/
|
||||
export function upAndDown(t) {
|
||||
if (t < 0.5) {
|
||||
return inAndOut(2 * t);
|
||||
} else {
|
||||
return 1 - inAndOut(2 * (t - 0.5));
|
||||
}
|
||||
}
|
||||
105
node_modules/ol/src/events.js
generated
vendored
Normal file
105
node_modules/ol/src/events.js
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @module ol/events
|
||||
*/
|
||||
import {clear} from './obj.js';
|
||||
|
||||
/**
|
||||
* Key to use with {@link module:ol/Observable.unByKey}.
|
||||
* @typedef {Object} EventsKey
|
||||
* @property {ListenerFunction} listener Listener.
|
||||
* @property {import("./events/Target.js").EventTargetLike} target Target.
|
||||
* @property {string} type Type.
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* Listener function. This function is called with an event object as argument.
|
||||
* When the function returns `false`, event propagation will stop.
|
||||
*
|
||||
* @typedef {function((Event|import("./events/Event.js").default)): (void|boolean)} ListenerFunction
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ListenerObject
|
||||
* @property {ListenerFunction} handleEvent HandleEvent listener function.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {ListenerFunction|ListenerObject} Listener
|
||||
*/
|
||||
|
||||
/**
|
||||
* Registers an event listener on an event target. Inspired by
|
||||
* https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html
|
||||
*
|
||||
* This function efficiently binds a `listener` to a `this` object, and returns
|
||||
* a key for use with {@link module:ol/events.unlistenByKey}.
|
||||
*
|
||||
* @param {import("./events/Target.js").EventTargetLike} target Event target.
|
||||
* @param {string} type Event type.
|
||||
* @param {ListenerFunction} listener Listener.
|
||||
* @param {Object} [opt_this] Object referenced by the `this` keyword in the
|
||||
* listener. Default is the `target`.
|
||||
* @param {boolean} [opt_once] If true, add the listener as one-off listener.
|
||||
* @return {EventsKey} Unique key for the listener.
|
||||
*/
|
||||
export function listen(target, type, listener, opt_this, opt_once) {
|
||||
if (opt_this && opt_this !== target) {
|
||||
listener = listener.bind(opt_this);
|
||||
}
|
||||
if (opt_once) {
|
||||
const originalListener = listener;
|
||||
listener = function () {
|
||||
target.removeEventListener(type, listener);
|
||||
originalListener.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
const eventsKey = {
|
||||
target: target,
|
||||
type: type,
|
||||
listener: listener,
|
||||
};
|
||||
target.addEventListener(type, listener);
|
||||
return eventsKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a one-off event listener on an event target. Inspired by
|
||||
* https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html
|
||||
*
|
||||
* This function efficiently binds a `listener` as self-unregistering listener
|
||||
* to a `this` object, and returns a key for use with
|
||||
* {@link module:ol/events.unlistenByKey} in case the listener needs to be
|
||||
* unregistered before it is called.
|
||||
*
|
||||
* When {@link module:ol/events.listen} is called with the same arguments after this
|
||||
* function, the self-unregistering listener will be turned into a permanent
|
||||
* listener.
|
||||
*
|
||||
* @param {import("./events/Target.js").EventTargetLike} target Event target.
|
||||
* @param {string} type Event type.
|
||||
* @param {ListenerFunction} listener Listener.
|
||||
* @param {Object} [opt_this] Object referenced by the `this` keyword in the
|
||||
* listener. Default is the `target`.
|
||||
* @return {EventsKey} Key for unlistenByKey.
|
||||
*/
|
||||
export function listenOnce(target, type, listener, opt_this) {
|
||||
return listen(target, type, listener, opt_this, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters event listeners on an event target. Inspired by
|
||||
* https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html
|
||||
*
|
||||
* The argument passed to this function is the key returned from
|
||||
* {@link module:ol/events.listen} or {@link module:ol/events.listenOnce}.
|
||||
*
|
||||
* @param {EventsKey} key The key.
|
||||
*/
|
||||
export function unlistenByKey(key) {
|
||||
if (key && key.target) {
|
||||
key.target.removeEventListener(key.type, key.listener);
|
||||
clear(key);
|
||||
}
|
||||
}
|
||||
77
node_modules/ol/src/events/Event.js
generated
vendored
Normal file
77
node_modules/ol/src/events/Event.js
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @module ol/events/Event
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Stripped down implementation of the W3C DOM Level 2 Event interface.
|
||||
* See https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface.
|
||||
*
|
||||
* This implementation only provides `type` and `target` properties, and
|
||||
* `stopPropagation` and `preventDefault` methods. It is meant as base class
|
||||
* for higher level events defined in the library, and works with
|
||||
* {@link module:ol/events/Target~Target}.
|
||||
*/
|
||||
class BaseEvent {
|
||||
/**
|
||||
* @param {string} type Type.
|
||||
*/
|
||||
constructor(type) {
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.propagationStopped;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.defaultPrevented;
|
||||
|
||||
/**
|
||||
* The event type.
|
||||
* @type {string}
|
||||
* @api
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* The event target.
|
||||
* @type {Object}
|
||||
* @api
|
||||
*/
|
||||
this.target = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent default. This means that no emulated `click`, `singleclick` or `doubleclick` events
|
||||
* will be fired.
|
||||
* @api
|
||||
*/
|
||||
preventDefault() {
|
||||
this.defaultPrevented = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop event propagation.
|
||||
* @api
|
||||
*/
|
||||
stopPropagation() {
|
||||
this.propagationStopped = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event|import("./Event.js").default} evt Event
|
||||
*/
|
||||
export function stopPropagation(evt) {
|
||||
evt.stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event|import("./Event.js").default} evt Event
|
||||
*/
|
||||
export function preventDefault(evt) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
|
||||
export default BaseEvent;
|
||||
39
node_modules/ol/src/events/EventType.js
generated
vendored
Normal file
39
node_modules/ol/src/events/EventType.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @module ol/events/EventType
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
* @const
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* Generic change event. Triggered when the revision counter is increased.
|
||||
* @event module:ol/events/Event~BaseEvent#change
|
||||
* @api
|
||||
*/
|
||||
CHANGE: 'change',
|
||||
|
||||
/**
|
||||
* Generic error event. Triggered when an error occurs.
|
||||
* @event module:ol/events/Event~BaseEvent#error
|
||||
* @api
|
||||
*/
|
||||
ERROR: 'error',
|
||||
|
||||
BLUR: 'blur',
|
||||
CLEAR: 'clear',
|
||||
CONTEXTMENU: 'contextmenu',
|
||||
CLICK: 'click',
|
||||
DBLCLICK: 'dblclick',
|
||||
DRAGENTER: 'dragenter',
|
||||
DRAGOVER: 'dragover',
|
||||
DROP: 'drop',
|
||||
FOCUS: 'focus',
|
||||
KEYDOWN: 'keydown',
|
||||
KEYPRESS: 'keypress',
|
||||
LOAD: 'load',
|
||||
RESIZE: 'resize',
|
||||
TOUCHMOVE: 'touchmove',
|
||||
WHEEL: 'wheel',
|
||||
};
|
||||
14
node_modules/ol/src/events/KeyCode.js
generated
vendored
Normal file
14
node_modules/ol/src/events/KeyCode.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @module ol/events/KeyCode
|
||||
*/
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
* @const
|
||||
*/
|
||||
export default {
|
||||
LEFT: 37,
|
||||
UP: 38,
|
||||
RIGHT: 39,
|
||||
DOWN: 40,
|
||||
};
|
||||
188
node_modules/ol/src/events/Target.js
generated
vendored
Normal file
188
node_modules/ol/src/events/Target.js
generated
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* @module ol/events/Target
|
||||
*/
|
||||
import Disposable from '../Disposable.js';
|
||||
import Event from './Event.js';
|
||||
import {VOID} from '../functions.js';
|
||||
import {clear} from '../obj.js';
|
||||
|
||||
/**
|
||||
* @typedef {EventTarget|Target} EventTargetLike
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A simplified implementation of the W3C DOM Level 2 EventTarget interface.
|
||||
* See https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget.
|
||||
*
|
||||
* There are two important simplifications compared to the specification:
|
||||
*
|
||||
* 1. The handling of `useCapture` in `addEventListener` and
|
||||
* `removeEventListener`. There is no real capture model.
|
||||
* 2. The handling of `stopPropagation` and `preventDefault` on `dispatchEvent`.
|
||||
* There is no event target hierarchy. When a listener calls
|
||||
* `stopPropagation` or `preventDefault` on an event object, it means that no
|
||||
* more listeners after this one will be called. Same as when the listener
|
||||
* returns false.
|
||||
*/
|
||||
class Target extends Disposable {
|
||||
/**
|
||||
* @param {*} [opt_target] Default event target for dispatched events.
|
||||
*/
|
||||
constructor(opt_target) {
|
||||
super();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {*}
|
||||
*/
|
||||
this.eventTarget_ = opt_target;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object<string, number>}
|
||||
*/
|
||||
this.pendingRemovals_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object<string, number>}
|
||||
*/
|
||||
this.dispatching_ = null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object<string, Array<import("../events.js").Listener>>}
|
||||
*/
|
||||
this.listeners_ = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} type Type.
|
||||
* @param {import("../events.js").Listener} listener Listener.
|
||||
*/
|
||||
addEventListener(type, listener) {
|
||||
if (!type || !listener) {
|
||||
return;
|
||||
}
|
||||
const listeners = this.listeners_ || (this.listeners_ = {});
|
||||
const listenersForType = listeners[type] || (listeners[type] = []);
|
||||
if (listenersForType.indexOf(listener) === -1) {
|
||||
listenersForType.push(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an event and calls all listeners listening for events
|
||||
* of this type. The event parameter can either be a string or an
|
||||
* Object with a `type` property.
|
||||
*
|
||||
* @param {import("./Event.js").default|string} event Event object.
|
||||
* @return {boolean|undefined} `false` if anyone called preventDefault on the
|
||||
* event object or if any of the listeners returned false.
|
||||
* @api
|
||||
*/
|
||||
dispatchEvent(event) {
|
||||
const isString = typeof event === 'string';
|
||||
const type = isString ? event : event.type;
|
||||
const listeners = this.listeners_ && this.listeners_[type];
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
|
||||
const evt = isString ? new Event(event) : /** @type {Event} */ (event);
|
||||
if (!evt.target) {
|
||||
evt.target = this.eventTarget_ || this;
|
||||
}
|
||||
const dispatching = this.dispatching_ || (this.dispatching_ = {});
|
||||
const pendingRemovals =
|
||||
this.pendingRemovals_ || (this.pendingRemovals_ = {});
|
||||
if (!(type in dispatching)) {
|
||||
dispatching[type] = 0;
|
||||
pendingRemovals[type] = 0;
|
||||
}
|
||||
++dispatching[type];
|
||||
let propagate;
|
||||
for (let i = 0, ii = listeners.length; i < ii; ++i) {
|
||||
if ('handleEvent' in listeners[i]) {
|
||||
propagate = /** @type {import("../events.js").ListenerObject} */ (
|
||||
listeners[i]
|
||||
).handleEvent(evt);
|
||||
} else {
|
||||
propagate = /** @type {import("../events.js").ListenerFunction} */ (
|
||||
listeners[i]
|
||||
).call(this, evt);
|
||||
}
|
||||
if (propagate === false || evt.propagationStopped) {
|
||||
propagate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (--dispatching[type] === 0) {
|
||||
let pr = pendingRemovals[type];
|
||||
delete pendingRemovals[type];
|
||||
while (pr--) {
|
||||
this.removeEventListener(type, VOID);
|
||||
}
|
||||
delete dispatching[type];
|
||||
}
|
||||
return propagate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up.
|
||||
*/
|
||||
disposeInternal() {
|
||||
this.listeners_ && clear(this.listeners_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the listeners for a specified event type. Listeners are returned in the
|
||||
* order that they will be called in.
|
||||
*
|
||||
* @param {string} type Type.
|
||||
* @return {Array<import("../events.js").Listener>|undefined} Listeners.
|
||||
*/
|
||||
getListeners(type) {
|
||||
return (this.listeners_ && this.listeners_[type]) || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} [opt_type] Type. If not provided,
|
||||
* `true` will be returned if this event target has any listeners.
|
||||
* @return {boolean} Has listeners.
|
||||
*/
|
||||
hasListener(opt_type) {
|
||||
if (!this.listeners_) {
|
||||
return false;
|
||||
}
|
||||
return opt_type
|
||||
? opt_type in this.listeners_
|
||||
: Object.keys(this.listeners_).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} type Type.
|
||||
* @param {import("../events.js").Listener} listener Listener.
|
||||
*/
|
||||
removeEventListener(type, listener) {
|
||||
const listeners = this.listeners_ && this.listeners_[type];
|
||||
if (listeners) {
|
||||
const index = listeners.indexOf(listener);
|
||||
if (index !== -1) {
|
||||
if (this.pendingRemovals_ && type in this.pendingRemovals_) {
|
||||
// make listener a no-op, and remove later in #dispatchEvent()
|
||||
listeners[index] = VOID;
|
||||
++this.pendingRemovals_[type];
|
||||
} else {
|
||||
listeners.splice(index, 1);
|
||||
if (listeners.length === 0) {
|
||||
delete this.listeners_[type];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Target;
|
||||
328
node_modules/ol/src/events/condition.js
generated
vendored
Normal file
328
node_modules/ol/src/events/condition.js
generated
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
/**
|
||||
* @module ol/events/condition
|
||||
*/
|
||||
import MapBrowserEventType from '../MapBrowserEventType.js';
|
||||
import {FALSE, TRUE} from '../functions.js';
|
||||
import {MAC, WEBKIT} from '../has.js';
|
||||
import {assert} from '../asserts.js';
|
||||
|
||||
/**
|
||||
* A function that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a
|
||||
* `{boolean}`. If the condition is met, true should be returned.
|
||||
*
|
||||
* @typedef {function(this: ?, import("../MapBrowserEvent.js").default): boolean} Condition
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a condition function that passes when all provided conditions pass.
|
||||
* @param {...Condition} var_args Conditions to check.
|
||||
* @return {Condition} Condition function.
|
||||
*/
|
||||
export function all(var_args) {
|
||||
const conditions = arguments;
|
||||
/**
|
||||
* @param {import("../MapBrowserEvent.js").default} event Event.
|
||||
* @return {boolean} All conditions passed.
|
||||
*/
|
||||
return function (event) {
|
||||
let pass = true;
|
||||
for (let i = 0, ii = conditions.length; i < ii; ++i) {
|
||||
pass = pass && conditions[i](event);
|
||||
if (!pass) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pass;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `true` if only the alt-key is pressed, `false` otherwise (e.g. when
|
||||
* additionally the shift-key is pressed).
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if only the alt key is pressed.
|
||||
* @api
|
||||
*/
|
||||
export const altKeyOnly = function (mapBrowserEvent) {
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (
|
||||
mapBrowserEvent.originalEvent
|
||||
);
|
||||
return (
|
||||
originalEvent.altKey &&
|
||||
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
|
||||
!originalEvent.shiftKey
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if only the alt-key and shift-key is pressed, `false` otherwise
|
||||
* (e.g. when additionally the platform-modifier-key is pressed).
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if only the alt and shift keys are pressed.
|
||||
* @api
|
||||
*/
|
||||
export const altShiftKeysOnly = function (mapBrowserEvent) {
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (
|
||||
mapBrowserEvent.originalEvent
|
||||
);
|
||||
return (
|
||||
originalEvent.altKey &&
|
||||
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
|
||||
originalEvent.shiftKey
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the map has the focus. This condition requires a map target
|
||||
* element with a `tabindex` attribute, e.g. `<div id="map" tabindex="1">`.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} event Map browser event.
|
||||
* @return {boolean} The map has the focus.
|
||||
* @api
|
||||
*/
|
||||
export const focus = function (event) {
|
||||
const targetElement = event.map.getTargetElement();
|
||||
const activeElement = event.map.getOwnerDocument().activeElement;
|
||||
return targetElement.contains(activeElement);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the map has the focus or no 'tabindex' attribute set.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} event Map browser event.
|
||||
* @return {boolean} The map container has the focus or no 'tabindex' attribute.
|
||||
*/
|
||||
export const focusWithTabindex = function (event) {
|
||||
return event.map.getTargetElement().hasAttribute('tabindex')
|
||||
? focus(event)
|
||||
: true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return always true.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True.
|
||||
* @api
|
||||
*/
|
||||
export const always = TRUE;
|
||||
|
||||
/**
|
||||
* Return `true` if the event is a `click` event, `false` otherwise.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event is a map `click` event.
|
||||
* @api
|
||||
*/
|
||||
export const click = function (mapBrowserEvent) {
|
||||
return mapBrowserEvent.type == MapBrowserEventType.CLICK;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the event has an "action"-producing mouse button.
|
||||
*
|
||||
* By definition, this includes left-click on windows/linux, and left-click
|
||||
* without the ctrl key on Macs.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} The result.
|
||||
*/
|
||||
export const mouseActionButton = function (mapBrowserEvent) {
|
||||
const originalEvent = /** @type {MouseEvent} */ (
|
||||
mapBrowserEvent.originalEvent
|
||||
);
|
||||
return originalEvent.button == 0 && !(WEBKIT && MAC && originalEvent.ctrlKey);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return always false.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} False.
|
||||
* @api
|
||||
*/
|
||||
export const never = FALSE;
|
||||
|
||||
/**
|
||||
* Return `true` if the browser event is a `pointermove` event, `false`
|
||||
* otherwise.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the browser event is a `pointermove` event.
|
||||
* @api
|
||||
*/
|
||||
export const pointerMove = function (mapBrowserEvent) {
|
||||
return mapBrowserEvent.type == 'pointermove';
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the event is a map `singleclick` event, `false` otherwise.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event is a map `singleclick` event.
|
||||
* @api
|
||||
*/
|
||||
export const singleClick = function (mapBrowserEvent) {
|
||||
return mapBrowserEvent.type == MapBrowserEventType.SINGLECLICK;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the event is a map `dblclick` event, `false` otherwise.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event is a map `dblclick` event.
|
||||
* @api
|
||||
*/
|
||||
export const doubleClick = function (mapBrowserEvent) {
|
||||
return mapBrowserEvent.type == MapBrowserEventType.DBLCLICK;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if no modifier key (alt-, shift- or platform-modifier-key) is
|
||||
* pressed.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True only if there no modifier keys are pressed.
|
||||
* @api
|
||||
*/
|
||||
export const noModifierKeys = function (mapBrowserEvent) {
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (
|
||||
mapBrowserEvent.originalEvent
|
||||
);
|
||||
return (
|
||||
!originalEvent.altKey &&
|
||||
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
|
||||
!originalEvent.shiftKey
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if only the platform-modifier-key (the meta-key on Mac,
|
||||
* ctrl-key otherwise) is pressed, `false` otherwise (e.g. when additionally
|
||||
* the shift-key is pressed).
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if only the platform modifier key is pressed.
|
||||
* @api
|
||||
*/
|
||||
export const platformModifierKeyOnly = function (mapBrowserEvent) {
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (
|
||||
mapBrowserEvent.originalEvent
|
||||
);
|
||||
return (
|
||||
!originalEvent.altKey &&
|
||||
(MAC ? originalEvent.metaKey : originalEvent.ctrlKey) &&
|
||||
!originalEvent.shiftKey
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if only the shift-key is pressed, `false` otherwise (e.g. when
|
||||
* additionally the alt-key is pressed).
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if only the shift key is pressed.
|
||||
* @api
|
||||
*/
|
||||
export const shiftKeyOnly = function (mapBrowserEvent) {
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (
|
||||
mapBrowserEvent.originalEvent
|
||||
);
|
||||
return (
|
||||
!originalEvent.altKey &&
|
||||
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
|
||||
originalEvent.shiftKey
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the target element is not editable, i.e. not an `input`,
|
||||
* `select`, or `textarea` element and no `contenteditable` attribute is
|
||||
* set or inherited, `false` otherwise.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True only if the target element is not editable.
|
||||
* @api
|
||||
*/
|
||||
export const targetNotEditable = function (mapBrowserEvent) {
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (
|
||||
mapBrowserEvent.originalEvent
|
||||
);
|
||||
const tagName = /** @type {Element} */ (originalEvent.target).tagName;
|
||||
return (
|
||||
tagName !== 'INPUT' &&
|
||||
tagName !== 'SELECT' &&
|
||||
tagName !== 'TEXTAREA' &&
|
||||
// `isContentEditable` is only available on `HTMLElement`, but it may also be a
|
||||
// different type like `SVGElement`.
|
||||
// @ts-ignore
|
||||
!originalEvent.target.isContentEditable
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the event originates from a mouse device.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event originates from a mouse device.
|
||||
* @api
|
||||
*/
|
||||
export const mouseOnly = function (mapBrowserEvent) {
|
||||
const pointerEvent = /** @type {import("../MapBrowserEvent").default} */ (
|
||||
mapBrowserEvent
|
||||
).originalEvent;
|
||||
assert(pointerEvent !== undefined, 56); // mapBrowserEvent must originate from a pointer event
|
||||
// see https://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType
|
||||
return pointerEvent.pointerType == 'mouse';
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the event originates from a touchable device.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event originates from a touchable device.
|
||||
* @api
|
||||
*/
|
||||
export const touchOnly = function (mapBrowserEvent) {
|
||||
const pointerEvt = /** @type {import("../MapBrowserEvent").default} */ (
|
||||
mapBrowserEvent
|
||||
).originalEvent;
|
||||
assert(pointerEvt !== undefined, 56); // mapBrowserEvent must originate from a pointer event
|
||||
// see https://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType
|
||||
return pointerEvt.pointerType === 'touch';
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the event originates from a digital pen.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event originates from a digital pen.
|
||||
* @api
|
||||
*/
|
||||
export const penOnly = function (mapBrowserEvent) {
|
||||
const pointerEvt = /** @type {import("../MapBrowserEvent").default} */ (
|
||||
mapBrowserEvent
|
||||
).originalEvent;
|
||||
assert(pointerEvt !== undefined, 56); // mapBrowserEvent must originate from a pointer event
|
||||
// see https://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType
|
||||
return pointerEvt.pointerType === 'pen';
|
||||
};
|
||||
|
||||
/**
|
||||
* Return `true` if the event originates from a primary pointer in
|
||||
* contact with the surface or if the left mouse button is pressed.
|
||||
* See https://www.w3.org/TR/pointerevents/#button-states.
|
||||
*
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} True if the event originates from a primary pointer.
|
||||
* @api
|
||||
*/
|
||||
export const primaryAction = function (mapBrowserEvent) {
|
||||
const pointerEvent = /** @type {import("../MapBrowserEvent").default} */ (
|
||||
mapBrowserEvent
|
||||
).originalEvent;
|
||||
assert(pointerEvent !== undefined, 56); // mapBrowserEvent must originate from a pointer event
|
||||
return pointerEvent.isPrimary && pointerEvent.button === 0;
|
||||
};
|
||||
928
node_modules/ol/src/extent.js
generated
vendored
Normal file
928
node_modules/ol/src/extent.js
generated
vendored
Normal file
@@ -0,0 +1,928 @@
|
||||
/**
|
||||
* @module ol/extent
|
||||
*/
|
||||
import Relationship from './extent/Relationship.js';
|
||||
import {assert} from './asserts.js';
|
||||
|
||||
/**
|
||||
* An array of numbers representing an extent: `[minx, miny, maxx, maxy]`.
|
||||
* @typedef {Array<number>} Extent
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extent corner.
|
||||
* @typedef {'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'} Corner
|
||||
*/
|
||||
|
||||
/**
|
||||
* Build an extent that includes all given coordinates.
|
||||
*
|
||||
* @param {Array<import("./coordinate.js").Coordinate>} coordinates Coordinates.
|
||||
* @return {Extent} Bounding extent.
|
||||
* @api
|
||||
*/
|
||||
export function boundingExtent(coordinates) {
|
||||
const extent = createEmpty();
|
||||
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
extendCoordinate(extent, coordinates[i]);
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<number>} xs Xs.
|
||||
* @param {Array<number>} ys Ys.
|
||||
* @param {Extent} [opt_extent] Destination extent.
|
||||
* @private
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
function _boundingExtentXYs(xs, ys, opt_extent) {
|
||||
const minX = Math.min.apply(null, xs);
|
||||
const minY = Math.min.apply(null, ys);
|
||||
const maxX = Math.max.apply(null, xs);
|
||||
const maxY = Math.max.apply(null, ys);
|
||||
return createOrUpdate(minX, minY, maxX, maxY, opt_extent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return extent increased by the provided value.
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {number} value The amount by which the extent should be buffered.
|
||||
* @param {Extent} [opt_extent] Extent.
|
||||
* @return {Extent} Extent.
|
||||
* @api
|
||||
*/
|
||||
export function buffer(extent, value, opt_extent) {
|
||||
if (opt_extent) {
|
||||
opt_extent[0] = extent[0] - value;
|
||||
opt_extent[1] = extent[1] - value;
|
||||
opt_extent[2] = extent[2] + value;
|
||||
opt_extent[3] = extent[3] + value;
|
||||
return opt_extent;
|
||||
} else {
|
||||
return [
|
||||
extent[0] - value,
|
||||
extent[1] - value,
|
||||
extent[2] + value,
|
||||
extent[3] + value,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a clone of an extent.
|
||||
*
|
||||
* @param {Extent} extent Extent to clone.
|
||||
* @param {Extent} [opt_extent] Extent.
|
||||
* @return {Extent} The clone.
|
||||
*/
|
||||
export function clone(extent, opt_extent) {
|
||||
if (opt_extent) {
|
||||
opt_extent[0] = extent[0];
|
||||
opt_extent[1] = extent[1];
|
||||
opt_extent[2] = extent[2];
|
||||
opt_extent[3] = extent[3];
|
||||
return opt_extent;
|
||||
} else {
|
||||
return extent.slice();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @return {number} Closest squared distance.
|
||||
*/
|
||||
export function closestSquaredDistanceXY(extent, x, y) {
|
||||
let dx, dy;
|
||||
if (x < extent[0]) {
|
||||
dx = extent[0] - x;
|
||||
} else if (extent[2] < x) {
|
||||
dx = x - extent[2];
|
||||
} else {
|
||||
dx = 0;
|
||||
}
|
||||
if (y < extent[1]) {
|
||||
dy = extent[1] - y;
|
||||
} else if (extent[3] < y) {
|
||||
dy = y - extent[3];
|
||||
} else {
|
||||
dy = 0;
|
||||
}
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the passed coordinate is contained or on the edge of the extent.
|
||||
*
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {import("./coordinate.js").Coordinate} coordinate Coordinate.
|
||||
* @return {boolean} The coordinate is contained in the extent.
|
||||
* @api
|
||||
*/
|
||||
export function containsCoordinate(extent, coordinate) {
|
||||
return containsXY(extent, coordinate[0], coordinate[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if one extent contains another.
|
||||
*
|
||||
* An extent is deemed contained if it lies completely within the other extent,
|
||||
* including if they share one or more edges.
|
||||
*
|
||||
* @param {Extent} extent1 Extent 1.
|
||||
* @param {Extent} extent2 Extent 2.
|
||||
* @return {boolean} The second extent is contained by or on the edge of the
|
||||
* first.
|
||||
* @api
|
||||
*/
|
||||
export function containsExtent(extent1, extent2) {
|
||||
return (
|
||||
extent1[0] <= extent2[0] &&
|
||||
extent2[2] <= extent1[2] &&
|
||||
extent1[1] <= extent2[1] &&
|
||||
extent2[3] <= extent1[3]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the passed coordinate is contained or on the edge of the extent.
|
||||
*
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {number} x X coordinate.
|
||||
* @param {number} y Y coordinate.
|
||||
* @return {boolean} The x, y values are contained in the extent.
|
||||
* @api
|
||||
*/
|
||||
export function containsXY(extent, x, y) {
|
||||
return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationship between a coordinate and extent.
|
||||
* @param {Extent} extent The extent.
|
||||
* @param {import("./coordinate.js").Coordinate} coordinate The coordinate.
|
||||
* @return {import("./extent/Relationship.js").default} The relationship (bitwise compare with
|
||||
* import("./extent/Relationship.js").Relationship).
|
||||
*/
|
||||
export function coordinateRelationship(extent, coordinate) {
|
||||
const minX = extent[0];
|
||||
const minY = extent[1];
|
||||
const maxX = extent[2];
|
||||
const maxY = extent[3];
|
||||
const x = coordinate[0];
|
||||
const y = coordinate[1];
|
||||
let relationship = Relationship.UNKNOWN;
|
||||
if (x < minX) {
|
||||
relationship = relationship | Relationship.LEFT;
|
||||
} else if (x > maxX) {
|
||||
relationship = relationship | Relationship.RIGHT;
|
||||
}
|
||||
if (y < minY) {
|
||||
relationship = relationship | Relationship.BELOW;
|
||||
} else if (y > maxY) {
|
||||
relationship = relationship | Relationship.ABOVE;
|
||||
}
|
||||
if (relationship === Relationship.UNKNOWN) {
|
||||
relationship = Relationship.INTERSECTING;
|
||||
}
|
||||
return relationship;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty extent.
|
||||
* @return {Extent} Empty extent.
|
||||
* @api
|
||||
*/
|
||||
export function createEmpty() {
|
||||
return [Infinity, Infinity, -Infinity, -Infinity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new extent or update the provided extent.
|
||||
* @param {number} minX Minimum X.
|
||||
* @param {number} minY Minimum Y.
|
||||
* @param {number} maxX Maximum X.
|
||||
* @param {number} maxY Maximum Y.
|
||||
* @param {Extent} [opt_extent] Destination extent.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function createOrUpdate(minX, minY, maxX, maxY, opt_extent) {
|
||||
if (opt_extent) {
|
||||
opt_extent[0] = minX;
|
||||
opt_extent[1] = minY;
|
||||
opt_extent[2] = maxX;
|
||||
opt_extent[3] = maxY;
|
||||
return opt_extent;
|
||||
} else {
|
||||
return [minX, minY, maxX, maxY];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new empty extent or make the provided one empty.
|
||||
* @param {Extent} [opt_extent] Extent.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function createOrUpdateEmpty(opt_extent) {
|
||||
return createOrUpdate(Infinity, Infinity, -Infinity, -Infinity, opt_extent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./coordinate.js").Coordinate} coordinate Coordinate.
|
||||
* @param {Extent} [opt_extent] Extent.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function createOrUpdateFromCoordinate(coordinate, opt_extent) {
|
||||
const x = coordinate[0];
|
||||
const y = coordinate[1];
|
||||
return createOrUpdate(x, y, x, y, opt_extent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<import("./coordinate.js").Coordinate>} coordinates Coordinates.
|
||||
* @param {Extent} [opt_extent] Extent.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function createOrUpdateFromCoordinates(coordinates, opt_extent) {
|
||||
const extent = createOrUpdateEmpty(opt_extent);
|
||||
return extendCoordinates(extent, coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @param {Extent} [opt_extent] Extent.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function createOrUpdateFromFlatCoordinates(
|
||||
flatCoordinates,
|
||||
offset,
|
||||
end,
|
||||
stride,
|
||||
opt_extent
|
||||
) {
|
||||
const extent = createOrUpdateEmpty(opt_extent);
|
||||
return extendFlatCoordinates(extent, flatCoordinates, offset, end, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<Array<import("./coordinate.js").Coordinate>>} rings Rings.
|
||||
* @param {Extent} [opt_extent] Extent.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function createOrUpdateFromRings(rings, opt_extent) {
|
||||
const extent = createOrUpdateEmpty(opt_extent);
|
||||
return extendRings(extent, rings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two extents are equivalent.
|
||||
* @param {Extent} extent1 Extent 1.
|
||||
* @param {Extent} extent2 Extent 2.
|
||||
* @return {boolean} The two extents are equivalent.
|
||||
* @api
|
||||
*/
|
||||
export function equals(extent1, extent2) {
|
||||
return (
|
||||
extent1[0] == extent2[0] &&
|
||||
extent1[2] == extent2[2] &&
|
||||
extent1[1] == extent2[1] &&
|
||||
extent1[3] == extent2[3]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if two extents are approximately equivalent.
|
||||
* @param {Extent} extent1 Extent 1.
|
||||
* @param {Extent} extent2 Extent 2.
|
||||
* @param {number} tolerance Tolerance in extent coordinate units.
|
||||
* @return {boolean} The two extents differ by less than the tolerance.
|
||||
*/
|
||||
export function approximatelyEquals(extent1, extent2, tolerance) {
|
||||
return (
|
||||
Math.abs(extent1[0] - extent2[0]) < tolerance &&
|
||||
Math.abs(extent1[2] - extent2[2]) < tolerance &&
|
||||
Math.abs(extent1[1] - extent2[1]) < tolerance &&
|
||||
Math.abs(extent1[3] - extent2[3]) < tolerance
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify an extent to include another extent.
|
||||
* @param {Extent} extent1 The extent to be modified.
|
||||
* @param {Extent} extent2 The extent that will be included in the first.
|
||||
* @return {Extent} A reference to the first (extended) extent.
|
||||
* @api
|
||||
*/
|
||||
export function extend(extent1, extent2) {
|
||||
if (extent2[0] < extent1[0]) {
|
||||
extent1[0] = extent2[0];
|
||||
}
|
||||
if (extent2[2] > extent1[2]) {
|
||||
extent1[2] = extent2[2];
|
||||
}
|
||||
if (extent2[1] < extent1[1]) {
|
||||
extent1[1] = extent2[1];
|
||||
}
|
||||
if (extent2[3] > extent1[3]) {
|
||||
extent1[3] = extent2[3];
|
||||
}
|
||||
return extent1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {import("./coordinate.js").Coordinate} coordinate Coordinate.
|
||||
*/
|
||||
export function extendCoordinate(extent, coordinate) {
|
||||
if (coordinate[0] < extent[0]) {
|
||||
extent[0] = coordinate[0];
|
||||
}
|
||||
if (coordinate[0] > extent[2]) {
|
||||
extent[2] = coordinate[0];
|
||||
}
|
||||
if (coordinate[1] < extent[1]) {
|
||||
extent[1] = coordinate[1];
|
||||
}
|
||||
if (coordinate[1] > extent[3]) {
|
||||
extent[3] = coordinate[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {Array<import("./coordinate.js").Coordinate>} coordinates Coordinates.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function extendCoordinates(extent, coordinates) {
|
||||
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
extendCoordinate(extent, coordinates[i]);
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {Array<number>} flatCoordinates Flat coordinates.
|
||||
* @param {number} offset Offset.
|
||||
* @param {number} end End.
|
||||
* @param {number} stride Stride.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function extendFlatCoordinates(
|
||||
extent,
|
||||
flatCoordinates,
|
||||
offset,
|
||||
end,
|
||||
stride
|
||||
) {
|
||||
for (; offset < end; offset += stride) {
|
||||
extendXY(extent, flatCoordinates[offset], flatCoordinates[offset + 1]);
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {Array<Array<import("./coordinate.js").Coordinate>>} rings Rings.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function extendRings(extent, rings) {
|
||||
for (let i = 0, ii = rings.length; i < ii; ++i) {
|
||||
extendCoordinates(extent, rings[i]);
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
*/
|
||||
export function extendXY(extent, x, y) {
|
||||
extent[0] = Math.min(extent[0], x);
|
||||
extent[1] = Math.min(extent[1], y);
|
||||
extent[2] = Math.max(extent[2], x);
|
||||
extent[3] = Math.max(extent[3], y);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function calls `callback` for each corner of the extent. If the
|
||||
* callback returns a truthy value the function returns that value
|
||||
* immediately. Otherwise the function returns `false`.
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {function(import("./coordinate.js").Coordinate): S} callback Callback.
|
||||
* @return {S|boolean} Value.
|
||||
* @template S
|
||||
*/
|
||||
export function forEachCorner(extent, callback) {
|
||||
let val;
|
||||
val = callback(getBottomLeft(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback(getBottomRight(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback(getTopRight(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
val = callback(getTopLeft(extent));
|
||||
if (val) {
|
||||
return val;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {number} Area.
|
||||
* @api
|
||||
*/
|
||||
export function getArea(extent) {
|
||||
let area = 0;
|
||||
if (!isEmpty(extent)) {
|
||||
area = getWidth(extent) * getHeight(extent);
|
||||
}
|
||||
return area;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bottom left coordinate of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {import("./coordinate.js").Coordinate} Bottom left coordinate.
|
||||
* @api
|
||||
*/
|
||||
export function getBottomLeft(extent) {
|
||||
return [extent[0], extent[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bottom right coordinate of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {import("./coordinate.js").Coordinate} Bottom right coordinate.
|
||||
* @api
|
||||
*/
|
||||
export function getBottomRight(extent) {
|
||||
return [extent[2], extent[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the center coordinate of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {import("./coordinate.js").Coordinate} Center.
|
||||
* @api
|
||||
*/
|
||||
export function getCenter(extent) {
|
||||
return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a corner coordinate of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {Corner} corner Corner.
|
||||
* @return {import("./coordinate.js").Coordinate} Corner coordinate.
|
||||
*/
|
||||
export function getCorner(extent, corner) {
|
||||
let coordinate;
|
||||
if (corner === 'bottom-left') {
|
||||
coordinate = getBottomLeft(extent);
|
||||
} else if (corner === 'bottom-right') {
|
||||
coordinate = getBottomRight(extent);
|
||||
} else if (corner === 'top-left') {
|
||||
coordinate = getTopLeft(extent);
|
||||
} else if (corner === 'top-right') {
|
||||
coordinate = getTopRight(extent);
|
||||
} else {
|
||||
assert(false, 13); // Invalid corner
|
||||
}
|
||||
return coordinate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent1 Extent 1.
|
||||
* @param {Extent} extent2 Extent 2.
|
||||
* @return {number} Enlarged area.
|
||||
*/
|
||||
export function getEnlargedArea(extent1, extent2) {
|
||||
const minX = Math.min(extent1[0], extent2[0]);
|
||||
const minY = Math.min(extent1[1], extent2[1]);
|
||||
const maxX = Math.max(extent1[2], extent2[2]);
|
||||
const maxY = Math.max(extent1[3], extent2[3]);
|
||||
return (maxX - minX) * (maxY - minY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./coordinate.js").Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {import("./size.js").Size} size Size.
|
||||
* @param {Extent} [opt_extent] Destination extent.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function getForViewAndSize(
|
||||
center,
|
||||
resolution,
|
||||
rotation,
|
||||
size,
|
||||
opt_extent
|
||||
) {
|
||||
const [x0, y0, x1, y1, x2, y2, x3, y3] = getRotatedViewport(
|
||||
center,
|
||||
resolution,
|
||||
rotation,
|
||||
size
|
||||
);
|
||||
return createOrUpdate(
|
||||
Math.min(x0, x1, x2, x3),
|
||||
Math.min(y0, y1, y2, y3),
|
||||
Math.max(x0, x1, x2, x3),
|
||||
Math.max(y0, y1, y2, y3),
|
||||
opt_extent
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./coordinate.js").Coordinate} center Center.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {import("./size.js").Size} size Size.
|
||||
* @return {Array<number>} Linear ring representing the viewport.
|
||||
*/
|
||||
export function getRotatedViewport(center, resolution, rotation, size) {
|
||||
const dx = (resolution * size[0]) / 2;
|
||||
const dy = (resolution * size[1]) / 2;
|
||||
const cosRotation = Math.cos(rotation);
|
||||
const sinRotation = Math.sin(rotation);
|
||||
const xCos = dx * cosRotation;
|
||||
const xSin = dx * sinRotation;
|
||||
const yCos = dy * cosRotation;
|
||||
const ySin = dy * sinRotation;
|
||||
const x = center[0];
|
||||
const y = center[1];
|
||||
return [
|
||||
x - xCos + ySin,
|
||||
y - xSin - yCos,
|
||||
x - xCos - ySin,
|
||||
y - xSin + yCos,
|
||||
x + xCos - ySin,
|
||||
y + xSin + yCos,
|
||||
x + xCos + ySin,
|
||||
y + xSin - yCos,
|
||||
x - xCos + ySin,
|
||||
y - xSin - yCos,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {number} Height.
|
||||
* @api
|
||||
*/
|
||||
export function getHeight(extent) {
|
||||
return extent[3] - extent[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent1 Extent 1.
|
||||
* @param {Extent} extent2 Extent 2.
|
||||
* @return {number} Intersection area.
|
||||
*/
|
||||
export function getIntersectionArea(extent1, extent2) {
|
||||
const intersection = getIntersection(extent1, extent2);
|
||||
return getArea(intersection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the intersection of two extents.
|
||||
* @param {Extent} extent1 Extent 1.
|
||||
* @param {Extent} extent2 Extent 2.
|
||||
* @param {Extent} [opt_extent] Optional extent to populate with intersection.
|
||||
* @return {Extent} Intersecting extent.
|
||||
* @api
|
||||
*/
|
||||
export function getIntersection(extent1, extent2, opt_extent) {
|
||||
const intersection = opt_extent ? opt_extent : createEmpty();
|
||||
if (intersects(extent1, extent2)) {
|
||||
if (extent1[0] > extent2[0]) {
|
||||
intersection[0] = extent1[0];
|
||||
} else {
|
||||
intersection[0] = extent2[0];
|
||||
}
|
||||
if (extent1[1] > extent2[1]) {
|
||||
intersection[1] = extent1[1];
|
||||
} else {
|
||||
intersection[1] = extent2[1];
|
||||
}
|
||||
if (extent1[2] < extent2[2]) {
|
||||
intersection[2] = extent1[2];
|
||||
} else {
|
||||
intersection[2] = extent2[2];
|
||||
}
|
||||
if (extent1[3] < extent2[3]) {
|
||||
intersection[3] = extent1[3];
|
||||
} else {
|
||||
intersection[3] = extent2[3];
|
||||
}
|
||||
} else {
|
||||
createOrUpdateEmpty(intersection);
|
||||
}
|
||||
return intersection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {number} Margin.
|
||||
*/
|
||||
export function getMargin(extent) {
|
||||
return getWidth(extent) + getHeight(extent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size (width, height) of an extent.
|
||||
* @param {Extent} extent The extent.
|
||||
* @return {import("./size.js").Size} The extent size.
|
||||
* @api
|
||||
*/
|
||||
export function getSize(extent) {
|
||||
return [extent[2] - extent[0], extent[3] - extent[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top left coordinate of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {import("./coordinate.js").Coordinate} Top left coordinate.
|
||||
* @api
|
||||
*/
|
||||
export function getTopLeft(extent) {
|
||||
return [extent[0], extent[3]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the top right coordinate of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {import("./coordinate.js").Coordinate} Top right coordinate.
|
||||
* @api
|
||||
*/
|
||||
export function getTopRight(extent) {
|
||||
return [extent[2], extent[3]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {number} Width.
|
||||
* @api
|
||||
*/
|
||||
export function getWidth(extent) {
|
||||
return extent[2] - extent[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if one extent intersects another.
|
||||
* @param {Extent} extent1 Extent 1.
|
||||
* @param {Extent} extent2 Extent.
|
||||
* @return {boolean} The two extents intersect.
|
||||
* @api
|
||||
*/
|
||||
export function intersects(extent1, extent2) {
|
||||
return (
|
||||
extent1[0] <= extent2[2] &&
|
||||
extent1[2] >= extent2[0] &&
|
||||
extent1[1] <= extent2[3] &&
|
||||
extent1[3] >= extent2[1]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an extent is empty.
|
||||
* @param {Extent} extent Extent.
|
||||
* @return {boolean} Is empty.
|
||||
* @api
|
||||
*/
|
||||
export function isEmpty(extent) {
|
||||
return extent[2] < extent[0] || extent[3] < extent[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {Extent} [opt_extent] Extent.
|
||||
* @return {Extent} Extent.
|
||||
*/
|
||||
export function returnOrUpdate(extent, opt_extent) {
|
||||
if (opt_extent) {
|
||||
opt_extent[0] = extent[0];
|
||||
opt_extent[1] = extent[1];
|
||||
opt_extent[2] = extent[2];
|
||||
opt_extent[3] = extent[3];
|
||||
return opt_extent;
|
||||
} else {
|
||||
return extent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {number} value Value.
|
||||
*/
|
||||
export function scaleFromCenter(extent, value) {
|
||||
const deltaX = ((extent[2] - extent[0]) / 2) * (value - 1);
|
||||
const deltaY = ((extent[3] - extent[1]) / 2) * (value - 1);
|
||||
extent[0] -= deltaX;
|
||||
extent[2] += deltaX;
|
||||
extent[1] -= deltaY;
|
||||
extent[3] += deltaY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the segment between two coordinates intersects (crosses,
|
||||
* touches, or is contained by) the provided extent.
|
||||
* @param {Extent} extent The extent.
|
||||
* @param {import("./coordinate.js").Coordinate} start Segment start coordinate.
|
||||
* @param {import("./coordinate.js").Coordinate} end Segment end coordinate.
|
||||
* @return {boolean} The segment intersects the extent.
|
||||
*/
|
||||
export function intersectsSegment(extent, start, end) {
|
||||
let intersects = false;
|
||||
const startRel = coordinateRelationship(extent, start);
|
||||
const endRel = coordinateRelationship(extent, end);
|
||||
if (
|
||||
startRel === Relationship.INTERSECTING ||
|
||||
endRel === Relationship.INTERSECTING
|
||||
) {
|
||||
intersects = true;
|
||||
} else {
|
||||
const minX = extent[0];
|
||||
const minY = extent[1];
|
||||
const maxX = extent[2];
|
||||
const maxY = extent[3];
|
||||
const startX = start[0];
|
||||
const startY = start[1];
|
||||
const endX = end[0];
|
||||
const endY = end[1];
|
||||
const slope = (endY - startY) / (endX - startX);
|
||||
let x, y;
|
||||
if (!!(endRel & Relationship.ABOVE) && !(startRel & Relationship.ABOVE)) {
|
||||
// potentially intersects top
|
||||
x = endX - (endY - maxY) / slope;
|
||||
intersects = x >= minX && x <= maxX;
|
||||
}
|
||||
if (
|
||||
!intersects &&
|
||||
!!(endRel & Relationship.RIGHT) &&
|
||||
!(startRel & Relationship.RIGHT)
|
||||
) {
|
||||
// potentially intersects right
|
||||
y = endY - (endX - maxX) * slope;
|
||||
intersects = y >= minY && y <= maxY;
|
||||
}
|
||||
if (
|
||||
!intersects &&
|
||||
!!(endRel & Relationship.BELOW) &&
|
||||
!(startRel & Relationship.BELOW)
|
||||
) {
|
||||
// potentially intersects bottom
|
||||
x = endX - (endY - minY) / slope;
|
||||
intersects = x >= minX && x <= maxX;
|
||||
}
|
||||
if (
|
||||
!intersects &&
|
||||
!!(endRel & Relationship.LEFT) &&
|
||||
!(startRel & Relationship.LEFT)
|
||||
) {
|
||||
// potentially intersects left
|
||||
y = endY - (endX - minX) * slope;
|
||||
intersects = y >= minY && y <= maxY;
|
||||
}
|
||||
}
|
||||
return intersects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a transform function to the extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @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, 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 = [];
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the provided extent in-place to be within the real world
|
||||
* extent.
|
||||
*
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {import("./proj/Projection.js").default} projection Projection
|
||||
* @return {Extent} The extent within the real world extent.
|
||||
*/
|
||||
export function wrapX(extent, projection) {
|
||||
const projectionExtent = projection.getExtent();
|
||||
const center = getCenter(extent);
|
||||
if (
|
||||
projection.canWrapX() &&
|
||||
(center[0] < projectionExtent[0] || center[0] >= projectionExtent[2])
|
||||
) {
|
||||
const worldWidth = getWidth(projectionExtent);
|
||||
const worldsAway = Math.floor(
|
||||
(center[0] - projectionExtent[0]) / worldWidth
|
||||
);
|
||||
const offset = worldsAway * worldWidth;
|
||||
extent[0] -= offset;
|
||||
extent[2] -= offset;
|
||||
}
|
||||
return extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fits the extent to the real world
|
||||
*
|
||||
* If the extent does not cross the anti meridian, this will return the extent in an array
|
||||
* If the extent crosses the anti meridian, the extent will be sliced, so each part fits within the
|
||||
* real world
|
||||
*
|
||||
*
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {import("./proj/Projection.js").default} projection Projection
|
||||
* @return {Array<Extent>} The extent within the real world extent.
|
||||
*/
|
||||
export function wrapAndSliceX(extent, projection) {
|
||||
if (projection.canWrapX()) {
|
||||
const projectionExtent = projection.getExtent();
|
||||
|
||||
if (!isFinite(extent[0]) || !isFinite(extent[2])) {
|
||||
return [[projectionExtent[0], extent[1], projectionExtent[2], extent[3]]];
|
||||
}
|
||||
|
||||
wrapX(extent, projection);
|
||||
const worldWidth = getWidth(projectionExtent);
|
||||
|
||||
if (getWidth(extent) > worldWidth) {
|
||||
// the extent wraps around on itself
|
||||
return [[projectionExtent[0], extent[1], projectionExtent[2], extent[3]]];
|
||||
} else if (extent[0] < projectionExtent[0]) {
|
||||
// the extent crosses the anti meridian, so it needs to be sliced
|
||||
return [
|
||||
[extent[0] + worldWidth, extent[1], projectionExtent[2], extent[3]],
|
||||
[projectionExtent[0], extent[1], extent[2], extent[3]],
|
||||
];
|
||||
} else if (extent[2] > projectionExtent[2]) {
|
||||
// the extent crosses the anti meridian, so it needs to be sliced
|
||||
return [
|
||||
[extent[0], extent[1], projectionExtent[2], extent[3]],
|
||||
[projectionExtent[0], extent[1], extent[2] - worldWidth, extent[3]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return [extent];
|
||||
}
|
||||
16
node_modules/ol/src/extent/Relationship.js
generated
vendored
Normal file
16
node_modules/ol/src/extent/Relationship.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @module ol/extent/Relationship
|
||||
*/
|
||||
|
||||
/**
|
||||
* Relationship to an extent.
|
||||
* @enum {number}
|
||||
*/
|
||||
export default {
|
||||
UNKNOWN: 0,
|
||||
INTERSECTING: 1,
|
||||
ABOVE: 2,
|
||||
RIGHT: 4,
|
||||
BELOW: 8,
|
||||
LEFT: 16,
|
||||
};
|
||||
179
node_modules/ol/src/featureloader.js
generated
vendored
Normal file
179
node_modules/ol/src/featureloader.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @module ol/featureloader
|
||||
*/
|
||||
import {VOID} from './functions.js';
|
||||
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
let withCredentials = false;
|
||||
|
||||
/**
|
||||
* {@link module:ol/source/Vector~VectorSource} sources use a function of this type to
|
||||
* load features.
|
||||
*
|
||||
* This function takes up to 5 arguments. These are an {@link module:ol/extent~Extent} representing
|
||||
* the area to be loaded, a `{number}` representing the resolution (map units per pixel), an
|
||||
* {@link module:ol/proj/Projection~Projection} for the projection, an optional success callback that should get
|
||||
* the loaded features passed as an argument and an optional failure callback with no arguments. If
|
||||
* the callbacks are not used, the corresponding vector source will not fire `'featuresloadend'` and
|
||||
* `'featuresloaderror'` events. `this` within the function is bound to the
|
||||
* {@link module:ol/source/Vector~VectorSource} it's called from.
|
||||
*
|
||||
* The function is responsible for loading the features and adding them to the
|
||||
* source.
|
||||
* @typedef {function(this:(import("./source/Vector").default|import("./VectorTile.js").default),
|
||||
* import("./extent.js").Extent,
|
||||
* number,
|
||||
* import("./proj/Projection.js").default,
|
||||
* function(Array<import("./Feature.js").default>): void=,
|
||||
* function(): void=): void} FeatureLoader
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@link module:ol/source/Vector~VectorSource} sources use a function of this type to
|
||||
* get the url to load features from.
|
||||
*
|
||||
* This function takes an {@link module:ol/extent~Extent} representing the area
|
||||
* to be loaded, a `{number}` representing the resolution (map units per pixel)
|
||||
* and an {@link module:ol/proj/Projection~Projection} for the projection as
|
||||
* arguments and returns a `{string}` representing the URL.
|
||||
* @typedef {function(import("./extent.js").Extent, number, import("./proj/Projection.js").default): string} FeatureUrlFunction
|
||||
* @api
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string|FeatureUrlFunction} url Feature URL service.
|
||||
* @param {import("./format/Feature.js").default} format Feature format.
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {import("./proj/Projection.js").default} projection Projection.
|
||||
* @param {function(Array<import("./Feature.js").default>, import("./proj/Projection.js").default): void} success Success
|
||||
* Function called with the loaded features and optionally with the data projection.
|
||||
* @param {function(): void} failure Failure
|
||||
* Function called when loading failed.
|
||||
*/
|
||||
export function loadFeaturesXhr(
|
||||
url,
|
||||
format,
|
||||
extent,
|
||||
resolution,
|
||||
projection,
|
||||
success,
|
||||
failure
|
||||
) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open(
|
||||
'GET',
|
||||
typeof url === 'function' ? url(extent, resolution, projection) : url,
|
||||
true
|
||||
);
|
||||
if (format.getType() == 'arraybuffer') {
|
||||
xhr.responseType = 'arraybuffer';
|
||||
}
|
||||
xhr.withCredentials = withCredentials;
|
||||
/**
|
||||
* @param {Event} event Event.
|
||||
* @private
|
||||
*/
|
||||
xhr.onload = function (event) {
|
||||
// status will be 0 for file:// urls
|
||||
if (!xhr.status || (xhr.status >= 200 && xhr.status < 300)) {
|
||||
const type = format.getType();
|
||||
/** @type {Document|Node|Object|string|undefined} */
|
||||
let source;
|
||||
if (type == 'json' || type == 'text') {
|
||||
source = xhr.responseText;
|
||||
} else if (type == 'xml') {
|
||||
source = xhr.responseXML;
|
||||
if (!source) {
|
||||
source = new DOMParser().parseFromString(
|
||||
xhr.responseText,
|
||||
'application/xml'
|
||||
);
|
||||
}
|
||||
} else if (type == 'arraybuffer') {
|
||||
source = /** @type {ArrayBuffer} */ (xhr.response);
|
||||
}
|
||||
if (source) {
|
||||
success(
|
||||
/** @type {Array<import("./Feature.js").default>} */
|
||||
(
|
||||
format.readFeatures(source, {
|
||||
extent: extent,
|
||||
featureProjection: projection,
|
||||
})
|
||||
),
|
||||
format.readProjection(source)
|
||||
);
|
||||
} else {
|
||||
failure();
|
||||
}
|
||||
} else {
|
||||
failure();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
xhr.onerror = failure;
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an XHR feature loader for a `url` and `format`. The feature loader
|
||||
* loads features (with XHR), parses the features, and adds them to the
|
||||
* vector source.
|
||||
* @param {string|FeatureUrlFunction} url Feature URL service.
|
||||
* @param {import("./format/Feature.js").default} format Feature format.
|
||||
* @return {FeatureLoader} The feature loader.
|
||||
* @api
|
||||
*/
|
||||
export function xhr(url, format) {
|
||||
/**
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {import("./proj/Projection.js").default} projection Projection.
|
||||
* @param {function(Array<import("./Feature.js").default>): void} [success] Success
|
||||
* Function called when loading succeeded.
|
||||
* @param {function(): void} [failure] Failure
|
||||
* Function called when loading failed.
|
||||
* @this {import("./source/Vector").default}
|
||||
*/
|
||||
return function (extent, resolution, projection, success, failure) {
|
||||
const source = /** @type {import("./source/Vector").default} */ (this);
|
||||
loadFeaturesXhr(
|
||||
url,
|
||||
format,
|
||||
extent,
|
||||
resolution,
|
||||
projection,
|
||||
/**
|
||||
* @param {Array<import("./Feature.js").default>} features The loaded features.
|
||||
* @param {import("./proj/Projection.js").default} dataProjection Data
|
||||
* projection.
|
||||
*/
|
||||
function (features, dataProjection) {
|
||||
source.addFeatures(features);
|
||||
if (success !== undefined) {
|
||||
success(features);
|
||||
}
|
||||
},
|
||||
/* FIXME handle error */ failure ? failure : VOID
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the withCredentials configuration for the XHR.
|
||||
*
|
||||
* @param {boolean} xhrWithCredentials The value of withCredentials to set.
|
||||
* Compare https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/
|
||||
* @api
|
||||
*/
|
||||
export function setWithCredentials(xhrWithCredentials) {
|
||||
withCredentials = xhrWithCredentials;
|
||||
}
|
||||
21
node_modules/ol/src/format.js
generated
vendored
Normal file
21
node_modules/ol/src/format.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @module ol/format
|
||||
*/
|
||||
|
||||
export {default as EsriJSON} from './format/EsriJSON.js';
|
||||
export {default as GeoJSON} from './format/GeoJSON.js';
|
||||
export {default as GML} from './format/GML.js';
|
||||
export {default as GPX} from './format/GPX.js';
|
||||
export {default as IGC} from './format/IGC.js';
|
||||
export {default as IIIFInfo} from './format/IIIFInfo.js';
|
||||
export {default as KML} from './format/KML.js';
|
||||
export {default as MVT} from './format/MVT.js';
|
||||
export {default as OWS} from './format/OWS.js';
|
||||
export {default as Polyline} from './format/Polyline.js';
|
||||
export {default as TopoJSON} from './format/TopoJSON.js';
|
||||
export {default as WFS} from './format/WFS.js';
|
||||
export {default as WKB} from './format/WKB.js';
|
||||
export {default as WKT} from './format/WKT.js';
|
||||
export {default as WMSCapabilities} from './format/WMSCapabilities.js';
|
||||
export {default as WMSGetFeatureInfo} from './format/WMSGetFeatureInfo.js';
|
||||
export {default as WMTSCapabilities} from './format/WMTSCapabilities.js';
|
||||
581
node_modules/ol/src/format/EsriJSON.js
generated
vendored
Normal file
581
node_modules/ol/src/format/EsriJSON.js
generated
vendored
Normal file
@@ -0,0 +1,581 @@
|
||||
/**
|
||||
* @module ol/format/EsriJSON
|
||||
*/
|
||||
import Feature from '../Feature.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import JSONFeature from './JSONFeature.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import LinearRing from '../geom/LinearRing.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import MultiPoint from '../geom/MultiPoint.js';
|
||||
import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import {assert} from '../asserts.js';
|
||||
import {assign, isEmpty} from '../obj.js';
|
||||
import {containsExtent} from '../extent.js';
|
||||
import {deflateCoordinates} from '../geom/flat/deflate.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {linearRingIsClockwise} from '../geom/flat/orient.js';
|
||||
import {transformGeometryWithOptions} from './Feature.js';
|
||||
|
||||
/**
|
||||
* @typedef {import("arcgis-rest-api").Feature} EsriJSONFeature
|
||||
* @typedef {import("arcgis-rest-api").FeatureSet} EsriJSONFeatureSet
|
||||
* @typedef {import("arcgis-rest-api").Geometry} EsriJSONGeometry
|
||||
* @typedef {import("arcgis-rest-api").Point} EsriJSONPoint
|
||||
* @typedef {import("arcgis-rest-api").Polyline} EsriJSONPolyline
|
||||
* @typedef {import("arcgis-rest-api").Polygon} EsriJSONPolygon
|
||||
* @typedef {import("arcgis-rest-api").Multipoint} EsriJSONMultipoint
|
||||
* @typedef {import("arcgis-rest-api").HasZM} EsriJSONHasZM
|
||||
* @typedef {import("arcgis-rest-api").Position} EsriJSONPosition
|
||||
* @typedef {import("arcgis-rest-api").SpatialReferenceWkid} EsriJSONSpatialReferenceWkid
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} EsriJSONMultiPolygon
|
||||
* @property {Array<Array<Array<Array<number>>>>} rings Rings for the MultiPolygon.
|
||||
* @property {boolean} [hasM] If the polygon coordinates have an M value.
|
||||
* @property {boolean} [hasZ] If the polygon coordinates have a Z value.
|
||||
* @property {EsriJSONSpatialReferenceWkid} [spatialReference] The coordinate reference system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<import("../geom/Geometry.js").Type, function(EsriJSONGeometry): import("../geom/Geometry.js").default>}
|
||||
*/
|
||||
const GEOMETRY_READERS = {
|
||||
Point: readPointGeometry,
|
||||
LineString: readLineStringGeometry,
|
||||
Polygon: readPolygonGeometry,
|
||||
MultiPoint: readMultiPointGeometry,
|
||||
MultiLineString: readMultiLineStringGeometry,
|
||||
MultiPolygon: readMultiPolygonGeometry,
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<import("../geom/Geometry.js").Type, function(import("../geom/Geometry.js").default, import("./Feature.js").WriteOptions=): (EsriJSONGeometry)>}
|
||||
*/
|
||||
const GEOMETRY_WRITERS = {
|
||||
Point: writePointGeometry,
|
||||
LineString: writeLineStringGeometry,
|
||||
Polygon: writePolygonGeometry,
|
||||
MultiPoint: writeMultiPointGeometry,
|
||||
MultiLineString: writeMultiLineStringGeometry,
|
||||
MultiPolygon: writeMultiPolygonGeometry,
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [geometryName] Geometry name to use when creating features.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the EsriJSON format.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class EsriJSON extends JSONFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* Name of the geometry attribute for features.
|
||||
* @type {string|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.geometryName_ = options.geometryName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @param {string} [opt_idField] Name of the field where to get the id from.
|
||||
* @protected
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromObject(object, opt_options, opt_idField) {
|
||||
const esriJSONFeature = /** @type {EsriJSONFeature} */ (object);
|
||||
const geometry = readGeometry(esriJSONFeature.geometry, opt_options);
|
||||
const feature = new Feature();
|
||||
if (this.geometryName_) {
|
||||
feature.setGeometryName(this.geometryName_);
|
||||
}
|
||||
feature.setGeometry(geometry);
|
||||
if (esriJSONFeature.attributes) {
|
||||
feature.setProperties(esriJSONFeature.attributes, true);
|
||||
const id = esriJSONFeature.attributes[opt_idField];
|
||||
if (id !== undefined) {
|
||||
feature.setId(/** @type {number} */ (id));
|
||||
}
|
||||
}
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {Array<Feature>} Features.
|
||||
*/
|
||||
readFeaturesFromObject(object, opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
if (object['features']) {
|
||||
const esriJSONFeatureSet = /** @type {EsriJSONFeatureSet} */ (object);
|
||||
/** @type {Array<import("../Feature.js").default>} */
|
||||
const features = [];
|
||||
const esriJSONFeatures = esriJSONFeatureSet.features;
|
||||
for (let i = 0, ii = esriJSONFeatures.length; i < ii; ++i) {
|
||||
features.push(
|
||||
this.readFeatureFromObject(
|
||||
esriJSONFeatures[i],
|
||||
options,
|
||||
object.objectIdFieldName
|
||||
)
|
||||
);
|
||||
}
|
||||
return features;
|
||||
} else {
|
||||
return [this.readFeatureFromObject(object, options)];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromObject(object, opt_options) {
|
||||
return readGeometry(object, opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @protected
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjectionFromObject(object) {
|
||||
if (
|
||||
object['spatialReference'] &&
|
||||
object['spatialReference']['wkid'] !== undefined
|
||||
) {
|
||||
const spatialReference = /** @type {EsriJSONSpatialReferenceWkid} */ (
|
||||
object['spatialReference']
|
||||
);
|
||||
const crs = spatialReference.wkid;
|
||||
return getProjection('EPSG:' + crs);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a geometry as a EsriJSON object.
|
||||
*
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONGeometry} Object.
|
||||
* @api
|
||||
*/
|
||||
writeGeometryObject(geometry, opt_options) {
|
||||
return writeGeometry(geometry, this.adaptOptions(opt_options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature as a esriJSON Feature object.
|
||||
*
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {Object} Object.
|
||||
* @api
|
||||
*/
|
||||
writeFeatureObject(feature, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
const object = {};
|
||||
if (!feature.hasProperties()) {
|
||||
object['attributes'] = {};
|
||||
return object;
|
||||
}
|
||||
const properties = feature.getProperties();
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
object['geometry'] = writeGeometry(geometry, opt_options);
|
||||
const projection =
|
||||
opt_options &&
|
||||
(opt_options.dataProjection || opt_options.featureProjection);
|
||||
if (projection) {
|
||||
object['geometry']['spatialReference'] =
|
||||
/** @type {EsriJSONSpatialReferenceWkid} */ ({
|
||||
wkid: Number(getProjection(projection).getCode().split(':').pop()),
|
||||
});
|
||||
}
|
||||
delete properties[feature.getGeometryName()];
|
||||
}
|
||||
if (!isEmpty(properties)) {
|
||||
object['attributes'] = properties;
|
||||
} else {
|
||||
object['attributes'] = {};
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features as a EsriJSON object.
|
||||
*
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONFeatureSet} EsriJSON Object.
|
||||
* @api
|
||||
*/
|
||||
writeFeaturesObject(features, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
const objects = [];
|
||||
for (let i = 0, ii = features.length; i < ii; ++i) {
|
||||
objects.push(this.writeFeatureObject(features[i], opt_options));
|
||||
}
|
||||
return {
|
||||
'features': objects,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
function readGeometry(object, opt_options) {
|
||||
if (!object) {
|
||||
return null;
|
||||
}
|
||||
/** @type {import("../geom/Geometry.js").Type} */
|
||||
let type;
|
||||
if (typeof object['x'] === 'number' && typeof object['y'] === 'number') {
|
||||
type = 'Point';
|
||||
} else if (object['points']) {
|
||||
type = 'MultiPoint';
|
||||
} else if (object['paths']) {
|
||||
const esriJSONPolyline = /** @type {EsriJSONPolyline} */ (object);
|
||||
if (esriJSONPolyline.paths.length === 1) {
|
||||
type = 'LineString';
|
||||
} else {
|
||||
type = 'MultiLineString';
|
||||
}
|
||||
} else if (object['rings']) {
|
||||
const esriJSONPolygon = /** @type {EsriJSONPolygon} */ (object);
|
||||
const layout = getGeometryLayout(esriJSONPolygon);
|
||||
const rings = convertRings(esriJSONPolygon.rings, layout);
|
||||
if (rings.length === 1) {
|
||||
type = 'Polygon';
|
||||
object = assign({}, object, {['rings']: rings[0]});
|
||||
} else {
|
||||
type = 'MultiPolygon';
|
||||
object = assign({}, object, {['rings']: rings});
|
||||
}
|
||||
}
|
||||
const geometryReader = GEOMETRY_READERS[type];
|
||||
return transformGeometryWithOptions(
|
||||
geometryReader(object),
|
||||
false,
|
||||
opt_options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines inner and outer rings.
|
||||
* Checks if any polygons in this array contain any other polygons in this
|
||||
* array. It is used for checking for holes.
|
||||
* Logic inspired by: https://github.com/Esri/terraformer-arcgis-parser
|
||||
* @param {Array<!Array<!Array<number>>>} rings Rings.
|
||||
* @param {import("../geom/GeometryLayout.js").default} layout Geometry layout.
|
||||
* @return {Array<!Array<!Array<!Array<number>>>>} Transformed rings.
|
||||
*/
|
||||
function convertRings(rings, layout) {
|
||||
const flatRing = [];
|
||||
const outerRings = [];
|
||||
const holes = [];
|
||||
let i, ii;
|
||||
for (i = 0, ii = rings.length; i < ii; ++i) {
|
||||
flatRing.length = 0;
|
||||
deflateCoordinates(flatRing, 0, rings[i], layout.length);
|
||||
// is this ring an outer ring? is it clockwise?
|
||||
const clockwise = linearRingIsClockwise(
|
||||
flatRing,
|
||||
0,
|
||||
flatRing.length,
|
||||
layout.length
|
||||
);
|
||||
if (clockwise) {
|
||||
outerRings.push([rings[i]]);
|
||||
} else {
|
||||
holes.push(rings[i]);
|
||||
}
|
||||
}
|
||||
while (holes.length) {
|
||||
const hole = holes.shift();
|
||||
let matched = false;
|
||||
// loop over all outer rings and see if they contain our hole.
|
||||
for (i = outerRings.length - 1; i >= 0; i--) {
|
||||
const outerRing = outerRings[i][0];
|
||||
const containsHole = containsExtent(
|
||||
new LinearRing(outerRing).getExtent(),
|
||||
new LinearRing(hole).getExtent()
|
||||
);
|
||||
if (containsHole) {
|
||||
// the hole is contained push it into our polygon
|
||||
outerRings[i].push(hole);
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched) {
|
||||
// no outer rings contain this hole turn it into and outer
|
||||
// ring (reverse it)
|
||||
outerRings.push([hole.reverse()]);
|
||||
}
|
||||
}
|
||||
return outerRings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONPoint} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} Point.
|
||||
*/
|
||||
function readPointGeometry(object) {
|
||||
let point;
|
||||
if (object.m !== undefined && object.z !== undefined) {
|
||||
point = new Point(
|
||||
[object.x, object.y, object.z, object.m],
|
||||
GeometryLayout.XYZM
|
||||
);
|
||||
} else if (object.z !== undefined) {
|
||||
point = new Point([object.x, object.y, object.z], GeometryLayout.XYZ);
|
||||
} else if (object.m !== undefined) {
|
||||
point = new Point([object.x, object.y, object.m], GeometryLayout.XYM);
|
||||
} else {
|
||||
point = new Point([object.x, object.y]);
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONPolyline} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} LineString.
|
||||
*/
|
||||
function readLineStringGeometry(object) {
|
||||
const layout = getGeometryLayout(object);
|
||||
return new LineString(object.paths[0], layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONPolyline} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} MultiLineString.
|
||||
*/
|
||||
function readMultiLineStringGeometry(object) {
|
||||
const layout = getGeometryLayout(object);
|
||||
return new MultiLineString(object.paths, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONHasZM} object Object.
|
||||
* @return {import("../geom/GeometryLayout.js").default} The geometry layout to use.
|
||||
*/
|
||||
function getGeometryLayout(object) {
|
||||
let layout = GeometryLayout.XY;
|
||||
if (object.hasZ === true && object.hasM === true) {
|
||||
layout = GeometryLayout.XYZM;
|
||||
} else if (object.hasZ === true) {
|
||||
layout = GeometryLayout.XYZ;
|
||||
} else if (object.hasM === true) {
|
||||
layout = GeometryLayout.XYM;
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONMultipoint} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} MultiPoint.
|
||||
*/
|
||||
function readMultiPointGeometry(object) {
|
||||
const layout = getGeometryLayout(object);
|
||||
return new MultiPoint(object.points, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONMultiPolygon} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} MultiPolygon.
|
||||
*/
|
||||
function readMultiPolygonGeometry(object) {
|
||||
const layout = getGeometryLayout(object);
|
||||
return new MultiPolygon(object.rings, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {EsriJSONPolygon} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} Polygon.
|
||||
*/
|
||||
function readPolygonGeometry(object) {
|
||||
const layout = getGeometryLayout(object);
|
||||
return new Polygon(object.rings, layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Point.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONPoint} EsriJSON geometry.
|
||||
*/
|
||||
function writePointGeometry(geometry, opt_options) {
|
||||
const coordinates = geometry.getCoordinates();
|
||||
/** @type {EsriJSONPoint} */
|
||||
let esriJSON;
|
||||
const layout = geometry.getLayout();
|
||||
if (layout === GeometryLayout.XYZ) {
|
||||
esriJSON = {
|
||||
x: coordinates[0],
|
||||
y: coordinates[1],
|
||||
z: coordinates[2],
|
||||
};
|
||||
} else if (layout === GeometryLayout.XYM) {
|
||||
esriJSON = {
|
||||
x: coordinates[0],
|
||||
y: coordinates[1],
|
||||
m: coordinates[2],
|
||||
};
|
||||
} else if (layout === GeometryLayout.XYZM) {
|
||||
esriJSON = {
|
||||
x: coordinates[0],
|
||||
y: coordinates[1],
|
||||
z: coordinates[2],
|
||||
m: coordinates[3],
|
||||
};
|
||||
} else if (layout === GeometryLayout.XY) {
|
||||
esriJSON = {
|
||||
x: coordinates[0],
|
||||
y: coordinates[1],
|
||||
};
|
||||
} else {
|
||||
assert(false, 34); // Invalid geometry layout
|
||||
}
|
||||
return esriJSON;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/SimpleGeometry.js").default} geometry Geometry.
|
||||
* @return {Object} Object with boolean hasZ and hasM keys.
|
||||
*/
|
||||
function getHasZM(geometry) {
|
||||
const layout = geometry.getLayout();
|
||||
return {
|
||||
hasZ: layout === GeometryLayout.XYZ || layout === GeometryLayout.XYZM,
|
||||
hasM: layout === GeometryLayout.XYM || layout === GeometryLayout.XYZM,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/LineString.js").default} lineString Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONPolyline} EsriJSON geometry.
|
||||
*/
|
||||
function writeLineStringGeometry(lineString, opt_options) {
|
||||
const hasZM = getHasZM(lineString);
|
||||
return {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
paths: [
|
||||
/** @type {Array<EsriJSONPosition>} */ (lineString.getCoordinates()),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Polygon.js").default} polygon Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONPolygon} EsriJSON geometry.
|
||||
*/
|
||||
function writePolygonGeometry(polygon, opt_options) {
|
||||
// Esri geometries use the left-hand rule
|
||||
const hasZM = getHasZM(polygon);
|
||||
return {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
rings: /** @type {Array<Array<EsriJSONPosition>>} */ (
|
||||
polygon.getCoordinates(false)
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/MultiLineString.js").default} multiLineString Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONPolyline} EsriJSON geometry.
|
||||
*/
|
||||
function writeMultiLineStringGeometry(multiLineString, opt_options) {
|
||||
const hasZM = getHasZM(multiLineString);
|
||||
return {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
paths: /** @type {Array<Array<EsriJSONPosition>>} */ (
|
||||
multiLineString.getCoordinates()
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/MultiPoint.js").default} multiPoint Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONMultipoint} EsriJSON geometry.
|
||||
*/
|
||||
function writeMultiPointGeometry(multiPoint, opt_options) {
|
||||
const hasZM = getHasZM(multiPoint);
|
||||
return {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
points: /** @type {Array<EsriJSONPosition>} */ (
|
||||
multiPoint.getCoordinates()
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/MultiPolygon.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONPolygon} EsriJSON geometry.
|
||||
*/
|
||||
function writeMultiPolygonGeometry(geometry, opt_options) {
|
||||
const hasZM = getHasZM(geometry);
|
||||
const coordinates = geometry.getCoordinates(false);
|
||||
const output = [];
|
||||
for (let i = 0; i < coordinates.length; i++) {
|
||||
for (let x = coordinates[i].length - 1; x >= 0; x--) {
|
||||
output.push(coordinates[i][x]);
|
||||
}
|
||||
}
|
||||
return {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
rings: /** @type {Array<Array<EsriJSONPosition>>} */ (output),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {EsriJSONGeometry} EsriJSON geometry.
|
||||
*/
|
||||
function writeGeometry(geometry, opt_options) {
|
||||
const geometryWriter = GEOMETRY_WRITERS[geometry.getType()];
|
||||
return geometryWriter(
|
||||
transformGeometryWithOptions(geometry, true, opt_options),
|
||||
opt_options
|
||||
);
|
||||
}
|
||||
|
||||
export default EsriJSON;
|
||||
310
node_modules/ol/src/format/Feature.js
generated
vendored
Normal file
310
node_modules/ol/src/format/Feature.js
generated
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
/**
|
||||
* @module ol/format/Feature
|
||||
*/
|
||||
import Units from '../proj/Units.js';
|
||||
import {abstract} from '../util.js';
|
||||
import {assign} from '../obj.js';
|
||||
import {
|
||||
equivalent as equivalentProjection,
|
||||
get as getProjection,
|
||||
transformExtent,
|
||||
} from '../proj.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} ReadOptions
|
||||
* @property {import("../proj.js").ProjectionLike} [dataProjection] Projection of the data we are reading.
|
||||
* If not provided, the projection will be derived from the data (where possible) or
|
||||
* the `dataProjection` of the format is assigned (where set). If the projection
|
||||
* can not be derived from the data and if no `dataProjection` is set for a format,
|
||||
* the features will not be reprojected.
|
||||
* @property {import("../extent.js").Extent} [extent] Tile extent in map units of the tile being read.
|
||||
* This is only required when reading data with tile pixels as geometry units. When configured,
|
||||
* a `dataProjection` with `TILE_PIXELS` as `units` and the tile's pixel extent as `extent` needs to be
|
||||
* provided.
|
||||
* @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
|
||||
* created by the format reader. If not provided, features will be returned in the
|
||||
* `dataProjection`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} WriteOptions
|
||||
* @property {import("../proj.js").ProjectionLike} [dataProjection] Projection of the data we are writing.
|
||||
* If not provided, the `dataProjection` of the format is assigned (where set).
|
||||
* If no `dataProjection` is set for a format, the features will be returned
|
||||
* in the `featureProjection`.
|
||||
* @property {import("../proj.js").ProjectionLike} [featureProjection] Projection of the feature geometries
|
||||
* that will be serialized by the format writer. If not provided, geometries are assumed
|
||||
* to be in the `dataProjection` if that is set; in other words, they are not transformed.
|
||||
* @property {boolean} [rightHanded] When writing geometries, follow the right-hand
|
||||
* rule for linear ring orientation. This means that polygons will have counter-clockwise
|
||||
* exterior rings and clockwise interior rings. By default, coordinates are serialized
|
||||
* as they are provided at construction. If `true`, the right-hand rule will
|
||||
* be applied. If `false`, the left-hand rule will be applied (clockwise for
|
||||
* exterior and counter-clockwise for interior rings). Note that not all
|
||||
* formats support this. The GeoJSON format does use this property when writing
|
||||
* geometries.
|
||||
* @property {number} [decimals] Maximum number of decimal places for coordinates.
|
||||
* Coordinates are stored internally as floats, but floating-point arithmetic can create
|
||||
* coordinates with a large number of decimal places, not generally wanted on output.
|
||||
* Set a number here to round coordinates. Can also be used to ensure that
|
||||
* coordinates read in can be written back out with the same number of decimals.
|
||||
* Default is no rounding.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {'arraybuffer' | 'json' | 'text' | 'xml'} Type
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for feature formats.
|
||||
* {@link module:ol/format/Feature~FeatureFormat} subclasses provide the ability to decode and encode
|
||||
* {@link module:ol/Feature~Feature} objects from a variety of commonly used geospatial
|
||||
* file formats. See the documentation for each format for more details.
|
||||
*
|
||||
* @abstract
|
||||
* @api
|
||||
*/
|
||||
class FeatureFormat {
|
||||
constructor() {
|
||||
/**
|
||||
* @protected
|
||||
* @type {import("../proj/Projection.js").default|undefined}
|
||||
*/
|
||||
this.dataProjection = undefined;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {import("../proj/Projection.js").default|undefined}
|
||||
*/
|
||||
this.defaultFeatureProjection = undefined;
|
||||
|
||||
/**
|
||||
* A list media types supported by the format in descending order of preference.
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
this.supportedMediaTypes = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the data projection to the read options.
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {ReadOptions} [opt_options] Options.
|
||||
* @return {ReadOptions|undefined} Options.
|
||||
* @protected
|
||||
*/
|
||||
getReadOptions(source, opt_options) {
|
||||
let options;
|
||||
if (opt_options) {
|
||||
let dataProjection = opt_options.dataProjection
|
||||
? getProjection(opt_options.dataProjection)
|
||||
: this.readProjection(source);
|
||||
if (
|
||||
opt_options.extent &&
|
||||
dataProjection &&
|
||||
dataProjection.getUnits() === Units.TILE_PIXELS
|
||||
) {
|
||||
dataProjection = getProjection(dataProjection);
|
||||
dataProjection.setWorldExtent(opt_options.extent);
|
||||
}
|
||||
options = {
|
||||
dataProjection: dataProjection,
|
||||
featureProjection: opt_options.featureProjection,
|
||||
};
|
||||
}
|
||||
return this.adaptOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the `dataProjection` on the options, if no `dataProjection`
|
||||
* is set.
|
||||
* @param {WriteOptions|ReadOptions|undefined} options
|
||||
* Options.
|
||||
* @protected
|
||||
* @return {WriteOptions|ReadOptions|undefined}
|
||||
* Updated options.
|
||||
*/
|
||||
adaptOptions(options) {
|
||||
return assign(
|
||||
{
|
||||
dataProjection: this.dataProjection,
|
||||
featureProjection: this.defaultFeatureProjection,
|
||||
},
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {Type} The format type.
|
||||
*/
|
||||
getType() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single feature from a source.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../Feature.js").FeatureLike} Feature.
|
||||
*/
|
||||
readFeature(source, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all features from a source.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Document|Element|ArrayBuffer|Object|string} source Source.
|
||||
* @param {ReadOptions} [opt_options] Read options.
|
||||
* @return {Array<import("../Feature.js").FeatureLike>} Features.
|
||||
*/
|
||||
readFeatures(source, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single geometry from a source.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometry(source, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection from a source.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @return {import("../proj/Projection.js").default|undefined} Projection.
|
||||
*/
|
||||
readProjection(source) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature in this format.
|
||||
*
|
||||
* @abstract
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {WriteOptions} [opt_options] Write options.
|
||||
* @return {string|ArrayBuffer} Result.
|
||||
*/
|
||||
writeFeature(feature, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features in this format.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {WriteOptions} [opt_options] Write options.
|
||||
* @return {string|ArrayBuffer} Result.
|
||||
*/
|
||||
writeFeatures(features, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single geometry in this format.
|
||||
*
|
||||
* @abstract
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {WriteOptions} [opt_options] Write options.
|
||||
* @return {string|ArrayBuffer} Result.
|
||||
*/
|
||||
writeGeometry(geometry, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
}
|
||||
|
||||
export default FeatureFormat;
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {boolean} write Set to true for writing, false for reading.
|
||||
* @param {WriteOptions|ReadOptions} [opt_options] Options.
|
||||
* @return {import("../geom/Geometry.js").default} Transformed geometry.
|
||||
*/
|
||||
export function transformGeometryWithOptions(geometry, write, opt_options) {
|
||||
const featureProjection = opt_options
|
||||
? getProjection(opt_options.featureProjection)
|
||||
: null;
|
||||
const dataProjection = opt_options
|
||||
? getProjection(opt_options.dataProjection)
|
||||
: null;
|
||||
|
||||
let transformed;
|
||||
if (
|
||||
featureProjection &&
|
||||
dataProjection &&
|
||||
!equivalentProjection(featureProjection, dataProjection)
|
||||
) {
|
||||
transformed = (write ? geometry.clone() : geometry).transform(
|
||||
write ? featureProjection : dataProjection,
|
||||
write ? dataProjection : featureProjection
|
||||
);
|
||||
} else {
|
||||
transformed = geometry;
|
||||
}
|
||||
if (
|
||||
write &&
|
||||
opt_options &&
|
||||
/** @type {WriteOptions} */ (opt_options).decimals !== undefined
|
||||
) {
|
||||
const power = Math.pow(
|
||||
10,
|
||||
/** @type {WriteOptions} */ (opt_options).decimals
|
||||
);
|
||||
// if decimals option on write, round each coordinate appropriately
|
||||
/**
|
||||
* @param {Array<number>} coordinates Coordinates.
|
||||
* @return {Array<number>} Transformed coordinates.
|
||||
*/
|
||||
const transform = function (coordinates) {
|
||||
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
coordinates[i] = Math.round(coordinates[i] * power) / power;
|
||||
}
|
||||
return coordinates;
|
||||
};
|
||||
if (transformed === geometry) {
|
||||
transformed = geometry.clone();
|
||||
}
|
||||
transformed.applyTransform(transform);
|
||||
}
|
||||
return transformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../extent.js").Extent} extent Extent.
|
||||
* @param {ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../extent.js").Extent} Transformed extent.
|
||||
*/
|
||||
export function transformExtentWithOptions(extent, opt_options) {
|
||||
const featureProjection = opt_options
|
||||
? getProjection(opt_options.featureProjection)
|
||||
: null;
|
||||
const dataProjection = opt_options
|
||||
? getProjection(opt_options.dataProjection)
|
||||
: null;
|
||||
|
||||
if (
|
||||
featureProjection &&
|
||||
dataProjection &&
|
||||
!equivalentProjection(featureProjection, dataProjection)
|
||||
) {
|
||||
return transformExtent(extent, dataProjection, featureProjection);
|
||||
} else {
|
||||
return extent;
|
||||
}
|
||||
}
|
||||
40
node_modules/ol/src/format/GML.js
generated
vendored
Normal file
40
node_modules/ol/src/format/GML.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @module ol/format/GML
|
||||
*/
|
||||
import GML3 from './GML3.js';
|
||||
|
||||
/**
|
||||
* Feature format for reading and writing data in the GML format
|
||||
* version 3.1.1.
|
||||
* Currently only supports GML 3.1.1 Simple Features profile.
|
||||
*
|
||||
* @class
|
||||
* @param {import("./GMLBase.js").Options} [opt_options]
|
||||
* Optional configuration object.
|
||||
* @api
|
||||
*/
|
||||
const GML = GML3;
|
||||
|
||||
/**
|
||||
* Encode an array of features in GML 3.1.1 Simple Features.
|
||||
*
|
||||
* @function
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Options.
|
||||
* @return {string} Result.
|
||||
* @api
|
||||
*/
|
||||
GML.prototype.writeFeatures;
|
||||
|
||||
/**
|
||||
* Encode an array of features in the GML 3.1.1 format as an XML node.
|
||||
*
|
||||
* @function
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Options.
|
||||
* @return {Node} Node.
|
||||
* @api
|
||||
*/
|
||||
GML.prototype.writeFeaturesNode;
|
||||
|
||||
export default GML;
|
||||
788
node_modules/ol/src/format/GML2.js
generated
vendored
Normal file
788
node_modules/ol/src/format/GML2.js
generated
vendored
Normal file
@@ -0,0 +1,788 @@
|
||||
/**
|
||||
* @module ol/format/GML2
|
||||
*/
|
||||
import GMLBase, {GMLNS} from './GMLBase.js';
|
||||
import {
|
||||
OBJECT_PROPERTY_NODE_FACTORY,
|
||||
createElementNS,
|
||||
getAllTextContent,
|
||||
makeArrayPusher,
|
||||
makeChildAppender,
|
||||
makeReplacer,
|
||||
makeSimpleNodeFactory,
|
||||
pushParseAndPop,
|
||||
pushSerializeAndPop,
|
||||
} from '../xml.js';
|
||||
import {assign} from '../obj.js';
|
||||
import {createOrUpdate} from '../extent.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {
|
||||
transformExtentWithOptions,
|
||||
transformGeometryWithOptions,
|
||||
} from './Feature.js';
|
||||
import {writeStringTextNode} from './xsd.js';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
const schemaLocation =
|
||||
GMLNS + ' http://schemas.opengis.net/gml/2.1.2/feature.xsd';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, string>}
|
||||
*/
|
||||
const MULTIGEOMETRY_TO_MEMBER_NODENAME = {
|
||||
'MultiLineString': 'lineStringMember',
|
||||
'MultiCurve': 'curveMember',
|
||||
'MultiPolygon': 'polygonMember',
|
||||
'MultiSurface': 'surfaceMember',
|
||||
};
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the GML format,
|
||||
* version 2.1.2.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class GML2 extends GMLBase {
|
||||
/**
|
||||
* @param {import("./GMLBase.js").Options} [opt_options] Optional configuration object.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options =
|
||||
/** @type {import("./GMLBase.js").Options} */
|
||||
(opt_options ? opt_options : {});
|
||||
|
||||
super(options);
|
||||
|
||||
this.FEATURE_COLLECTION_PARSERS[GMLNS]['featureMember'] = makeArrayPusher(
|
||||
this.readFeaturesInternal
|
||||
);
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.schemaLocation = options.schemaLocation
|
||||
? options.schemaLocation
|
||||
: schemaLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Array<number>|undefined} Flat coordinates.
|
||||
*/
|
||||
readFlatCoordinates(node, objectStack) {
|
||||
const s = getAllTextContent(node, false).replace(/^\s*|\s*$/g, '');
|
||||
const context = /** @type {import("../xml.js").NodeStackItem} */ (
|
||||
objectStack[0]
|
||||
);
|
||||
const containerSrs = context['srsName'];
|
||||
let axisOrientation = 'enu';
|
||||
if (containerSrs) {
|
||||
const proj = getProjection(containerSrs);
|
||||
if (proj) {
|
||||
axisOrientation = proj.getAxisOrientation();
|
||||
}
|
||||
}
|
||||
const coordsGroups = s.trim().split(/\s+/);
|
||||
const flatCoordinates = [];
|
||||
for (let i = 0, ii = coordsGroups.length; i < ii; i++) {
|
||||
const coords = coordsGroups[i].split(/,+/);
|
||||
const x = parseFloat(coords[0]);
|
||||
const y = parseFloat(coords[1]);
|
||||
const z = coords.length === 3 ? parseFloat(coords[2]) : 0;
|
||||
if (axisOrientation.substr(0, 2) === 'en') {
|
||||
flatCoordinates.push(x, y, z);
|
||||
} else {
|
||||
flatCoordinates.push(y, x, z);
|
||||
}
|
||||
}
|
||||
return flatCoordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {import("../extent.js").Extent|undefined} Envelope.
|
||||
*/
|
||||
readBox(node, objectStack) {
|
||||
/** @type {Array<number>} */
|
||||
const flatCoordinates = pushParseAndPop(
|
||||
[null],
|
||||
this.BOX_PARSERS_,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
return createOrUpdate(
|
||||
flatCoordinates[1][0],
|
||||
flatCoordinates[1][1],
|
||||
flatCoordinates[1][3],
|
||||
flatCoordinates[1][4]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
innerBoundaryIsParser(node, objectStack) {
|
||||
/** @type {Array<number>|undefined} */
|
||||
const flatLinearRing = pushParseAndPop(
|
||||
undefined,
|
||||
this.RING_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
if (flatLinearRing) {
|
||||
const flatLinearRings =
|
||||
/** @type {Array<Array<number>>} */
|
||||
(objectStack[objectStack.length - 1]);
|
||||
flatLinearRings.push(flatLinearRing);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
outerBoundaryIsParser(node, objectStack) {
|
||||
/** @type {Array<number>|undefined} */
|
||||
const flatLinearRing = pushParseAndPop(
|
||||
undefined,
|
||||
this.RING_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
if (flatLinearRing) {
|
||||
const flatLinearRings =
|
||||
/** @type {Array<Array<number>>} */
|
||||
(objectStack[objectStack.length - 1]);
|
||||
flatLinearRings[0] = flatLinearRing;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @param {*} value Value.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @param {string} [opt_nodeName] Node name.
|
||||
* @return {Element|undefined} Node.
|
||||
* @private
|
||||
*/
|
||||
GEOMETRY_NODE_FACTORY_(value, objectStack, opt_nodeName) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const multiSurface = context['multiSurface'];
|
||||
const surface = context['surface'];
|
||||
const multiCurve = context['multiCurve'];
|
||||
let nodeName;
|
||||
if (!Array.isArray(value)) {
|
||||
nodeName = /** @type {import("../geom/Geometry.js").default} */ (
|
||||
value
|
||||
).getType();
|
||||
if (nodeName === 'MultiPolygon' && multiSurface === true) {
|
||||
nodeName = 'MultiSurface';
|
||||
} else if (nodeName === 'Polygon' && surface === true) {
|
||||
nodeName = 'Surface';
|
||||
} else if (nodeName === 'MultiLineString' && multiCurve === true) {
|
||||
nodeName = 'MultiCurve';
|
||||
}
|
||||
} else {
|
||||
nodeName = 'Envelope';
|
||||
}
|
||||
return createElementNS('http://www.opengis.net/gml', nodeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeFeatureElement(node, feature, objectStack) {
|
||||
const fid = feature.getId();
|
||||
if (fid) {
|
||||
node.setAttribute('fid', /** @type {string} */ (fid));
|
||||
}
|
||||
const context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
const featureNS = context['featureNS'];
|
||||
const geometryName = feature.getGeometryName();
|
||||
if (!context.serializers) {
|
||||
context.serializers = {};
|
||||
context.serializers[featureNS] = {};
|
||||
}
|
||||
const keys = [];
|
||||
const values = [];
|
||||
if (feature.hasProperties()) {
|
||||
const properties = feature.getProperties();
|
||||
for (const key in properties) {
|
||||
const value = properties[key];
|
||||
if (value !== null) {
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
if (
|
||||
key == geometryName ||
|
||||
typeof (/** @type {?} */ (value).getSimplifiedGeometry) ===
|
||||
'function'
|
||||
) {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
this.writeGeometryElement,
|
||||
this
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] =
|
||||
makeChildAppender(writeStringTextNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const item = assign({}, context);
|
||||
item.node = node;
|
||||
pushSerializeAndPop(
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
(item),
|
||||
context.serializers,
|
||||
makeSimpleNodeFactory(undefined, featureNS),
|
||||
values,
|
||||
objectStack,
|
||||
keys
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/LineString.js").default} geometry LineString geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeCurveOrLineString(node, geometry, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const srsName = context['srsName'];
|
||||
if (node.nodeName !== 'LineStringSegment' && srsName) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
if (
|
||||
node.nodeName === 'LineString' ||
|
||||
node.nodeName === 'LineStringSegment'
|
||||
) {
|
||||
const coordinates = this.createCoordinatesNode_(node.namespaceURI);
|
||||
node.appendChild(coordinates);
|
||||
this.writeCoordinates_(coordinates, geometry, objectStack);
|
||||
} else if (node.nodeName === 'Curve') {
|
||||
const segments = createElementNS(node.namespaceURI, 'segments');
|
||||
node.appendChild(segments);
|
||||
this.writeCurveSegments_(segments, geometry, objectStack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/LineString.js").default} line LineString geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeLineStringOrCurveMember(node, line, objectStack) {
|
||||
const child = this.GEOMETRY_NODE_FACTORY_(line, objectStack);
|
||||
if (child) {
|
||||
node.appendChild(child);
|
||||
this.writeCurveOrLineString(child, line, objectStack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/MultiLineString.js").default} geometry MultiLineString geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeMultiCurveOrLineString(node, geometry, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const hasZ = context['hasZ'];
|
||||
const srsName = context['srsName'];
|
||||
const curve = context['curve'];
|
||||
if (srsName) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
const lines = geometry.getLineStrings();
|
||||
pushSerializeAndPop(
|
||||
{node: node, hasZ: hasZ, srsName: srsName, curve: curve},
|
||||
this.LINESTRINGORCURVEMEMBER_SERIALIZERS,
|
||||
this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_,
|
||||
lines,
|
||||
objectStack,
|
||||
undefined,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {import("../geom/Geometry.js").default|import("../extent.js").Extent} geometry Geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeGeometryElement(node, geometry, objectStack) {
|
||||
const context = /** @type {import("./Feature.js").WriteOptions} */ (
|
||||
objectStack[objectStack.length - 1]
|
||||
);
|
||||
const item = assign({}, context);
|
||||
item['node'] = node;
|
||||
let value;
|
||||
if (Array.isArray(geometry)) {
|
||||
value = transformExtentWithOptions(
|
||||
/** @type {import("../extent.js").Extent} */ (geometry),
|
||||
context
|
||||
);
|
||||
} else {
|
||||
value = transformGeometryWithOptions(
|
||||
/** @type {import("../geom/Geometry.js").default} */ (geometry),
|
||||
true,
|
||||
context
|
||||
);
|
||||
}
|
||||
pushSerializeAndPop(
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
(item),
|
||||
this.GEOMETRY_SERIALIZERS,
|
||||
this.GEOMETRY_NODE_FACTORY_,
|
||||
[value],
|
||||
objectStack,
|
||||
undefined,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} namespaceURI XML namespace.
|
||||
* @return {Element} coordinates node.
|
||||
* @private
|
||||
*/
|
||||
createCoordinatesNode_(namespaceURI) {
|
||||
const coordinates = createElementNS(namespaceURI, 'coordinates');
|
||||
coordinates.setAttribute('decimal', '.');
|
||||
coordinates.setAttribute('cs', ',');
|
||||
coordinates.setAttribute('ts', ' ');
|
||||
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {import("../geom/LineString.js").default|import("../geom/LinearRing.js").default} value Geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
writeCoordinates_(node, value, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const hasZ = context['hasZ'];
|
||||
const srsName = context['srsName'];
|
||||
// only 2d for simple features profile
|
||||
const points = value.getCoordinates();
|
||||
const len = points.length;
|
||||
const parts = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
const point = points[i];
|
||||
parts[i] = this.getCoords_(point, srsName, hasZ);
|
||||
}
|
||||
writeStringTextNode(node, parts.join(' '));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/LineString.js").default} line LineString geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
writeCurveSegments_(node, line, objectStack) {
|
||||
const child = createElementNS(node.namespaceURI, 'LineStringSegment');
|
||||
node.appendChild(child);
|
||||
this.writeCurveOrLineString(child, line, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/Polygon.js").default} geometry Polygon geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeSurfaceOrPolygon(node, geometry, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const hasZ = context['hasZ'];
|
||||
const srsName = context['srsName'];
|
||||
if (node.nodeName !== 'PolygonPatch' && srsName) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
if (node.nodeName === 'Polygon' || node.nodeName === 'PolygonPatch') {
|
||||
const rings = geometry.getLinearRings();
|
||||
pushSerializeAndPop(
|
||||
{node: node, hasZ: hasZ, srsName: srsName},
|
||||
this.RING_SERIALIZERS,
|
||||
this.RING_NODE_FACTORY_,
|
||||
rings,
|
||||
objectStack,
|
||||
undefined,
|
||||
this
|
||||
);
|
||||
} else if (node.nodeName === 'Surface') {
|
||||
const patches = createElementNS(node.namespaceURI, 'patches');
|
||||
node.appendChild(patches);
|
||||
this.writeSurfacePatches_(patches, geometry, objectStack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} value Value.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @param {string} [opt_nodeName] Node name.
|
||||
* @return {Node} Node.
|
||||
* @private
|
||||
*/
|
||||
RING_NODE_FACTORY_(value, objectStack, opt_nodeName) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const parentNode = context.node;
|
||||
const exteriorWritten = context['exteriorWritten'];
|
||||
if (exteriorWritten === undefined) {
|
||||
context['exteriorWritten'] = true;
|
||||
}
|
||||
return createElementNS(
|
||||
parentNode.namespaceURI,
|
||||
exteriorWritten !== undefined ? 'innerBoundaryIs' : 'outerBoundaryIs'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/Polygon.js").default} polygon Polygon geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
* @private
|
||||
*/
|
||||
writeSurfacePatches_(node, polygon, objectStack) {
|
||||
const child = createElementNS(node.namespaceURI, 'PolygonPatch');
|
||||
node.appendChild(child);
|
||||
this.writeSurfaceOrPolygon(child, polygon, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/LinearRing.js").default} ring LinearRing geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeRing(node, ring, objectStack) {
|
||||
const linearRing = createElementNS(node.namespaceURI, 'LinearRing');
|
||||
node.appendChild(linearRing);
|
||||
this.writeLinearRing(linearRing, ring, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<number>} point Point geometry.
|
||||
* @param {string} [opt_srsName] Optional srsName
|
||||
* @param {boolean} [opt_hasZ] whether the geometry has a Z coordinate (is 3D) or not.
|
||||
* @return {string} The coords string.
|
||||
* @private
|
||||
*/
|
||||
getCoords_(point, opt_srsName, opt_hasZ) {
|
||||
let axisOrientation = 'enu';
|
||||
if (opt_srsName) {
|
||||
axisOrientation = getProjection(opt_srsName).getAxisOrientation();
|
||||
}
|
||||
let coords =
|
||||
axisOrientation.substr(0, 2) === 'en'
|
||||
? point[0] + ',' + point[1]
|
||||
: point[1] + ',' + point[0];
|
||||
if (opt_hasZ) {
|
||||
// For newly created points, Z can be undefined.
|
||||
const z = point[2] || 0;
|
||||
coords += ',' + z;
|
||||
}
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/Point.js").default} geometry Point geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writePoint(node, geometry, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const hasZ = context['hasZ'];
|
||||
const srsName = context['srsName'];
|
||||
if (srsName) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
const coordinates = this.createCoordinatesNode_(node.namespaceURI);
|
||||
node.appendChild(coordinates);
|
||||
const point = geometry.getCoordinates();
|
||||
const coord = this.getCoords_(point, srsName, hasZ);
|
||||
writeStringTextNode(coordinates, coord);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/MultiPoint.js").default} geometry MultiPoint geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeMultiPoint(node, geometry, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const hasZ = context['hasZ'];
|
||||
const srsName = context['srsName'];
|
||||
if (srsName) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
const points = geometry.getPoints();
|
||||
pushSerializeAndPop(
|
||||
{node: node, hasZ: hasZ, srsName: srsName},
|
||||
this.POINTMEMBER_SERIALIZERS,
|
||||
makeSimpleNodeFactory('pointMember'),
|
||||
points,
|
||||
objectStack,
|
||||
undefined,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/Point.js").default} point Point geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writePointMember(node, point, objectStack) {
|
||||
const child = createElementNS(node.namespaceURI, 'Point');
|
||||
node.appendChild(child);
|
||||
this.writePoint(child, point, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/LinearRing.js").default} geometry LinearRing geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeLinearRing(node, geometry, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const srsName = context['srsName'];
|
||||
if (srsName) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
const coordinates = this.createCoordinatesNode_(node.namespaceURI);
|
||||
node.appendChild(coordinates);
|
||||
this.writeCoordinates_(coordinates, geometry, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../geom/MultiPolygon.js").default} geometry MultiPolygon geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeMultiSurfaceOrPolygon(node, geometry, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const hasZ = context['hasZ'];
|
||||
const srsName = context['srsName'];
|
||||
const surface = context['surface'];
|
||||
if (srsName) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
const polygons = geometry.getPolygons();
|
||||
pushSerializeAndPop(
|
||||
{node: node, hasZ: hasZ, srsName: srsName, surface: surface},
|
||||
this.SURFACEORPOLYGONMEMBER_SERIALIZERS,
|
||||
this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_,
|
||||
polygons,
|
||||
objectStack,
|
||||
undefined,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {import("../geom/Polygon.js").default} polygon Polygon geometry.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeSurfaceOrPolygonMember(node, polygon, objectStack) {
|
||||
const child = this.GEOMETRY_NODE_FACTORY_(polygon, objectStack);
|
||||
if (child) {
|
||||
node.appendChild(child);
|
||||
this.writeSurfaceOrPolygon(child, polygon, objectStack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../extent.js").Extent} extent Extent.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
writeEnvelope(node, extent, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const srsName = context['srsName'];
|
||||
if (srsName) {
|
||||
node.setAttribute('srsName', srsName);
|
||||
}
|
||||
const keys = ['lowerCorner', 'upperCorner'];
|
||||
const values = [extent[0] + ' ' + extent[1], extent[2] + ' ' + extent[3]];
|
||||
pushSerializeAndPop(
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
({node: node}),
|
||||
this.ENVELOPE_SERIALIZERS,
|
||||
OBJECT_PROPERTY_NODE_FACTORY,
|
||||
values,
|
||||
objectStack,
|
||||
keys,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @param {*} value Value.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @param {string} [opt_nodeName] Node name.
|
||||
* @return {Node|undefined} Node.
|
||||
* @private
|
||||
*/
|
||||
MULTIGEOMETRY_MEMBER_NODE_FACTORY_(value, objectStack, opt_nodeName) {
|
||||
const parentNode = objectStack[objectStack.length - 1].node;
|
||||
return createElementNS(
|
||||
'http://www.opengis.net/gml',
|
||||
MULTIGEOMETRY_TO_MEMBER_NODENAME[parentNode.nodeName]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'coordinates': makeReplacer(GML2.prototype.readFlatCoordinates),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML2.prototype.FLAT_LINEAR_RINGS_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'innerBoundaryIs': GML2.prototype.innerBoundaryIsParser,
|
||||
'outerBoundaryIs': GML2.prototype.outerBoundaryIsParser,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML2.prototype.BOX_PARSERS_ = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'coordinates': makeArrayPusher(GML2.prototype.readFlatCoordinates),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML2.prototype.GEOMETRY_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'Point': makeReplacer(GMLBase.prototype.readPoint),
|
||||
'MultiPoint': makeReplacer(GMLBase.prototype.readMultiPoint),
|
||||
'LineString': makeReplacer(GMLBase.prototype.readLineString),
|
||||
'MultiLineString': makeReplacer(GMLBase.prototype.readMultiLineString),
|
||||
'LinearRing': makeReplacer(GMLBase.prototype.readLinearRing),
|
||||
'Polygon': makeReplacer(GMLBase.prototype.readPolygon),
|
||||
'MultiPolygon': makeReplacer(GMLBase.prototype.readMultiPolygon),
|
||||
'Box': makeReplacer(GML2.prototype.readBox),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML2.prototype.GEOMETRY_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'Curve': makeChildAppender(GML2.prototype.writeCurveOrLineString),
|
||||
'MultiCurve': makeChildAppender(GML2.prototype.writeMultiCurveOrLineString),
|
||||
'Point': makeChildAppender(GML2.prototype.writePoint),
|
||||
'MultiPoint': makeChildAppender(GML2.prototype.writeMultiPoint),
|
||||
'LineString': makeChildAppender(GML2.prototype.writeCurveOrLineString),
|
||||
'MultiLineString': makeChildAppender(
|
||||
GML2.prototype.writeMultiCurveOrLineString
|
||||
),
|
||||
'LinearRing': makeChildAppender(GML2.prototype.writeLinearRing),
|
||||
'Polygon': makeChildAppender(GML2.prototype.writeSurfaceOrPolygon),
|
||||
'MultiPolygon': makeChildAppender(
|
||||
GML2.prototype.writeMultiSurfaceOrPolygon
|
||||
),
|
||||
'Surface': makeChildAppender(GML2.prototype.writeSurfaceOrPolygon),
|
||||
'MultiSurface': makeChildAppender(
|
||||
GML2.prototype.writeMultiSurfaceOrPolygon
|
||||
),
|
||||
'Envelope': makeChildAppender(GML2.prototype.writeEnvelope),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML2.prototype.LINESTRINGORCURVEMEMBER_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'lineStringMember': makeChildAppender(
|
||||
GML2.prototype.writeLineStringOrCurveMember
|
||||
),
|
||||
'curveMember': makeChildAppender(
|
||||
GML2.prototype.writeLineStringOrCurveMember
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML2.prototype.RING_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'outerBoundaryIs': makeChildAppender(GML2.prototype.writeRing),
|
||||
'innerBoundaryIs': makeChildAppender(GML2.prototype.writeRing),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML2.prototype.POINTMEMBER_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'pointMember': makeChildAppender(GML2.prototype.writePointMember),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML2.prototype.SURFACEORPOLYGONMEMBER_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'surfaceMember': makeChildAppender(
|
||||
GML2.prototype.writeSurfaceOrPolygonMember
|
||||
),
|
||||
'polygonMember': makeChildAppender(
|
||||
GML2.prototype.writeSurfaceOrPolygonMember
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML2.prototype.ENVELOPE_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'lowerCorner': makeChildAppender(writeStringTextNode),
|
||||
'upperCorner': makeChildAppender(writeStringTextNode),
|
||||
},
|
||||
};
|
||||
|
||||
export default GML2;
|
||||
1291
node_modules/ol/src/format/GML3.js
generated
vendored
Normal file
1291
node_modules/ol/src/format/GML3.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
344
node_modules/ol/src/format/GML32.js
generated
vendored
Normal file
344
node_modules/ol/src/format/GML32.js
generated
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
/**
|
||||
* @module ol/format/GML32
|
||||
*/
|
||||
import GML2 from './GML2.js';
|
||||
import GML3 from './GML3.js';
|
||||
import GMLBase from './GMLBase.js';
|
||||
import {
|
||||
makeArrayExtender,
|
||||
makeArrayPusher,
|
||||
makeChildAppender,
|
||||
makeReplacer,
|
||||
} from '../xml.js';
|
||||
import {writeStringTextNode} from '../format/xsd.js';
|
||||
|
||||
/**
|
||||
* @classdesc Feature format for reading and writing data in the GML format
|
||||
* version 3.2.1.
|
||||
* @api
|
||||
*/
|
||||
class GML32 extends GML3 {
|
||||
/**
|
||||
* @param {import("./GMLBase.js").Options} [opt_options] Optional configuration object.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = /** @type {import("./GMLBase.js").Options} */ (
|
||||
opt_options ? opt_options : {}
|
||||
);
|
||||
|
||||
super(options);
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.schemaLocation = options.schemaLocation
|
||||
? options.schemaLocation
|
||||
: this.namespace + ' http://schemas.opengis.net/gml/3.2.1/gml.xsd';
|
||||
}
|
||||
}
|
||||
|
||||
GML32.prototype.namespace = 'http://www.opengis.net/gml/3.2';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'pos': makeReplacer(GML3.prototype.readFlatPos),
|
||||
'posList': makeReplacer(GML3.prototype.readFlatPosList),
|
||||
'coordinates': makeReplacer(GML2.prototype.readFlatCoordinates),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.FLAT_LINEAR_RINGS_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'interior': GML3.prototype.interiorParser,
|
||||
'exterior': GML3.prototype.exteriorParser,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.GEOMETRY_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Point': makeReplacer(GMLBase.prototype.readPoint),
|
||||
'MultiPoint': makeReplacer(GMLBase.prototype.readMultiPoint),
|
||||
'LineString': makeReplacer(GMLBase.prototype.readLineString),
|
||||
'MultiLineString': makeReplacer(GMLBase.prototype.readMultiLineString),
|
||||
'LinearRing': makeReplacer(GMLBase.prototype.readLinearRing),
|
||||
'Polygon': makeReplacer(GMLBase.prototype.readPolygon),
|
||||
'MultiPolygon': makeReplacer(GMLBase.prototype.readMultiPolygon),
|
||||
'Surface': makeReplacer(GML32.prototype.readSurface),
|
||||
'MultiSurface': makeReplacer(GML3.prototype.readMultiSurface),
|
||||
'Curve': makeReplacer(GML32.prototype.readCurve),
|
||||
'MultiCurve': makeReplacer(GML3.prototype.readMultiCurve),
|
||||
'Envelope': makeReplacer(GML32.prototype.readEnvelope),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.MULTICURVE_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'curveMember': makeArrayPusher(GML3.prototype.curveMemberParser),
|
||||
'curveMembers': makeArrayPusher(GML3.prototype.curveMemberParser),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.MULTISURFACE_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'surfaceMember': makeArrayPusher(GML3.prototype.surfaceMemberParser),
|
||||
'surfaceMembers': makeArrayPusher(GML3.prototype.surfaceMemberParser),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.CURVEMEMBER_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'LineString': makeArrayPusher(GMLBase.prototype.readLineString),
|
||||
'Curve': makeArrayPusher(GML3.prototype.readCurve),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.SURFACEMEMBER_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Polygon': makeArrayPusher(GMLBase.prototype.readPolygon),
|
||||
'Surface': makeArrayPusher(GML3.prototype.readSurface),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.SURFACE_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'patches': makeReplacer(GML3.prototype.readPatch),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.CURVE_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'segments': makeReplacer(GML3.prototype.readSegment),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.ENVELOPE_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'lowerCorner': makeArrayPusher(GML3.prototype.readFlatPosList),
|
||||
'upperCorner': makeArrayPusher(GML3.prototype.readFlatPosList),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.PATCHES_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'PolygonPatch': makeReplacer(GML3.prototype.readPolygonPatch),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.SEGMENTS_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'LineStringSegment': makeArrayExtender(
|
||||
GML3.prototype.readLineStringSegment
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.MULTIPOINT_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'pointMember': makeArrayPusher(GMLBase.prototype.pointMemberParser),
|
||||
'pointMembers': makeArrayPusher(GMLBase.prototype.pointMemberParser),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.MULTILINESTRING_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'lineStringMember': makeArrayPusher(
|
||||
GMLBase.prototype.lineStringMemberParser
|
||||
),
|
||||
'lineStringMembers': makeArrayPusher(
|
||||
GMLBase.prototype.lineStringMemberParser
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.MULTIPOLYGON_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'polygonMember': makeArrayPusher(GMLBase.prototype.polygonMemberParser),
|
||||
'polygonMembers': makeArrayPusher(GMLBase.prototype.polygonMemberParser),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.POINTMEMBER_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Point': makeArrayPusher(GMLBase.prototype.readFlatCoordinatesFromNode),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.LINESTRINGMEMBER_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'LineString': makeArrayPusher(GMLBase.prototype.readLineString),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.POLYGONMEMBER_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Polygon': makeArrayPusher(GMLBase.prototype.readPolygon),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GML32.prototype.RING_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'LinearRing': makeReplacer(GMLBase.prototype.readFlatLinearRing),
|
||||
'Ring': makeReplacer(GML32.prototype.readFlatCurveRing),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML32.prototype.RING_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'exterior': makeChildAppender(GML3.prototype.writeRing),
|
||||
'interior': makeChildAppender(GML3.prototype.writeRing),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML32.prototype.ENVELOPE_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'lowerCorner': makeChildAppender(writeStringTextNode),
|
||||
'upperCorner': makeChildAppender(writeStringTextNode),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML32.prototype.SURFACEORPOLYGONMEMBER_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'surfaceMember': makeChildAppender(
|
||||
GML3.prototype.writeSurfaceOrPolygonMember
|
||||
),
|
||||
'polygonMember': makeChildAppender(
|
||||
GML3.prototype.writeSurfaceOrPolygonMember
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML32.prototype.POINTMEMBER_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'pointMember': makeChildAppender(GML3.prototype.writePointMember),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML32.prototype.LINESTRINGORCURVEMEMBER_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'lineStringMember': makeChildAppender(
|
||||
GML3.prototype.writeLineStringOrCurveMember
|
||||
),
|
||||
'curveMember': makeChildAppender(
|
||||
GML3.prototype.writeLineStringOrCurveMember
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
GML32.prototype.GEOMETRY_SERIALIZERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Curve': makeChildAppender(GML3.prototype.writeCurveOrLineString),
|
||||
'MultiCurve': makeChildAppender(GML3.prototype.writeMultiCurveOrLineString),
|
||||
'Point': makeChildAppender(GML32.prototype.writePoint),
|
||||
'MultiPoint': makeChildAppender(GML3.prototype.writeMultiPoint),
|
||||
'LineString': makeChildAppender(GML3.prototype.writeCurveOrLineString),
|
||||
'MultiLineString': makeChildAppender(
|
||||
GML3.prototype.writeMultiCurveOrLineString
|
||||
),
|
||||
'LinearRing': makeChildAppender(GML3.prototype.writeLinearRing),
|
||||
'Polygon': makeChildAppender(GML3.prototype.writeSurfaceOrPolygon),
|
||||
'MultiPolygon': makeChildAppender(
|
||||
GML3.prototype.writeMultiSurfaceOrPolygon
|
||||
),
|
||||
'Surface': makeChildAppender(GML3.prototype.writeSurfaceOrPolygon),
|
||||
'MultiSurface': makeChildAppender(
|
||||
GML3.prototype.writeMultiSurfaceOrPolygon
|
||||
),
|
||||
'Envelope': makeChildAppender(GML3.prototype.writeEnvelope),
|
||||
},
|
||||
};
|
||||
|
||||
export default GML32;
|
||||
696
node_modules/ol/src/format/GMLBase.js
generated
vendored
Normal file
696
node_modules/ol/src/format/GMLBase.js
generated
vendored
Normal file
@@ -0,0 +1,696 @@
|
||||
/**
|
||||
* @module ol/format/GMLBase
|
||||
*/
|
||||
// FIXME Envelopes should not be treated as geometries! readEnvelope_ is part
|
||||
// of GEOMETRY_PARSERS_ and methods using GEOMETRY_PARSERS_ do not expect
|
||||
// envelopes/extents, only geometries!
|
||||
import Feature from '../Feature.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import LinearRing from '../geom/LinearRing.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import MultiPoint from '../geom/MultiPoint.js';
|
||||
import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import XMLFeature from './XMLFeature.js';
|
||||
import {assign} from '../obj.js';
|
||||
import {extend} from '../array.js';
|
||||
import {
|
||||
getAllTextContent,
|
||||
getAttributeNS,
|
||||
makeArrayPusher,
|
||||
makeReplacer,
|
||||
parseNode,
|
||||
pushParseAndPop,
|
||||
} from '../xml.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {
|
||||
transformExtentWithOptions,
|
||||
transformGeometryWithOptions,
|
||||
} from './Feature.js';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
export const GMLNS = 'http://www.opengis.net/gml';
|
||||
|
||||
/**
|
||||
* A regular expression that matches if a string only contains whitespace
|
||||
* characters. It will e.g. match `''`, `' '`, `'\n'` etc. The non-breaking
|
||||
* space (0xa0) is explicitly included as IE doesn't include it in its
|
||||
* definition of `\s`.
|
||||
*
|
||||
* Information from `goog.string.isEmptyOrWhitespace`: https://github.com/google/closure-library/blob/e877b1e/closure/goog/string/string.js#L156-L160
|
||||
*
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
*/
|
||||
const ONLY_WHITESPACE_RE = /^[\s\xa0]*$/;
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {Object<string, string>|string} [featureNS] Feature
|
||||
* namespace. If not defined will be derived from GML. If multiple
|
||||
* feature types have been configured which come from different feature
|
||||
* namespaces, this will be an object with the keys being the prefixes used
|
||||
* in the entries of featureType array. The values of the object will be the
|
||||
* feature namespaces themselves. So for instance there might be a featureType
|
||||
* item `topp:states` in the `featureType` array and then there will be a key
|
||||
* `topp` in the featureNS object with value `http://www.openplans.org/topp`.
|
||||
* @property {Array<string>|string} [featureType] Feature type(s) to parse.
|
||||
* If multiple feature types need to be configured
|
||||
* which come from different feature namespaces, `featureNS` will be an object
|
||||
* with the keys being the prefixes used in the entries of featureType array.
|
||||
* The values of the object will be the feature namespaces themselves.
|
||||
* So for instance there might be a featureType item `topp:states` and then
|
||||
* there will be a key named `topp` in the featureNS object with value
|
||||
* `http://www.openplans.org/topp`.
|
||||
* @property {string} srsName srsName to use when writing geometries.
|
||||
* @property {boolean} [surface=false] Write gml:Surface instead of gml:Polygon
|
||||
* elements. This also affects the elements in multi-part geometries.
|
||||
* @property {boolean} [curve=false] Write gml:Curve instead of gml:LineString
|
||||
* elements. This also affects the elements in multi-part geometries.
|
||||
* @property {boolean} [multiCurve=true] Write gml:MultiCurve instead of gml:MultiLineString.
|
||||
* Since the latter is deprecated in GML 3.
|
||||
* @property {boolean} [multiSurface=true] Write gml:multiSurface instead of
|
||||
* gml:MultiPolygon. Since the latter is deprecated in GML 3.
|
||||
* @property {string} [schemaLocation] Optional schemaLocation to use when
|
||||
* writing out the GML, this will override the default provided.
|
||||
* @property {boolean} [hasZ=false] If coordinates have a Z value.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Feature base format for reading and writing data in the GML format.
|
||||
* This class cannot be instantiated, it contains only base content that
|
||||
* is shared with versioned format classes GML2 and GML3.
|
||||
*
|
||||
* @abstract
|
||||
* @api
|
||||
*/
|
||||
class GMLBase extends XMLFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Optional configuration object.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = /** @type {Options} */ (opt_options ? opt_options : {});
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Array<string>|string|undefined}
|
||||
*/
|
||||
this.featureType = options.featureType;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {Object<string, string>|string|undefined}
|
||||
*/
|
||||
this.featureNS = options.featureNS;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {string}
|
||||
*/
|
||||
this.srsName = options.srsName;
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {string}
|
||||
*/
|
||||
this.schemaLocation = '';
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, Object>>}
|
||||
*/
|
||||
this.FEATURE_COLLECTION_PARSERS = {};
|
||||
this.FEATURE_COLLECTION_PARSERS[this.namespace] = {
|
||||
'featureMember': makeArrayPusher(this.readFeaturesInternal),
|
||||
'featureMembers': makeReplacer(this.readFeaturesInternal),
|
||||
};
|
||||
|
||||
this.supportedMediaTypes = ['application/gml+xml'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Array<Feature> | undefined} Features.
|
||||
*/
|
||||
readFeaturesInternal(node, objectStack) {
|
||||
const localName = node.localName;
|
||||
let features = null;
|
||||
if (localName == 'FeatureCollection') {
|
||||
features = pushParseAndPop(
|
||||
[],
|
||||
this.FEATURE_COLLECTION_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
} else if (
|
||||
localName == 'featureMembers' ||
|
||||
localName == 'featureMember' ||
|
||||
localName == 'member'
|
||||
) {
|
||||
const context = objectStack[0];
|
||||
let featureType = context['featureType'];
|
||||
let featureNS = context['featureNS'];
|
||||
const prefix = 'p';
|
||||
const defaultPrefix = 'p0';
|
||||
if (!featureType && node.childNodes) {
|
||||
(featureType = []), (featureNS = {});
|
||||
for (let i = 0, ii = node.childNodes.length; i < ii; ++i) {
|
||||
const child = /** @type {Element} */ (node.childNodes[i]);
|
||||
if (child.nodeType === 1) {
|
||||
const ft = child.nodeName.split(':').pop();
|
||||
if (featureType.indexOf(ft) === -1) {
|
||||
let key = '';
|
||||
let count = 0;
|
||||
const uri = child.namespaceURI;
|
||||
for (const candidate in featureNS) {
|
||||
if (featureNS[candidate] === uri) {
|
||||
key = candidate;
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
}
|
||||
if (!key) {
|
||||
key = prefix + count;
|
||||
featureNS[key] = uri;
|
||||
}
|
||||
featureType.push(key + ':' + ft);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (localName != 'featureMember') {
|
||||
// recheck featureType for each featureMember
|
||||
context['featureType'] = featureType;
|
||||
context['featureNS'] = featureNS;
|
||||
}
|
||||
}
|
||||
if (typeof featureNS === 'string') {
|
||||
const ns = featureNS;
|
||||
featureNS = {};
|
||||
featureNS[defaultPrefix] = ns;
|
||||
}
|
||||
/** @type {Object<string, Object<string, import("../xml.js").Parser>>} */
|
||||
const parsersNS = {};
|
||||
const featureTypes = Array.isArray(featureType)
|
||||
? featureType
|
||||
: [featureType];
|
||||
for (const p in featureNS) {
|
||||
/** @type {Object<string, import("../xml.js").Parser>} */
|
||||
const parsers = {};
|
||||
for (let i = 0, ii = featureTypes.length; i < ii; ++i) {
|
||||
const featurePrefix =
|
||||
featureTypes[i].indexOf(':') === -1
|
||||
? defaultPrefix
|
||||
: featureTypes[i].split(':')[0];
|
||||
if (featurePrefix === p) {
|
||||
parsers[featureTypes[i].split(':').pop()] =
|
||||
localName == 'featureMembers'
|
||||
? makeArrayPusher(this.readFeatureElement, this)
|
||||
: makeReplacer(this.readFeatureElement, this);
|
||||
}
|
||||
}
|
||||
parsersNS[featureNS[p]] = parsers;
|
||||
}
|
||||
if (localName == 'featureMember' || localName == 'member') {
|
||||
features = pushParseAndPop(undefined, parsersNS, node, objectStack);
|
||||
} else {
|
||||
features = pushParseAndPop([], parsersNS, node, objectStack);
|
||||
}
|
||||
}
|
||||
if (features === null) {
|
||||
features = [];
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {import("../geom/Geometry.js").default|import("../extent.js").Extent|undefined} Geometry.
|
||||
*/
|
||||
readGeometryOrExtent(node, objectStack) {
|
||||
const context = /** @type {Object} */ (objectStack[0]);
|
||||
context['srsName'] = node.firstElementChild.getAttribute('srsName');
|
||||
context['srsDimension'] =
|
||||
node.firstElementChild.getAttribute('srsDimension');
|
||||
return pushParseAndPop(
|
||||
null,
|
||||
this.GEOMETRY_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {import("../extent.js").Extent|undefined} Geometry.
|
||||
*/
|
||||
readExtentElement(node, objectStack) {
|
||||
const context = /** @type {Object} */ (objectStack[0]);
|
||||
const extent = /** @type {import("../extent.js").Extent} */ (
|
||||
this.readGeometryOrExtent(node, objectStack)
|
||||
);
|
||||
return extent ? transformExtentWithOptions(extent, context) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {import("../geom/Geometry.js").default|undefined} Geometry.
|
||||
*/
|
||||
readGeometryElement(node, objectStack) {
|
||||
const context = /** @type {Object} */ (objectStack[0]);
|
||||
const geometry = /** @type {import("../geom/Geometry.js").default} */ (
|
||||
this.readGeometryOrExtent(node, objectStack)
|
||||
);
|
||||
return geometry
|
||||
? transformGeometryWithOptions(geometry, false, context)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @param {boolean} asFeature whether result should be wrapped as a feature.
|
||||
* @return {Feature|Object} Feature
|
||||
*/
|
||||
readFeatureElementInternal(node, objectStack, asFeature) {
|
||||
let geometryName;
|
||||
const values = {};
|
||||
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
|
||||
let value;
|
||||
const localName = n.localName;
|
||||
// first, check if it is simple attribute
|
||||
if (
|
||||
n.childNodes.length === 0 ||
|
||||
(n.childNodes.length === 1 &&
|
||||
(n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))
|
||||
) {
|
||||
value = getAllTextContent(n, false);
|
||||
if (ONLY_WHITESPACE_RE.test(value)) {
|
||||
value = undefined;
|
||||
}
|
||||
} else {
|
||||
if (asFeature) {
|
||||
//if feature, try it as a geometry or extent
|
||||
value =
|
||||
localName === 'boundedBy'
|
||||
? this.readExtentElement(n, objectStack)
|
||||
: this.readGeometryElement(n, objectStack);
|
||||
}
|
||||
if (!value) {
|
||||
//if not a geometry or not a feature, treat it as a complex attribute
|
||||
value = this.readFeatureElementInternal(n, objectStack, false);
|
||||
} else if (localName !== 'boundedBy') {
|
||||
// boundedBy is an extent and must not be considered as a geometry
|
||||
geometryName = localName;
|
||||
}
|
||||
}
|
||||
|
||||
const len = n.attributes.length;
|
||||
if (len > 0) {
|
||||
value = {_content_: value};
|
||||
for (let i = 0; i < len; i++) {
|
||||
const attName = n.attributes[i].name;
|
||||
value[attName] = n.attributes[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
if (values[localName]) {
|
||||
if (!(values[localName] instanceof Array)) {
|
||||
values[localName] = [values[localName]];
|
||||
}
|
||||
values[localName].push(value);
|
||||
} else {
|
||||
values[localName] = value;
|
||||
}
|
||||
}
|
||||
if (!asFeature) {
|
||||
return values;
|
||||
} else {
|
||||
const feature = new Feature(values);
|
||||
if (geometryName) {
|
||||
feature.setGeometryName(geometryName);
|
||||
}
|
||||
const fid =
|
||||
node.getAttribute('fid') || getAttributeNS(node, this.namespace, 'id');
|
||||
if (fid) {
|
||||
feature.setId(fid);
|
||||
}
|
||||
return feature;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Feature} Feature.
|
||||
*/
|
||||
readFeatureElement(node, objectStack) {
|
||||
return this.readFeatureElementInternal(node, objectStack, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Point|undefined} Point.
|
||||
*/
|
||||
readPoint(node, objectStack) {
|
||||
const flatCoordinates = this.readFlatCoordinatesFromNode(node, objectStack);
|
||||
if (flatCoordinates) {
|
||||
return new Point(flatCoordinates, GeometryLayout.XYZ);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {MultiPoint|undefined} MultiPoint.
|
||||
*/
|
||||
readMultiPoint(node, objectStack) {
|
||||
/** @type {Array<Array<number>>} */
|
||||
const coordinates = pushParseAndPop(
|
||||
[],
|
||||
this.MULTIPOINT_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
if (coordinates) {
|
||||
return new MultiPoint(coordinates);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {MultiLineString|undefined} MultiLineString.
|
||||
*/
|
||||
readMultiLineString(node, objectStack) {
|
||||
/** @type {Array<LineString>} */
|
||||
const lineStrings = pushParseAndPop(
|
||||
[],
|
||||
this.MULTILINESTRING_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
if (lineStrings) {
|
||||
return new MultiLineString(lineStrings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {MultiPolygon|undefined} MultiPolygon.
|
||||
*/
|
||||
readMultiPolygon(node, objectStack) {
|
||||
/** @type {Array<Polygon>} */
|
||||
const polygons = pushParseAndPop(
|
||||
[],
|
||||
this.MULTIPOLYGON_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
if (polygons) {
|
||||
return new MultiPolygon(polygons);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
pointMemberParser(node, objectStack) {
|
||||
parseNode(this.POINTMEMBER_PARSERS, node, objectStack, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
lineStringMemberParser(node, objectStack) {
|
||||
parseNode(this.LINESTRINGMEMBER_PARSERS, node, objectStack, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
polygonMemberParser(node, objectStack) {
|
||||
parseNode(this.POLYGONMEMBER_PARSERS, node, objectStack, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {LineString|undefined} LineString.
|
||||
*/
|
||||
readLineString(node, objectStack) {
|
||||
const flatCoordinates = this.readFlatCoordinatesFromNode(node, objectStack);
|
||||
if (flatCoordinates) {
|
||||
const lineString = new LineString(flatCoordinates, GeometryLayout.XYZ);
|
||||
return lineString;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Array<number>|undefined} LinearRing flat coordinates.
|
||||
*/
|
||||
readFlatLinearRing(node, objectStack) {
|
||||
const ring = pushParseAndPop(
|
||||
null,
|
||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
if (ring) {
|
||||
return ring;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {LinearRing|undefined} LinearRing.
|
||||
*/
|
||||
readLinearRing(node, objectStack) {
|
||||
const flatCoordinates = this.readFlatCoordinatesFromNode(node, objectStack);
|
||||
if (flatCoordinates) {
|
||||
return new LinearRing(flatCoordinates, GeometryLayout.XYZ);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Polygon|undefined} Polygon.
|
||||
*/
|
||||
readPolygon(node, objectStack) {
|
||||
/** @type {Array<Array<number>>} */
|
||||
const flatLinearRings = pushParseAndPop(
|
||||
[null],
|
||||
this.FLAT_LINEAR_RINGS_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
if (flatLinearRings && flatLinearRings[0]) {
|
||||
const flatCoordinates = flatLinearRings[0];
|
||||
const ends = [flatCoordinates.length];
|
||||
let i, ii;
|
||||
for (i = 1, ii = flatLinearRings.length; i < ii; ++i) {
|
||||
extend(flatCoordinates, flatLinearRings[i]);
|
||||
ends.push(flatCoordinates.length);
|
||||
}
|
||||
return new Polygon(flatCoordinates, GeometryLayout.XYZ, ends);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Array<number>} Flat coordinates.
|
||||
*/
|
||||
readFlatCoordinatesFromNode(node, objectStack) {
|
||||
return pushParseAndPop(
|
||||
null,
|
||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS,
|
||||
node,
|
||||
objectStack,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromNode(node, opt_options) {
|
||||
const geometry = this.readGeometryElement(node, [
|
||||
this.getReadOptions(node, opt_options ? opt_options : {}),
|
||||
]);
|
||||
return geometry ? geometry : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromNode(node, opt_options) {
|
||||
const options = {
|
||||
featureType: this.featureType,
|
||||
featureNS: this.featureNS,
|
||||
};
|
||||
if (opt_options) {
|
||||
assign(options, this.getReadOptions(node, opt_options));
|
||||
}
|
||||
const features = this.readFeaturesInternal(node, [options]);
|
||||
return features || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjectionFromNode(node) {
|
||||
return getProjection(
|
||||
this.srsName
|
||||
? this.srsName
|
||||
: node.firstElementChild.getAttribute('srsName')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
GMLBase.prototype.namespace = GMLNS;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.FLAT_LINEAR_RINGS_PARSERS = {
|
||||
'http://www.opengis.net/gml': {},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
|
||||
'http://www.opengis.net/gml': {},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.GEOMETRY_PARSERS = {
|
||||
'http://www.opengis.net/gml': {},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.MULTIPOINT_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'pointMember': makeArrayPusher(GMLBase.prototype.pointMemberParser),
|
||||
'pointMembers': makeArrayPusher(GMLBase.prototype.pointMemberParser),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.MULTILINESTRING_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'lineStringMember': makeArrayPusher(
|
||||
GMLBase.prototype.lineStringMemberParser
|
||||
),
|
||||
'lineStringMembers': makeArrayPusher(
|
||||
GMLBase.prototype.lineStringMemberParser
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.MULTIPOLYGON_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'polygonMember': makeArrayPusher(GMLBase.prototype.polygonMemberParser),
|
||||
'polygonMembers': makeArrayPusher(GMLBase.prototype.polygonMemberParser),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.POINTMEMBER_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'Point': makeArrayPusher(GMLBase.prototype.readFlatCoordinatesFromNode),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.LINESTRINGMEMBER_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'LineString': makeArrayPusher(GMLBase.prototype.readLineString),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.POLYGONMEMBER_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'Polygon': makeArrayPusher(GMLBase.prototype.readPolygon),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
GMLBase.prototype.RING_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'LinearRing': makeReplacer(GMLBase.prototype.readFlatLinearRing),
|
||||
},
|
||||
};
|
||||
|
||||
export default GMLBase;
|
||||
943
node_modules/ol/src/format/GPX.js
generated
vendored
Normal file
943
node_modules/ol/src/format/GPX.js
generated
vendored
Normal file
@@ -0,0 +1,943 @@
|
||||
/**
|
||||
* @module ol/format/GPX
|
||||
*/
|
||||
import Feature from '../Feature.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import XMLFeature from './XMLFeature.js';
|
||||
import {
|
||||
OBJECT_PROPERTY_NODE_FACTORY,
|
||||
XML_SCHEMA_INSTANCE_URI,
|
||||
createElementNS,
|
||||
makeArrayPusher,
|
||||
makeArraySerializer,
|
||||
makeChildAppender,
|
||||
makeObjectPropertySetter,
|
||||
makeSequence,
|
||||
makeSimpleNodeFactory,
|
||||
makeStructureNS,
|
||||
parseNode,
|
||||
pushParseAndPop,
|
||||
pushSerializeAndPop,
|
||||
} from '../xml.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {includes} from '../array.js';
|
||||
import {
|
||||
readDateTime,
|
||||
readDecimal,
|
||||
readPositiveInteger,
|
||||
readString,
|
||||
writeDateTimeTextNode,
|
||||
writeDecimalTextNode,
|
||||
writeNonNegativeIntegerTextNode,
|
||||
writeStringTextNode,
|
||||
} from './xsd.js';
|
||||
import {transformGeometryWithOptions} from './Feature.js';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array<null|string>}
|
||||
*/
|
||||
const NAMESPACE_URIS = [
|
||||
null,
|
||||
'http://www.topografix.com/GPX/1/0',
|
||||
'http://www.topografix.com/GPX/1/1',
|
||||
];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
const SCHEMA_LOCATION =
|
||||
'http://www.topografix.com/GPX/1/1 ' +
|
||||
'http://www.topografix.com/GPX/1/1/gpx.xsd';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, function(Node, Array<*>): (Feature|undefined)>}
|
||||
*/
|
||||
const FEATURE_READER = {
|
||||
'rte': readRte,
|
||||
'trk': readTrk,
|
||||
'wpt': readWpt,
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const GPX_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'rte': makeArrayPusher(readRte),
|
||||
'trk': makeArrayPusher(readTrk),
|
||||
'wpt': makeArrayPusher(readWpt),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const LINK_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'text': makeObjectPropertySetter(readString, 'linkText'),
|
||||
'type': makeObjectPropertySetter(readString, 'linkType'),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const GPX_SERIALIZERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'rte': makeChildAppender(writeRte),
|
||||
'trk': makeChildAppender(writeTrk),
|
||||
'wpt': makeChildAppender(writeWpt),
|
||||
});
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {function(Feature, Node):void} [readExtensions] Callback function
|
||||
* to process `extensions` nodes. To prevent memory leaks, this callback function must
|
||||
* not store any references to the node. Note that the `extensions`
|
||||
* node is not allowed in GPX 1.0. Moreover, only `extensions`
|
||||
* nodes from `wpt`, `rte` and `trk` can be processed, as those are
|
||||
* directly mapped to a feature.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} LayoutOptions
|
||||
* @property {boolean} [hasZ] HasZ.
|
||||
* @property {boolean} [hasM] HasM.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the GPX format.
|
||||
*
|
||||
* Note that {@link module:ol/format/GPX~GPX#readFeature} only reads the first
|
||||
* feature of the source.
|
||||
*
|
||||
* When reading, routes (`<rte>`) are converted into LineString geometries, and
|
||||
* tracks (`<trk>`) into MultiLineString. Any properties on route and track
|
||||
* waypoints are ignored.
|
||||
*
|
||||
* When writing, LineString geometries are output as routes (`<rte>`), and
|
||||
* MultiLineString as tracks (`<trk>`).
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class GPX extends XMLFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.dataProjection = getProjection('EPSG:4326');
|
||||
|
||||
/**
|
||||
* @type {function(Feature, Node): void|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.readExtensions_ = options.readExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<Feature>} features List of features.
|
||||
* @private
|
||||
*/
|
||||
handleReadExtensions_(features) {
|
||||
if (!features) {
|
||||
features = [];
|
||||
}
|
||||
for (let i = 0, ii = features.length; i < ii; ++i) {
|
||||
const feature = features[i];
|
||||
if (this.readExtensions_) {
|
||||
const extensionsNode = feature.get('extensionsNode_') || null;
|
||||
this.readExtensions_(feature, extensionsNode);
|
||||
}
|
||||
feature.set('extensionsNode_', undefined);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromNode(node, opt_options) {
|
||||
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
|
||||
return null;
|
||||
}
|
||||
const featureReader = FEATURE_READER[node.localName];
|
||||
if (!featureReader) {
|
||||
return null;
|
||||
}
|
||||
const feature = featureReader(node, [
|
||||
this.getReadOptions(node, opt_options),
|
||||
]);
|
||||
if (!feature) {
|
||||
return null;
|
||||
}
|
||||
this.handleReadExtensions_([feature]);
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromNode(node, opt_options) {
|
||||
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
|
||||
return [];
|
||||
}
|
||||
if (node.localName == 'gpx') {
|
||||
/** @type {Array<Feature>} */
|
||||
const features = pushParseAndPop([], GPX_PARSERS, node, [
|
||||
this.getReadOptions(node, opt_options),
|
||||
]);
|
||||
if (features) {
|
||||
this.handleReadExtensions_(features);
|
||||
return features;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features in the GPX format as an XML node.
|
||||
* LineString geometries are output as routes (`<rte>`), and MultiLineString
|
||||
* as tracks (`<trk>`).
|
||||
*
|
||||
* @param {Array<Feature>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Options.
|
||||
* @return {Node} Node.
|
||||
* @api
|
||||
*/
|
||||
writeFeaturesNode(features, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
//FIXME Serialize metadata
|
||||
const gpx = createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
|
||||
const xmlnsUri = 'http://www.w3.org/2000/xmlns/';
|
||||
gpx.setAttributeNS(xmlnsUri, 'xmlns:xsi', XML_SCHEMA_INSTANCE_URI);
|
||||
gpx.setAttributeNS(
|
||||
XML_SCHEMA_INSTANCE_URI,
|
||||
'xsi:schemaLocation',
|
||||
SCHEMA_LOCATION
|
||||
);
|
||||
gpx.setAttribute('version', '1.1');
|
||||
gpx.setAttribute('creator', 'OpenLayers');
|
||||
|
||||
pushSerializeAndPop(
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
({node: gpx}),
|
||||
GPX_SERIALIZERS,
|
||||
GPX_NODE_FACTORY,
|
||||
features,
|
||||
[opt_options]
|
||||
);
|
||||
return gpx;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const RTE_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'name': makeObjectPropertySetter(readString),
|
||||
'cmt': makeObjectPropertySetter(readString),
|
||||
'desc': makeObjectPropertySetter(readString),
|
||||
'src': makeObjectPropertySetter(readString),
|
||||
'link': parseLink,
|
||||
'number': makeObjectPropertySetter(readPositiveInteger),
|
||||
'extensions': parseExtensions,
|
||||
'type': makeObjectPropertySetter(readString),
|
||||
'rtept': parseRtePt,
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const RTEPT_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'ele': makeObjectPropertySetter(readDecimal),
|
||||
'time': makeObjectPropertySetter(readDateTime),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TRK_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'name': makeObjectPropertySetter(readString),
|
||||
'cmt': makeObjectPropertySetter(readString),
|
||||
'desc': makeObjectPropertySetter(readString),
|
||||
'src': makeObjectPropertySetter(readString),
|
||||
'link': parseLink,
|
||||
'number': makeObjectPropertySetter(readPositiveInteger),
|
||||
'type': makeObjectPropertySetter(readString),
|
||||
'extensions': parseExtensions,
|
||||
'trkseg': parseTrkSeg,
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TRKSEG_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'trkpt': parseTrkPt,
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TRKPT_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'ele': makeObjectPropertySetter(readDecimal),
|
||||
'time': makeObjectPropertySetter(readDateTime),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const WPT_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'ele': makeObjectPropertySetter(readDecimal),
|
||||
'time': makeObjectPropertySetter(readDateTime),
|
||||
'magvar': makeObjectPropertySetter(readDecimal),
|
||||
'geoidheight': makeObjectPropertySetter(readDecimal),
|
||||
'name': makeObjectPropertySetter(readString),
|
||||
'cmt': makeObjectPropertySetter(readString),
|
||||
'desc': makeObjectPropertySetter(readString),
|
||||
'src': makeObjectPropertySetter(readString),
|
||||
'link': parseLink,
|
||||
'sym': makeObjectPropertySetter(readString),
|
||||
'type': makeObjectPropertySetter(readString),
|
||||
'fix': makeObjectPropertySetter(readString),
|
||||
'sat': makeObjectPropertySetter(readPositiveInteger),
|
||||
'hdop': makeObjectPropertySetter(readDecimal),
|
||||
'vdop': makeObjectPropertySetter(readDecimal),
|
||||
'pdop': makeObjectPropertySetter(readDecimal),
|
||||
'ageofdgpsdata': makeObjectPropertySetter(readDecimal),
|
||||
'dgpsid': makeObjectPropertySetter(readPositiveInteger),
|
||||
'extensions': parseExtensions,
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
const LINK_SEQUENCE = ['text', 'type'];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const LINK_SERIALIZERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'text': makeChildAppender(writeStringTextNode),
|
||||
'type': makeChildAppender(writeStringTextNode),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Array<string>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const RTE_SEQUENCE = makeStructureNS(NAMESPACE_URIS, [
|
||||
'name',
|
||||
'cmt',
|
||||
'desc',
|
||||
'src',
|
||||
'link',
|
||||
'number',
|
||||
'type',
|
||||
'rtept',
|
||||
]);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const RTE_SERIALIZERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'name': makeChildAppender(writeStringTextNode),
|
||||
'cmt': makeChildAppender(writeStringTextNode),
|
||||
'desc': makeChildAppender(writeStringTextNode),
|
||||
'src': makeChildAppender(writeStringTextNode),
|
||||
'link': makeChildAppender(writeLink),
|
||||
'number': makeChildAppender(writeNonNegativeIntegerTextNode),
|
||||
'type': makeChildAppender(writeStringTextNode),
|
||||
'rtept': makeArraySerializer(makeChildAppender(writeWptType)),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Array<string>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const RTEPT_TYPE_SEQUENCE = makeStructureNS(NAMESPACE_URIS, ['ele', 'time']);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Array<string>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TRK_SEQUENCE = makeStructureNS(NAMESPACE_URIS, [
|
||||
'name',
|
||||
'cmt',
|
||||
'desc',
|
||||
'src',
|
||||
'link',
|
||||
'number',
|
||||
'type',
|
||||
'trkseg',
|
||||
]);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TRK_SERIALIZERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'name': makeChildAppender(writeStringTextNode),
|
||||
'cmt': makeChildAppender(writeStringTextNode),
|
||||
'desc': makeChildAppender(writeStringTextNode),
|
||||
'src': makeChildAppender(writeStringTextNode),
|
||||
'link': makeChildAppender(writeLink),
|
||||
'number': makeChildAppender(writeNonNegativeIntegerTextNode),
|
||||
'type': makeChildAppender(writeStringTextNode),
|
||||
'trkseg': makeArraySerializer(makeChildAppender(writeTrkSeg)),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {function(*, Array<*>, string=): (Node|undefined)}
|
||||
*/
|
||||
const TRKSEG_NODE_FACTORY = makeSimpleNodeFactory('trkpt');
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TRKSEG_SERIALIZERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'trkpt': makeChildAppender(writeWptType),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Array<string>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const WPT_TYPE_SEQUENCE = makeStructureNS(NAMESPACE_URIS, [
|
||||
'ele',
|
||||
'time',
|
||||
'magvar',
|
||||
'geoidheight',
|
||||
'name',
|
||||
'cmt',
|
||||
'desc',
|
||||
'src',
|
||||
'link',
|
||||
'sym',
|
||||
'type',
|
||||
'fix',
|
||||
'sat',
|
||||
'hdop',
|
||||
'vdop',
|
||||
'pdop',
|
||||
'ageofdgpsdata',
|
||||
'dgpsid',
|
||||
]);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const WPT_TYPE_SERIALIZERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'ele': makeChildAppender(writeDecimalTextNode),
|
||||
'time': makeChildAppender(writeDateTimeTextNode),
|
||||
'magvar': makeChildAppender(writeDecimalTextNode),
|
||||
'geoidheight': makeChildAppender(writeDecimalTextNode),
|
||||
'name': makeChildAppender(writeStringTextNode),
|
||||
'cmt': makeChildAppender(writeStringTextNode),
|
||||
'desc': makeChildAppender(writeStringTextNode),
|
||||
'src': makeChildAppender(writeStringTextNode),
|
||||
'link': makeChildAppender(writeLink),
|
||||
'sym': makeChildAppender(writeStringTextNode),
|
||||
'type': makeChildAppender(writeStringTextNode),
|
||||
'fix': makeChildAppender(writeStringTextNode),
|
||||
'sat': makeChildAppender(writeNonNegativeIntegerTextNode),
|
||||
'hdop': makeChildAppender(writeDecimalTextNode),
|
||||
'vdop': makeChildAppender(writeDecimalTextNode),
|
||||
'pdop': makeChildAppender(writeDecimalTextNode),
|
||||
'ageofdgpsdata': makeChildAppender(writeDecimalTextNode),
|
||||
'dgpsid': makeChildAppender(writeNonNegativeIntegerTextNode),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, string>}
|
||||
*/
|
||||
const GEOMETRY_TYPE_TO_NODENAME = {
|
||||
'Point': 'wpt',
|
||||
'LineString': 'rte',
|
||||
'MultiLineString': 'trk',
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {*} value Value.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @param {string} [opt_nodeName] Node name.
|
||||
* @return {Node|undefined} Node.
|
||||
*/
|
||||
function GPX_NODE_FACTORY(value, objectStack, opt_nodeName) {
|
||||
const geometry = /** @type {Feature} */ (value).getGeometry();
|
||||
if (geometry) {
|
||||
const nodeName = GEOMETRY_TYPE_TO_NODENAME[geometry.getType()];
|
||||
if (nodeName) {
|
||||
const parentNode = objectStack[objectStack.length - 1].node;
|
||||
return createElementNS(parentNode.namespaceURI, nodeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<number>} flatCoordinates Flat coordinates.
|
||||
* @param {LayoutOptions} layoutOptions Layout options.
|
||||
* @param {Element} node Node.
|
||||
* @param {!Object} values Values.
|
||||
* @return {Array<number>} Flat coordinates.
|
||||
*/
|
||||
function appendCoordinate(flatCoordinates, layoutOptions, node, values) {
|
||||
flatCoordinates.push(
|
||||
parseFloat(node.getAttribute('lon')),
|
||||
parseFloat(node.getAttribute('lat'))
|
||||
);
|
||||
if ('ele' in values) {
|
||||
flatCoordinates.push(/** @type {number} */ (values['ele']));
|
||||
delete values['ele'];
|
||||
layoutOptions.hasZ = true;
|
||||
} else {
|
||||
flatCoordinates.push(0);
|
||||
}
|
||||
if ('time' in values) {
|
||||
flatCoordinates.push(/** @type {number} */ (values['time']));
|
||||
delete values['time'];
|
||||
layoutOptions.hasM = true;
|
||||
} else {
|
||||
flatCoordinates.push(0);
|
||||
}
|
||||
return flatCoordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose GeometryLayout based on flags in layoutOptions and adjust flatCoordinates
|
||||
* and ends arrays by shrinking them accordingly (removing unused zero entries).
|
||||
*
|
||||
* @param {LayoutOptions} layoutOptions Layout options.
|
||||
* @param {Array<number>} flatCoordinates Flat coordinates.
|
||||
* @param {Array<number>} [ends] Ends.
|
||||
* @return {import("../geom/GeometryLayout.js").default} Layout.
|
||||
*/
|
||||
function applyLayoutOptions(layoutOptions, flatCoordinates, ends) {
|
||||
let layout = GeometryLayout.XY;
|
||||
let stride = 2;
|
||||
if (layoutOptions.hasZ && layoutOptions.hasM) {
|
||||
layout = GeometryLayout.XYZM;
|
||||
stride = 4;
|
||||
} else if (layoutOptions.hasZ) {
|
||||
layout = GeometryLayout.XYZ;
|
||||
stride = 3;
|
||||
} else if (layoutOptions.hasM) {
|
||||
layout = GeometryLayout.XYM;
|
||||
stride = 3;
|
||||
}
|
||||
if (stride !== 4) {
|
||||
for (let i = 0, ii = flatCoordinates.length / 4; i < ii; i++) {
|
||||
flatCoordinates[i * stride] = flatCoordinates[i * 4];
|
||||
flatCoordinates[i * stride + 1] = flatCoordinates[i * 4 + 1];
|
||||
if (layoutOptions.hasZ) {
|
||||
flatCoordinates[i * stride + 2] = flatCoordinates[i * 4 + 2];
|
||||
}
|
||||
if (layoutOptions.hasM) {
|
||||
flatCoordinates[i * stride + 2] = flatCoordinates[i * 4 + 3];
|
||||
}
|
||||
}
|
||||
flatCoordinates.length = (flatCoordinates.length / 4) * stride;
|
||||
if (ends) {
|
||||
for (let i = 0, ii = ends.length; i < ii; i++) {
|
||||
ends[i] = (ends[i] / 4) * stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function parseLink(node, objectStack) {
|
||||
const values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
const href = node.getAttribute('href');
|
||||
if (href !== null) {
|
||||
values['link'] = href;
|
||||
}
|
||||
parseNode(LINK_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function parseExtensions(node, objectStack) {
|
||||
const values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
values['extensionsNode_'] = node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function parseRtePt(node, objectStack) {
|
||||
const values = pushParseAndPop({}, RTEPT_PARSERS, node, objectStack);
|
||||
if (values) {
|
||||
const rteValues = /** @type {!Object} */ (
|
||||
objectStack[objectStack.length - 1]
|
||||
);
|
||||
const flatCoordinates = /** @type {Array<number>} */ (
|
||||
rteValues['flatCoordinates']
|
||||
);
|
||||
const layoutOptions = /** @type {LayoutOptions} */ (
|
||||
rteValues['layoutOptions']
|
||||
);
|
||||
appendCoordinate(flatCoordinates, layoutOptions, node, values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function parseTrkPt(node, objectStack) {
|
||||
const values = pushParseAndPop({}, TRKPT_PARSERS, node, objectStack);
|
||||
if (values) {
|
||||
const trkValues = /** @type {!Object} */ (
|
||||
objectStack[objectStack.length - 1]
|
||||
);
|
||||
const flatCoordinates = /** @type {Array<number>} */ (
|
||||
trkValues['flatCoordinates']
|
||||
);
|
||||
const layoutOptions = /** @type {LayoutOptions} */ (
|
||||
trkValues['layoutOptions']
|
||||
);
|
||||
appendCoordinate(flatCoordinates, layoutOptions, node, values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function parseTrkSeg(node, objectStack) {
|
||||
const values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
parseNode(TRKSEG_PARSERS, node, objectStack);
|
||||
const flatCoordinates =
|
||||
/** @type {Array<number>} */
|
||||
(values['flatCoordinates']);
|
||||
const ends = /** @type {Array<number>} */ (values['ends']);
|
||||
ends.push(flatCoordinates.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Feature|undefined} Track.
|
||||
*/
|
||||
function readRte(node, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").ReadOptions} */ (
|
||||
objectStack[0]
|
||||
);
|
||||
const values = pushParseAndPop(
|
||||
{
|
||||
'flatCoordinates': [],
|
||||
'layoutOptions': {},
|
||||
},
|
||||
RTE_PARSERS,
|
||||
node,
|
||||
objectStack
|
||||
);
|
||||
if (!values) {
|
||||
return undefined;
|
||||
}
|
||||
const flatCoordinates =
|
||||
/** @type {Array<number>} */
|
||||
(values['flatCoordinates']);
|
||||
delete values['flatCoordinates'];
|
||||
const layoutOptions = /** @type {LayoutOptions} */ (values['layoutOptions']);
|
||||
delete values['layoutOptions'];
|
||||
const layout = applyLayoutOptions(layoutOptions, flatCoordinates);
|
||||
const geometry = new LineString(flatCoordinates, layout);
|
||||
transformGeometryWithOptions(geometry, false, options);
|
||||
const feature = new Feature(geometry);
|
||||
feature.setProperties(values, true);
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Feature|undefined} Track.
|
||||
*/
|
||||
function readTrk(node, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").ReadOptions} */ (
|
||||
objectStack[0]
|
||||
);
|
||||
const values = pushParseAndPop(
|
||||
{
|
||||
'flatCoordinates': [],
|
||||
'ends': [],
|
||||
'layoutOptions': {},
|
||||
},
|
||||
TRK_PARSERS,
|
||||
node,
|
||||
objectStack
|
||||
);
|
||||
if (!values) {
|
||||
return undefined;
|
||||
}
|
||||
const flatCoordinates =
|
||||
/** @type {Array<number>} */
|
||||
(values['flatCoordinates']);
|
||||
delete values['flatCoordinates'];
|
||||
const ends = /** @type {Array<number>} */ (values['ends']);
|
||||
delete values['ends'];
|
||||
const layoutOptions = /** @type {LayoutOptions} */ (values['layoutOptions']);
|
||||
delete values['layoutOptions'];
|
||||
const layout = applyLayoutOptions(layoutOptions, flatCoordinates, ends);
|
||||
const geometry = new MultiLineString(flatCoordinates, layout, ends);
|
||||
transformGeometryWithOptions(geometry, false, options);
|
||||
const feature = new Feature(geometry);
|
||||
feature.setProperties(values, true);
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Feature|undefined} Waypoint.
|
||||
*/
|
||||
function readWpt(node, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").ReadOptions} */ (
|
||||
objectStack[0]
|
||||
);
|
||||
const values = pushParseAndPop({}, WPT_PARSERS, node, objectStack);
|
||||
if (!values) {
|
||||
return undefined;
|
||||
}
|
||||
const layoutOptions = /** @type {LayoutOptions} */ ({});
|
||||
const coordinates = appendCoordinate([], layoutOptions, node, values);
|
||||
const layout = applyLayoutOptions(layoutOptions, coordinates);
|
||||
const geometry = new Point(coordinates, layout);
|
||||
transformGeometryWithOptions(geometry, false, options);
|
||||
const feature = new Feature(geometry);
|
||||
feature.setProperties(values, true);
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {string} value Value for the link's `href` attribute.
|
||||
* @param {Array<*>} objectStack Node stack.
|
||||
*/
|
||||
function writeLink(node, value, objectStack) {
|
||||
node.setAttribute('href', value);
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const properties = context['properties'];
|
||||
const link = [properties['linkText'], properties['linkType']];
|
||||
pushSerializeAndPop(
|
||||
/** @type {import("../xml.js").NodeStackItem} */ ({node: node}),
|
||||
LINK_SERIALIZERS,
|
||||
OBJECT_PROPERTY_NODE_FACTORY,
|
||||
link,
|
||||
objectStack,
|
||||
LINK_SEQUENCE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("../coordinate.js").Coordinate} coordinate Coordinate.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function writeWptType(node, coordinate, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const parentNode = context.node;
|
||||
const namespaceURI = parentNode.namespaceURI;
|
||||
const properties = context['properties'];
|
||||
//FIXME Projection handling
|
||||
node.setAttributeNS(null, 'lat', String(coordinate[1]));
|
||||
node.setAttributeNS(null, 'lon', String(coordinate[0]));
|
||||
const geometryLayout = context['geometryLayout'];
|
||||
switch (geometryLayout) {
|
||||
case GeometryLayout.XYZM:
|
||||
if (coordinate[3] !== 0) {
|
||||
properties['time'] = coordinate[3];
|
||||
}
|
||||
// fall through
|
||||
case GeometryLayout.XYZ:
|
||||
if (coordinate[2] !== 0) {
|
||||
properties['ele'] = coordinate[2];
|
||||
}
|
||||
break;
|
||||
case GeometryLayout.XYM:
|
||||
if (coordinate[2] !== 0) {
|
||||
properties['time'] = coordinate[2];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
const orderedKeys =
|
||||
node.nodeName == 'rtept'
|
||||
? RTEPT_TYPE_SEQUENCE[namespaceURI]
|
||||
: WPT_TYPE_SEQUENCE[namespaceURI];
|
||||
const values = makeSequence(properties, orderedKeys);
|
||||
pushSerializeAndPop(
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
({node: node, 'properties': properties}),
|
||||
WPT_TYPE_SERIALIZERS,
|
||||
OBJECT_PROPERTY_NODE_FACTORY,
|
||||
values,
|
||||
objectStack,
|
||||
orderedKeys
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Feature} feature Feature.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function writeRte(node, feature, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").WriteOptions} */ (
|
||||
objectStack[0]
|
||||
);
|
||||
const properties = feature.getProperties();
|
||||
const context = {node: node};
|
||||
context['properties'] = properties;
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry.getType() == 'LineString') {
|
||||
const lineString = /** @type {LineString} */ (
|
||||
transformGeometryWithOptions(geometry, true, options)
|
||||
);
|
||||
context['geometryLayout'] = lineString.getLayout();
|
||||
properties['rtept'] = lineString.getCoordinates();
|
||||
}
|
||||
const parentNode = objectStack[objectStack.length - 1].node;
|
||||
const orderedKeys = RTE_SEQUENCE[parentNode.namespaceURI];
|
||||
const values = makeSequence(properties, orderedKeys);
|
||||
pushSerializeAndPop(
|
||||
context,
|
||||
RTE_SERIALIZERS,
|
||||
OBJECT_PROPERTY_NODE_FACTORY,
|
||||
values,
|
||||
objectStack,
|
||||
orderedKeys
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Feature} feature Feature.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function writeTrk(node, feature, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").WriteOptions} */ (
|
||||
objectStack[0]
|
||||
);
|
||||
const properties = feature.getProperties();
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
const context = {node: node};
|
||||
context['properties'] = properties;
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry.getType() == 'MultiLineString') {
|
||||
const multiLineString = /** @type {MultiLineString} */ (
|
||||
transformGeometryWithOptions(geometry, true, options)
|
||||
);
|
||||
properties['trkseg'] = multiLineString.getLineStrings();
|
||||
}
|
||||
const parentNode = objectStack[objectStack.length - 1].node;
|
||||
const orderedKeys = TRK_SEQUENCE[parentNode.namespaceURI];
|
||||
const values = makeSequence(properties, orderedKeys);
|
||||
pushSerializeAndPop(
|
||||
context,
|
||||
TRK_SERIALIZERS,
|
||||
OBJECT_PROPERTY_NODE_FACTORY,
|
||||
values,
|
||||
objectStack,
|
||||
orderedKeys
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {LineString} lineString LineString.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function writeTrkSeg(node, lineString, objectStack) {
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
const context = {node: node};
|
||||
context['geometryLayout'] = lineString.getLayout();
|
||||
context['properties'] = {};
|
||||
pushSerializeAndPop(
|
||||
context,
|
||||
TRKSEG_SERIALIZERS,
|
||||
TRKSEG_NODE_FACTORY,
|
||||
lineString.getCoordinates(),
|
||||
objectStack
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Feature} feature Feature.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function writeWpt(node, feature, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").WriteOptions} */ (
|
||||
objectStack[0]
|
||||
);
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
context['properties'] = feature.getProperties();
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry.getType() == 'Point') {
|
||||
const point = /** @type {Point} */ (
|
||||
transformGeometryWithOptions(geometry, true, options)
|
||||
);
|
||||
context['geometryLayout'] = point.getLayout();
|
||||
writeWptType(node, point.getCoordinates(), objectStack);
|
||||
}
|
||||
}
|
||||
|
||||
export default GPX;
|
||||
569
node_modules/ol/src/format/GeoJSON.js
generated
vendored
Normal file
569
node_modules/ol/src/format/GeoJSON.js
generated
vendored
Normal file
@@ -0,0 +1,569 @@
|
||||
/**
|
||||
* @module ol/format/GeoJSON
|
||||
*/
|
||||
|
||||
import Feature from '../Feature.js';
|
||||
import GeometryCollection from '../geom/GeometryCollection.js';
|
||||
import JSONFeature from './JSONFeature.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import MultiPoint from '../geom/MultiPoint.js';
|
||||
import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import {assert} from '../asserts.js';
|
||||
import {assign, isEmpty} from '../obj.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {transformGeometryWithOptions} from './Feature.js';
|
||||
|
||||
/**
|
||||
* @typedef {import("geojson").GeoJSON} GeoJSONObject
|
||||
* @typedef {import("geojson").Feature} GeoJSONFeature
|
||||
* @typedef {import("geojson").FeatureCollection} GeoJSONFeatureCollection
|
||||
* @typedef {import("geojson").Geometry} GeoJSONGeometry
|
||||
* @typedef {import("geojson").Point} GeoJSONPoint
|
||||
* @typedef {import("geojson").LineString} GeoJSONLineString
|
||||
* @typedef {import("geojson").Polygon} GeoJSONPolygon
|
||||
* @typedef {import("geojson").MultiPoint} GeoJSONMultiPoint
|
||||
* @typedef {import("geojson").MultiLineString} GeoJSONMultiLineString
|
||||
* @typedef {import("geojson").MultiPolygon} GeoJSONMultiPolygon
|
||||
* @typedef {import("geojson").GeometryCollection} GeoJSONGeometryCollection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {import("../proj.js").ProjectionLike} [dataProjection='EPSG:4326'] Default data projection.
|
||||
* @property {import("../proj.js").ProjectionLike} [featureProjection] Projection for features read or
|
||||
* written by the format. Options passed to read or write methods will take precedence.
|
||||
* @property {string} [geometryName] Geometry name to use when creating features.
|
||||
* @property {boolean} [extractGeometryName=false] Certain GeoJSON providers include
|
||||
* the geometry_name field in the feature GeoJSON. If set to `true` the GeoJSON reader
|
||||
* will look for that field to set the geometry name. If both this field is set to `true`
|
||||
* and a `geometryName` is provided, the `geometryName` will take precedence.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the GeoJSON format.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class GeoJSON extends JSONFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super();
|
||||
|
||||
/**
|
||||
* @type {import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.dataProjection = getProjection(
|
||||
options.dataProjection ? options.dataProjection : 'EPSG:4326'
|
||||
);
|
||||
|
||||
if (options.featureProjection) {
|
||||
/**
|
||||
* @type {import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.defaultFeatureProjection = getProjection(options.featureProjection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the geometry attribute for features.
|
||||
* @type {string|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.geometryName_ = options.geometryName;
|
||||
|
||||
/**
|
||||
* Look for the geometry name in the feature GeoJSON
|
||||
* @type {boolean|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.extractGeometryName_ = options.extractGeometryName;
|
||||
|
||||
this.supportedMediaTypes = [
|
||||
'application/geo+json',
|
||||
'application/vnd.geo+json',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromObject(object, opt_options) {
|
||||
/**
|
||||
* @type {GeoJSONFeature}
|
||||
*/
|
||||
let geoJSONFeature = null;
|
||||
if (object['type'] === 'Feature') {
|
||||
geoJSONFeature = /** @type {GeoJSONFeature} */ (object);
|
||||
} else {
|
||||
geoJSONFeature = {
|
||||
'type': 'Feature',
|
||||
'geometry': /** @type {GeoJSONGeometry} */ (object),
|
||||
'properties': null,
|
||||
};
|
||||
}
|
||||
|
||||
const geometry = readGeometry(geoJSONFeature['geometry'], opt_options);
|
||||
const feature = new Feature();
|
||||
if (this.geometryName_) {
|
||||
feature.setGeometryName(this.geometryName_);
|
||||
} else if (
|
||||
this.extractGeometryName_ &&
|
||||
'geometry_name' in geoJSONFeature !== undefined
|
||||
) {
|
||||
feature.setGeometryName(geoJSONFeature['geometry_name']);
|
||||
}
|
||||
feature.setGeometry(geometry);
|
||||
|
||||
if ('id' in geoJSONFeature) {
|
||||
feature.setId(geoJSONFeature['id']);
|
||||
}
|
||||
|
||||
if (geoJSONFeature['properties']) {
|
||||
feature.setProperties(geoJSONFeature['properties'], true);
|
||||
}
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {Array<Feature>} Features.
|
||||
*/
|
||||
readFeaturesFromObject(object, opt_options) {
|
||||
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
|
||||
/** @type {Array<import("../Feature.js").default>} */
|
||||
let features = null;
|
||||
if (geoJSONObject['type'] === 'FeatureCollection') {
|
||||
const geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */ (
|
||||
object
|
||||
);
|
||||
features = [];
|
||||
const geoJSONFeatures = geoJSONFeatureCollection['features'];
|
||||
for (let i = 0, ii = geoJSONFeatures.length; i < ii; ++i) {
|
||||
features.push(
|
||||
this.readFeatureFromObject(geoJSONFeatures[i], opt_options)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
features = [this.readFeatureFromObject(object, opt_options)];
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromObject(object, opt_options) {
|
||||
return readGeometry(object, opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @protected
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjectionFromObject(object) {
|
||||
const crs = object['crs'];
|
||||
let projection;
|
||||
if (crs) {
|
||||
if (crs['type'] == 'name') {
|
||||
projection = getProjection(crs['properties']['name']);
|
||||
} else if (crs['type'] === 'EPSG') {
|
||||
projection = getProjection('EPSG:' + crs['properties']['code']);
|
||||
} else {
|
||||
assert(false, 36); // Unknown SRS type
|
||||
}
|
||||
} else {
|
||||
projection = this.dataProjection;
|
||||
}
|
||||
return /** @type {import("../proj/Projection.js").default} */ (projection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature as a GeoJSON Feature object.
|
||||
*
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONFeature} Object.
|
||||
* @api
|
||||
*/
|
||||
writeFeatureObject(feature, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
|
||||
/** @type {GeoJSONFeature} */
|
||||
const object = {
|
||||
'type': 'Feature',
|
||||
geometry: null,
|
||||
properties: null,
|
||||
};
|
||||
|
||||
const id = feature.getId();
|
||||
if (id !== undefined) {
|
||||
object.id = id;
|
||||
}
|
||||
|
||||
if (!feature.hasProperties()) {
|
||||
return object;
|
||||
}
|
||||
|
||||
const properties = feature.getProperties();
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
object.geometry = writeGeometry(geometry, opt_options);
|
||||
|
||||
delete properties[feature.getGeometryName()];
|
||||
}
|
||||
|
||||
if (!isEmpty(properties)) {
|
||||
object.properties = properties;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features as a GeoJSON object.
|
||||
*
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONFeatureCollection} GeoJSON Object.
|
||||
* @api
|
||||
*/
|
||||
writeFeaturesObject(features, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
const objects = [];
|
||||
for (let i = 0, ii = features.length; i < ii; ++i) {
|
||||
objects.push(this.writeFeatureObject(features[i], opt_options));
|
||||
}
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
features: objects,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a geometry as a GeoJSON object.
|
||||
*
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometry|GeoJSONGeometryCollection} Object.
|
||||
* @api
|
||||
*/
|
||||
writeGeometryObject(geometry, opt_options) {
|
||||
return writeGeometry(geometry, this.adaptOptions(opt_options));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometry|GeoJSONGeometryCollection} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
function readGeometry(object, opt_options) {
|
||||
if (!object) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {import("../geom/Geometry.js").default}
|
||||
*/
|
||||
let geometry;
|
||||
switch (object['type']) {
|
||||
case 'Point': {
|
||||
geometry = readPointGeometry(/** @type {GeoJSONPoint} */ (object));
|
||||
break;
|
||||
}
|
||||
case 'LineString': {
|
||||
geometry = readLineStringGeometry(
|
||||
/** @type {GeoJSONLineString} */ (object)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'Polygon': {
|
||||
geometry = readPolygonGeometry(/** @type {GeoJSONPolygon} */ (object));
|
||||
break;
|
||||
}
|
||||
case 'MultiPoint': {
|
||||
geometry = readMultiPointGeometry(
|
||||
/** @type {GeoJSONMultiPoint} */ (object)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'MultiLineString': {
|
||||
geometry = readMultiLineStringGeometry(
|
||||
/** @type {GeoJSONMultiLineString} */ (object)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'MultiPolygon': {
|
||||
geometry = readMultiPolygonGeometry(
|
||||
/** @type {GeoJSONMultiPolygon} */ (object)
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'GeometryCollection': {
|
||||
geometry = readGeometryCollectionGeometry(
|
||||
/** @type {GeoJSONGeometryCollection} */ (object)
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error('Unsupported GeoJSON type: ' + object['type']);
|
||||
}
|
||||
}
|
||||
return transformGeometryWithOptions(geometry, false, opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometryCollection} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {GeometryCollection} Geometry collection.
|
||||
*/
|
||||
function readGeometryCollectionGeometry(object, opt_options) {
|
||||
const geometries = object['geometries'].map(
|
||||
/**
|
||||
* @param {GeoJSONGeometry} geometry Geometry.
|
||||
* @return {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
*/
|
||||
function (geometry) {
|
||||
return readGeometry(geometry, opt_options);
|
||||
}
|
||||
);
|
||||
return new GeometryCollection(geometries);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONPoint} object Object.
|
||||
* @return {Point} Point.
|
||||
*/
|
||||
function readPointGeometry(object) {
|
||||
return new Point(object['coordinates']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONLineString} object Object.
|
||||
* @return {LineString} LineString.
|
||||
*/
|
||||
function readLineStringGeometry(object) {
|
||||
return new LineString(object['coordinates']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONMultiLineString} object Object.
|
||||
* @return {MultiLineString} MultiLineString.
|
||||
*/
|
||||
function readMultiLineStringGeometry(object) {
|
||||
return new MultiLineString(object['coordinates']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONMultiPoint} object Object.
|
||||
* @return {MultiPoint} MultiPoint.
|
||||
*/
|
||||
function readMultiPointGeometry(object) {
|
||||
return new MultiPoint(object['coordinates']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONMultiPolygon} object Object.
|
||||
* @return {MultiPolygon} MultiPolygon.
|
||||
*/
|
||||
function readMultiPolygonGeometry(object) {
|
||||
return new MultiPolygon(object['coordinates']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeoJSONPolygon} object Object.
|
||||
* @return {Polygon} Polygon.
|
||||
*/
|
||||
function readPolygonGeometry(object) {
|
||||
return new Polygon(object['coordinates']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
function writeGeometry(geometry, opt_options) {
|
||||
geometry = transformGeometryWithOptions(geometry, true, opt_options);
|
||||
const type = geometry.getType();
|
||||
|
||||
/** @type {GeoJSONGeometry} */
|
||||
let geoJSON;
|
||||
switch (type) {
|
||||
case 'Point': {
|
||||
geoJSON = writePointGeometry(
|
||||
/** @type {Point} */ (geometry),
|
||||
opt_options
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'LineString': {
|
||||
geoJSON = writeLineStringGeometry(
|
||||
/** @type {LineString} */ (geometry),
|
||||
opt_options
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'Polygon': {
|
||||
geoJSON = writePolygonGeometry(
|
||||
/** @type {Polygon} */ (geometry),
|
||||
opt_options
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'MultiPoint': {
|
||||
geoJSON = writeMultiPointGeometry(
|
||||
/** @type {MultiPoint} */ (geometry),
|
||||
opt_options
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'MultiLineString': {
|
||||
geoJSON = writeMultiLineStringGeometry(
|
||||
/** @type {MultiLineString} */ (geometry),
|
||||
opt_options
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'MultiPolygon': {
|
||||
geoJSON = writeMultiPolygonGeometry(
|
||||
/** @type {MultiPolygon} */ (geometry),
|
||||
opt_options
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'GeometryCollection': {
|
||||
geoJSON = writeGeometryCollectionGeometry(
|
||||
/** @type {GeometryCollection} */ (geometry),
|
||||
opt_options
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'Circle': {
|
||||
geoJSON = {
|
||||
type: 'GeometryCollection',
|
||||
geometries: [],
|
||||
};
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new Error('Unsupported geometry type: ' + type);
|
||||
}
|
||||
}
|
||||
return geoJSON;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeometryCollection} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometryCollection} GeoJSON geometry collection.
|
||||
*/
|
||||
function writeGeometryCollectionGeometry(geometry, opt_options) {
|
||||
const geometries = geometry.getGeometriesArray().map(function (geometry) {
|
||||
const options = assign({}, opt_options);
|
||||
delete options.featureProjection;
|
||||
return writeGeometry(geometry, options);
|
||||
});
|
||||
return {
|
||||
type: 'GeometryCollection',
|
||||
geometries: geometries,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LineString} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
function writeLineStringGeometry(geometry, opt_options) {
|
||||
return {
|
||||
type: 'LineString',
|
||||
coordinates: geometry.getCoordinates(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MultiLineString} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
function writeMultiLineStringGeometry(geometry, opt_options) {
|
||||
return {
|
||||
type: 'MultiLineString',
|
||||
coordinates: geometry.getCoordinates(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MultiPoint} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
function writeMultiPointGeometry(geometry, opt_options) {
|
||||
return {
|
||||
type: 'MultiPoint',
|
||||
coordinates: geometry.getCoordinates(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MultiPolygon} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
function writeMultiPolygonGeometry(geometry, opt_options) {
|
||||
let right;
|
||||
if (opt_options) {
|
||||
right = opt_options.rightHanded;
|
||||
}
|
||||
return {
|
||||
type: 'MultiPolygon',
|
||||
coordinates: geometry.getCoordinates(right),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Point} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
function writePointGeometry(geometry, opt_options) {
|
||||
return {
|
||||
type: 'Point',
|
||||
coordinates: geometry.getCoordinates(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Polygon} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
function writePolygonGeometry(geometry, opt_options) {
|
||||
let right;
|
||||
if (opt_options) {
|
||||
right = opt_options.rightHanded;
|
||||
}
|
||||
return {
|
||||
type: 'Polygon',
|
||||
coordinates: geometry.getCoordinates(right),
|
||||
};
|
||||
}
|
||||
|
||||
export default GeoJSON;
|
||||
184
node_modules/ol/src/format/IGC.js
generated
vendored
Normal file
184
node_modules/ol/src/format/IGC.js
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* @module ol/format/IGC
|
||||
*/
|
||||
import Feature from '../Feature.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import TextFeature from './TextFeature.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {transformGeometryWithOptions} from './Feature.js';
|
||||
|
||||
/**
|
||||
* IGC altitude/z. One of 'barometric', 'gps', 'none'.
|
||||
* @enum {string}
|
||||
*/
|
||||
const IGCZ = {
|
||||
BAROMETRIC: 'barometric',
|
||||
GPS: 'gps',
|
||||
NONE: 'none',
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
*/
|
||||
const B_RECORD_RE =
|
||||
/^B(\d{2})(\d{2})(\d{2})(\d{2})(\d{5})([NS])(\d{3})(\d{5})([EW])([AV])(\d{5})(\d{5})/;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
*/
|
||||
const H_RECORD_RE = /^H.([A-Z]{3}).*?:(.*)/;
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
*/
|
||||
const HFDTE_RECORD_RE = /^HFDTE(\d{2})(\d{2})(\d{2})/;
|
||||
|
||||
/**
|
||||
* A regular expression matching the newline characters `\r\n`, `\r` and `\n`.
|
||||
*
|
||||
* @const
|
||||
* @type {RegExp}
|
||||
*/
|
||||
const NEWLINE_RE = /\r\n|\r|\n/;
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {IGCZ|string} [altitudeMode='none'] Altitude mode. Possible
|
||||
* values are `'barometric'`, `'gps'`, and `'none'`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for `*.igc` flight recording files.
|
||||
*
|
||||
* As IGC sources contain a single feature,
|
||||
* {@link module:ol/format/IGC~IGC#readFeatures} will return the feature in an
|
||||
* array
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class IGC extends TextFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.dataProjection = getProjection('EPSG:4326');
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {IGCZ}
|
||||
*/
|
||||
this.altitudeMode_ = options.altitudeMode
|
||||
? options.altitudeMode
|
||||
: IGCZ.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromText(text, opt_options) {
|
||||
const altitudeMode = this.altitudeMode_;
|
||||
const lines = text.split(NEWLINE_RE);
|
||||
/** @type {Object<string, string>} */
|
||||
const properties = {};
|
||||
const flatCoordinates = [];
|
||||
let year = 2000;
|
||||
let month = 0;
|
||||
let day = 1;
|
||||
let lastDateTime = -1;
|
||||
let i, ii;
|
||||
for (i = 0, ii = lines.length; i < ii; ++i) {
|
||||
const line = lines[i];
|
||||
let m;
|
||||
if (line.charAt(0) == 'B') {
|
||||
m = B_RECORD_RE.exec(line);
|
||||
if (m) {
|
||||
const hour = parseInt(m[1], 10);
|
||||
const minute = parseInt(m[2], 10);
|
||||
const second = parseInt(m[3], 10);
|
||||
let y = parseInt(m[4], 10) + parseInt(m[5], 10) / 60000;
|
||||
if (m[6] == 'S') {
|
||||
y = -y;
|
||||
}
|
||||
let x = parseInt(m[7], 10) + parseInt(m[8], 10) / 60000;
|
||||
if (m[9] == 'W') {
|
||||
x = -x;
|
||||
}
|
||||
flatCoordinates.push(x, y);
|
||||
if (altitudeMode != IGCZ.NONE) {
|
||||
let z;
|
||||
if (altitudeMode == IGCZ.GPS) {
|
||||
z = parseInt(m[11], 10);
|
||||
} else if (altitudeMode == IGCZ.BAROMETRIC) {
|
||||
z = parseInt(m[12], 10);
|
||||
} else {
|
||||
z = 0;
|
||||
}
|
||||
flatCoordinates.push(z);
|
||||
}
|
||||
let dateTime = Date.UTC(year, month, day, hour, minute, second);
|
||||
// Detect UTC midnight wrap around.
|
||||
if (dateTime < lastDateTime) {
|
||||
dateTime = Date.UTC(year, month, day + 1, hour, minute, second);
|
||||
}
|
||||
flatCoordinates.push(dateTime / 1000);
|
||||
lastDateTime = dateTime;
|
||||
}
|
||||
} else if (line.charAt(0) == 'H') {
|
||||
m = HFDTE_RECORD_RE.exec(line);
|
||||
if (m) {
|
||||
day = parseInt(m[1], 10);
|
||||
month = parseInt(m[2], 10) - 1;
|
||||
year = 2000 + parseInt(m[3], 10);
|
||||
} else {
|
||||
m = H_RECORD_RE.exec(line);
|
||||
if (m) {
|
||||
properties[m[1]] = m[2].trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flatCoordinates.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const layout =
|
||||
altitudeMode == IGCZ.NONE ? GeometryLayout.XYM : GeometryLayout.XYZM;
|
||||
const lineString = new LineString(flatCoordinates, layout);
|
||||
const feature = new Feature(
|
||||
transformGeometryWithOptions(lineString, false, opt_options)
|
||||
);
|
||||
feature.setProperties(properties, true);
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {Array<Feature>} Features.
|
||||
*/
|
||||
readFeaturesFromText(text, opt_options) {
|
||||
const feature = this.readFeatureFromText(text, opt_options);
|
||||
if (feature) {
|
||||
return [feature];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default IGC;
|
||||
485
node_modules/ol/src/format/IIIFInfo.js
generated
vendored
Normal file
485
node_modules/ol/src/format/IIIFInfo.js
generated
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
/**
|
||||
* @module ol/format/IIIFInfo
|
||||
*/
|
||||
|
||||
import {assert} from '../asserts.js';
|
||||
import {includes} from '../array.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} PreferredOptions
|
||||
* @property {string} [format] Preferred image format. Will be used if the image information
|
||||
* indicates support for that format.
|
||||
* @property {string} [quality] IIIF image qualitiy. Will be used if the image information
|
||||
* indicates support for that quality.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} SupportedFeatures
|
||||
* @property {Array<string>} [supports] Supported IIIF image size and region
|
||||
* calculation features.
|
||||
* @property {Array<string>} [formats] Supported image formats.
|
||||
* @property {Array<string>} [qualities] Supported IIIF image qualities.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} TileInfo
|
||||
* @property {Array<number>} scaleFactors Supported resolution scaling factors.
|
||||
* @property {number} width Tile width in pixels.
|
||||
* @property {number} [height] Tile height in pixels. Same as tile width if height is
|
||||
* not given.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} IiifProfile
|
||||
* @property {Array<string>} [formats] Supported image formats for the image service.
|
||||
* @property {Array<string>} [qualities] Supported IIIF image qualities.
|
||||
* @property {Array<string>} [supports] Supported features.
|
||||
* @property {number} [maxArea] Maximum area (pixels) available for this image service.
|
||||
* @property {number} [maxHeight] Maximum height.
|
||||
* @property {number} [maxWidth] Maximum width.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object<string,string|number|Array<number|string|IiifProfile|Object<string, number>|TileInfo>>}
|
||||
* ImageInformationResponse
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enum representing the major IIIF Image API versions
|
||||
* @enum {string}
|
||||
*/
|
||||
export const Versions = {
|
||||
VERSION1: 'version1',
|
||||
VERSION2: 'version2',
|
||||
VERSION3: 'version3',
|
||||
};
|
||||
|
||||
/**
|
||||
* Supported image formats, qualities and supported region / size calculation features
|
||||
* for different image API versions and compliance levels
|
||||
* @const
|
||||
* @type {Object<string, Object<string, SupportedFeatures>>}
|
||||
*/
|
||||
const IIIF_PROFILE_VALUES = {};
|
||||
IIIF_PROFILE_VALUES[Versions.VERSION1] = {
|
||||
'level0': {
|
||||
supports: [],
|
||||
formats: [],
|
||||
qualities: ['native'],
|
||||
},
|
||||
'level1': {
|
||||
supports: ['regionByPx', 'sizeByW', 'sizeByH', 'sizeByPct'],
|
||||
formats: ['jpg'],
|
||||
qualities: ['native'],
|
||||
},
|
||||
'level2': {
|
||||
supports: [
|
||||
'regionByPx',
|
||||
'regionByPct',
|
||||
'sizeByW',
|
||||
'sizeByH',
|
||||
'sizeByPct',
|
||||
'sizeByConfinedWh',
|
||||
'sizeByWh',
|
||||
],
|
||||
formats: ['jpg', 'png'],
|
||||
qualities: ['native', 'color', 'grey', 'bitonal'],
|
||||
},
|
||||
};
|
||||
IIIF_PROFILE_VALUES[Versions.VERSION2] = {
|
||||
'level0': {
|
||||
supports: [],
|
||||
formats: ['jpg'],
|
||||
qualities: ['default'],
|
||||
},
|
||||
'level1': {
|
||||
supports: ['regionByPx', 'sizeByW', 'sizeByH', 'sizeByPct'],
|
||||
formats: ['jpg'],
|
||||
qualities: ['default'],
|
||||
},
|
||||
'level2': {
|
||||
supports: [
|
||||
'regionByPx',
|
||||
'regionByPct',
|
||||
'sizeByW',
|
||||
'sizeByH',
|
||||
'sizeByPct',
|
||||
'sizeByConfinedWh',
|
||||
'sizeByDistortedWh',
|
||||
'sizeByWh',
|
||||
],
|
||||
formats: ['jpg', 'png'],
|
||||
qualities: ['default', 'bitonal'],
|
||||
},
|
||||
};
|
||||
IIIF_PROFILE_VALUES[Versions.VERSION3] = {
|
||||
'level0': {
|
||||
supports: [],
|
||||
formats: ['jpg'],
|
||||
qualities: ['default'],
|
||||
},
|
||||
'level1': {
|
||||
supports: ['regionByPx', 'regionSquare', 'sizeByW', 'sizeByH', 'sizeByWh'],
|
||||
formats: ['jpg'],
|
||||
qualities: ['default'],
|
||||
},
|
||||
'level2': {
|
||||
supports: [
|
||||
'regionByPx',
|
||||
'regionSquare',
|
||||
'regionByPct',
|
||||
'sizeByW',
|
||||
'sizeByH',
|
||||
'sizeByPct',
|
||||
'sizeByConfinedWh',
|
||||
'sizeByWh',
|
||||
],
|
||||
formats: ['jpg', 'png'],
|
||||
qualities: ['default'],
|
||||
},
|
||||
};
|
||||
IIIF_PROFILE_VALUES['none'] = {
|
||||
'none': {
|
||||
supports: [],
|
||||
formats: [],
|
||||
qualities: [],
|
||||
},
|
||||
};
|
||||
|
||||
const COMPLIANCE_VERSION1 =
|
||||
/^https?:\/\/library\.stanford\.edu\/iiif\/image-api\/(?:1\.1\/)?compliance\.html#level[0-2]$/;
|
||||
const COMPLIANCE_VERSION2 =
|
||||
/^https?:\/\/iiif\.io\/api\/image\/2\/level[0-2](?:\.json)?$/;
|
||||
const COMPLIANCE_VERSION3 =
|
||||
/(^https?:\/\/iiif\.io\/api\/image\/3\/level[0-2](?:\.json)?$)|(^level[0-2]$)/;
|
||||
|
||||
function generateVersion1Options(iiifInfo) {
|
||||
let levelProfile = iiifInfo.getComplianceLevelSupportedFeatures();
|
||||
// Version 1.0 and 1.1 do not require a profile.
|
||||
if (levelProfile === undefined) {
|
||||
levelProfile = IIIF_PROFILE_VALUES[Versions.VERSION1]['level0'];
|
||||
}
|
||||
return {
|
||||
url:
|
||||
iiifInfo.imageInfo['@id'] === undefined
|
||||
? undefined
|
||||
: iiifInfo.imageInfo['@id'].replace(/\/?(?:info\.json)?$/g, ''),
|
||||
supports: levelProfile.supports,
|
||||
formats: [
|
||||
...levelProfile.formats,
|
||||
iiifInfo.imageInfo.formats === undefined
|
||||
? []
|
||||
: iiifInfo.imageInfo.formats,
|
||||
],
|
||||
qualities: [
|
||||
...levelProfile.qualities,
|
||||
iiifInfo.imageInfo.qualities === undefined
|
||||
? []
|
||||
: iiifInfo.imageInfo.qualities,
|
||||
],
|
||||
resolutions: iiifInfo.imageInfo.scale_factors,
|
||||
tileSize:
|
||||
iiifInfo.imageInfo.tile_width !== undefined
|
||||
? iiifInfo.imageInfo.tile_height !== undefined
|
||||
? [iiifInfo.imageInfo.tile_width, iiifInfo.imageInfo.tile_height]
|
||||
: [iiifInfo.imageInfo.tile_width, iiifInfo.imageInfo.tile_width]
|
||||
: iiifInfo.imageInfo.tile_height != undefined
|
||||
? [iiifInfo.imageInfo.tile_height, iiifInfo.imageInfo.tile_height]
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
function generateVersion2Options(iiifInfo) {
|
||||
const levelProfile = iiifInfo.getComplianceLevelSupportedFeatures(),
|
||||
additionalProfile =
|
||||
Array.isArray(iiifInfo.imageInfo.profile) &&
|
||||
iiifInfo.imageInfo.profile.length > 1,
|
||||
profileSupports =
|
||||
additionalProfile && iiifInfo.imageInfo.profile[1].supports
|
||||
? iiifInfo.imageInfo.profile[1].supports
|
||||
: [],
|
||||
profileFormats =
|
||||
additionalProfile && iiifInfo.imageInfo.profile[1].formats
|
||||
? iiifInfo.imageInfo.profile[1].formats
|
||||
: [],
|
||||
profileQualities =
|
||||
additionalProfile && iiifInfo.imageInfo.profile[1].qualities
|
||||
? iiifInfo.imageInfo.profile[1].qualities
|
||||
: [];
|
||||
return {
|
||||
url: iiifInfo.imageInfo['@id'].replace(/\/?(?:info\.json)?$/g, ''),
|
||||
sizes:
|
||||
iiifInfo.imageInfo.sizes === undefined
|
||||
? undefined
|
||||
: iiifInfo.imageInfo.sizes.map(function (size) {
|
||||
return [size.width, size.height];
|
||||
}),
|
||||
tileSize:
|
||||
iiifInfo.imageInfo.tiles === undefined
|
||||
? undefined
|
||||
: [
|
||||
iiifInfo.imageInfo.tiles.map(function (tile) {
|
||||
return tile.width;
|
||||
})[0],
|
||||
iiifInfo.imageInfo.tiles.map(function (tile) {
|
||||
return tile.height === undefined ? tile.width : tile.height;
|
||||
})[0],
|
||||
],
|
||||
resolutions:
|
||||
iiifInfo.imageInfo.tiles === undefined
|
||||
? undefined
|
||||
: iiifInfo.imageInfo.tiles.map(function (tile) {
|
||||
return tile.scaleFactors;
|
||||
})[0],
|
||||
supports: [...levelProfile.supports, ...profileSupports],
|
||||
formats: [...levelProfile.formats, ...profileFormats],
|
||||
qualities: [...levelProfile.qualities, ...profileQualities],
|
||||
};
|
||||
}
|
||||
|
||||
function generateVersion3Options(iiifInfo) {
|
||||
const levelProfile = iiifInfo.getComplianceLevelSupportedFeatures(),
|
||||
formats =
|
||||
iiifInfo.imageInfo.extraFormats === undefined
|
||||
? levelProfile.formats
|
||||
: [...levelProfile.formats, ...iiifInfo.imageInfo.extraFormats],
|
||||
preferredFormat =
|
||||
iiifInfo.imageInfo.preferredFormats !== undefined &&
|
||||
Array.isArray(iiifInfo.imageInfo.preferredFormats) &&
|
||||
iiifInfo.imageInfo.preferredFormats.length > 0
|
||||
? iiifInfo.imageInfo.preferredFormats
|
||||
.filter(function (format) {
|
||||
return includes(['jpg', 'png', 'gif'], format);
|
||||
})
|
||||
.reduce(function (acc, format) {
|
||||
return acc === undefined && includes(formats, format)
|
||||
? format
|
||||
: acc;
|
||||
}, undefined)
|
||||
: undefined;
|
||||
return {
|
||||
url: iiifInfo.imageInfo['id'],
|
||||
sizes:
|
||||
iiifInfo.imageInfo.sizes === undefined
|
||||
? undefined
|
||||
: iiifInfo.imageInfo.sizes.map(function (size) {
|
||||
return [size.width, size.height];
|
||||
}),
|
||||
tileSize:
|
||||
iiifInfo.imageInfo.tiles === undefined
|
||||
? undefined
|
||||
: [
|
||||
iiifInfo.imageInfo.tiles.map(function (tile) {
|
||||
return tile.width;
|
||||
})[0],
|
||||
iiifInfo.imageInfo.tiles.map(function (tile) {
|
||||
return tile.height;
|
||||
})[0],
|
||||
],
|
||||
resolutions:
|
||||
iiifInfo.imageInfo.tiles === undefined
|
||||
? undefined
|
||||
: iiifInfo.imageInfo.tiles.map(function (tile) {
|
||||
return tile.scaleFactors;
|
||||
})[0],
|
||||
supports:
|
||||
iiifInfo.imageInfo.extraFeatures === undefined
|
||||
? levelProfile.supports
|
||||
: [...levelProfile.supports, ...iiifInfo.imageInfo.extraFeatures],
|
||||
formats: formats,
|
||||
qualities:
|
||||
iiifInfo.imageInfo.extraQualities === undefined
|
||||
? levelProfile.qualities
|
||||
: [...levelProfile.qualities, ...iiifInfo.imageInfo.extraQualities],
|
||||
preferredFormat: preferredFormat,
|
||||
};
|
||||
}
|
||||
|
||||
const versionFunctions = {};
|
||||
versionFunctions[Versions.VERSION1] = generateVersion1Options;
|
||||
versionFunctions[Versions.VERSION2] = generateVersion2Options;
|
||||
versionFunctions[Versions.VERSION3] = generateVersion3Options;
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Format for transforming IIIF Image API image information responses into
|
||||
* IIIF tile source ready options
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class IIIFInfo {
|
||||
/**
|
||||
* @param {string|ImageInformationResponse} imageInfo
|
||||
* Deserialized image information JSON response object or JSON response as string
|
||||
*/
|
||||
constructor(imageInfo) {
|
||||
this.setImageInfo(imageInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string|ImageInformationResponse} imageInfo
|
||||
* Deserialized image information JSON response object or JSON response as string
|
||||
* @api
|
||||
*/
|
||||
setImageInfo(imageInfo) {
|
||||
if (typeof imageInfo == 'string') {
|
||||
this.imageInfo = JSON.parse(imageInfo);
|
||||
} else {
|
||||
this.imageInfo = imageInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Versions} Major IIIF version.
|
||||
* @api
|
||||
*/
|
||||
getImageApiVersion() {
|
||||
if (this.imageInfo === undefined) {
|
||||
return;
|
||||
}
|
||||
let context = this.imageInfo['@context'] || 'ol-no-context';
|
||||
if (typeof context == 'string') {
|
||||
context = [context];
|
||||
}
|
||||
for (let i = 0; i < context.length; i++) {
|
||||
switch (context[i]) {
|
||||
case 'http://library.stanford.edu/iiif/image-api/1.1/context.json':
|
||||
case 'http://iiif.io/api/image/1/context.json':
|
||||
return Versions.VERSION1;
|
||||
case 'http://iiif.io/api/image/2/context.json':
|
||||
return Versions.VERSION2;
|
||||
case 'http://iiif.io/api/image/3/context.json':
|
||||
return Versions.VERSION3;
|
||||
case 'ol-no-context':
|
||||
// Image API 1.0 has no '@context'
|
||||
if (
|
||||
this.getComplianceLevelEntryFromProfile(Versions.VERSION1) &&
|
||||
this.imageInfo.identifier
|
||||
) {
|
||||
return Versions.VERSION1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
assert(false, 61);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Versions} version Optional IIIF image API version
|
||||
* @return {string} Compliance level as it appears in the IIIF image information
|
||||
* response.
|
||||
*/
|
||||
getComplianceLevelEntryFromProfile(version) {
|
||||
if (this.imageInfo === undefined || this.imageInfo.profile === undefined) {
|
||||
return;
|
||||
}
|
||||
if (version === undefined) {
|
||||
version = this.getImageApiVersion();
|
||||
}
|
||||
switch (version) {
|
||||
case Versions.VERSION1:
|
||||
if (COMPLIANCE_VERSION1.test(this.imageInfo.profile)) {
|
||||
return this.imageInfo.profile;
|
||||
}
|
||||
break;
|
||||
case Versions.VERSION3:
|
||||
if (COMPLIANCE_VERSION3.test(this.imageInfo.profile)) {
|
||||
return this.imageInfo.profile;
|
||||
}
|
||||
break;
|
||||
case Versions.VERSION2:
|
||||
if (
|
||||
typeof this.imageInfo.profile === 'string' &&
|
||||
COMPLIANCE_VERSION2.test(this.imageInfo.profile)
|
||||
) {
|
||||
return this.imageInfo.profile;
|
||||
}
|
||||
if (
|
||||
Array.isArray(this.imageInfo.profile) &&
|
||||
this.imageInfo.profile.length > 0 &&
|
||||
typeof this.imageInfo.profile[0] === 'string' &&
|
||||
COMPLIANCE_VERSION2.test(this.imageInfo.profile[0])
|
||||
) {
|
||||
return this.imageInfo.profile[0];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Versions} version Optional IIIF image API version
|
||||
* @return {string} Compliance level, on of 'level0', 'level1' or 'level2' or undefined
|
||||
*/
|
||||
getComplianceLevelFromProfile(version) {
|
||||
const complianceLevel = this.getComplianceLevelEntryFromProfile(version);
|
||||
if (complianceLevel === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const level = complianceLevel.match(/level[0-2](?:\.json)?$/g);
|
||||
return Array.isArray(level) ? level[0].replace('.json', '') : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {SupportedFeatures} Image formats, qualities and region / size calculation
|
||||
* methods that are supported by the IIIF service.
|
||||
*/
|
||||
getComplianceLevelSupportedFeatures() {
|
||||
if (this.imageInfo === undefined) {
|
||||
return;
|
||||
}
|
||||
const version = this.getImageApiVersion();
|
||||
const level = this.getComplianceLevelFromProfile(version);
|
||||
if (level === undefined) {
|
||||
return IIIF_PROFILE_VALUES['none']['none'];
|
||||
}
|
||||
return IIIF_PROFILE_VALUES[version][level];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PreferredOptions} [opt_preferredOptions] Optional options for preferred format and quality.
|
||||
* @return {import("../source/IIIF.js").Options} IIIF tile source ready constructor options.
|
||||
* @api
|
||||
*/
|
||||
getTileSourceOptions(opt_preferredOptions) {
|
||||
const options = opt_preferredOptions || {},
|
||||
version = this.getImageApiVersion();
|
||||
if (version === undefined) {
|
||||
return;
|
||||
}
|
||||
const imageOptions =
|
||||
version === undefined ? undefined : versionFunctions[version](this);
|
||||
if (imageOptions === undefined) {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
url: imageOptions.url,
|
||||
version: version,
|
||||
size: [this.imageInfo.width, this.imageInfo.height],
|
||||
sizes: imageOptions.sizes,
|
||||
format:
|
||||
options.format !== undefined &&
|
||||
includes(imageOptions.formats, options.format)
|
||||
? options.format
|
||||
: imageOptions.preferredFormat !== undefined
|
||||
? imageOptions.preferredFormat
|
||||
: 'jpg',
|
||||
supports: imageOptions.supports,
|
||||
quality:
|
||||
options.quality && includes(imageOptions.qualities, options.quality)
|
||||
? options.quality
|
||||
: includes(imageOptions.qualities, 'native')
|
||||
? 'native'
|
||||
: 'default',
|
||||
resolutions: Array.isArray(imageOptions.resolutions)
|
||||
? imageOptions.resolutions.sort(function (a, b) {
|
||||
return b - a;
|
||||
})
|
||||
: undefined,
|
||||
tileSize: imageOptions.tileSize,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default IIIFInfo;
|
||||
210
node_modules/ol/src/format/JSONFeature.js
generated
vendored
Normal file
210
node_modules/ol/src/format/JSONFeature.js
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* @module ol/format/JSONFeature
|
||||
*/
|
||||
import FeatureFormat from './Feature.js';
|
||||
import {abstract} from '../util.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for JSON feature formats.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
class JSONFeature extends FeatureFormat {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./Feature.js").Type} Format.
|
||||
*/
|
||||
getType() {
|
||||
return 'json';
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a feature. Only works for a single feature. Use `readFeatures` to
|
||||
* read a feature collection.
|
||||
*
|
||||
* @param {ArrayBuffer|Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
* @api
|
||||
*/
|
||||
readFeature(source, opt_options) {
|
||||
return this.readFeatureFromObject(
|
||||
getObject(source),
|
||||
this.getReadOptions(source, opt_options)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all features. Works with both a single feature and a feature
|
||||
* collection.
|
||||
*
|
||||
* @param {ArrayBuffer|Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
* @api
|
||||
*/
|
||||
readFeatures(source, opt_options) {
|
||||
return this.readFeaturesFromObject(
|
||||
getObject(source),
|
||||
this.getReadOptions(source, opt_options)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Object} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromObject(object, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Object} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromObject(object, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a geometry.
|
||||
*
|
||||
* @param {ArrayBuffer|Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
* @api
|
||||
*/
|
||||
readGeometry(source, opt_options) {
|
||||
return this.readGeometryFromObject(
|
||||
getObject(source),
|
||||
this.getReadOptions(source, opt_options)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Object} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromObject(object, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection.
|
||||
*
|
||||
* @param {ArrayBuffer|Document|Element|Object|string} source Source.
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
* @api
|
||||
*/
|
||||
readProjection(source) {
|
||||
return this.readProjectionFromObject(getObject(source));
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Object} object Object.
|
||||
* @protected
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjectionFromObject(object) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature as string.
|
||||
*
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Encoded feature.
|
||||
* @api
|
||||
*/
|
||||
writeFeature(feature, opt_options) {
|
||||
return JSON.stringify(this.writeFeatureObject(feature, opt_options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
writeFeatureObject(feature, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features as string.
|
||||
*
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Encoded features.
|
||||
* @api
|
||||
*/
|
||||
writeFeatures(features, opt_options) {
|
||||
return JSON.stringify(this.writeFeaturesObject(features, opt_options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
writeFeaturesObject(features, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a geometry as string.
|
||||
*
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Encoded geometry.
|
||||
* @api
|
||||
*/
|
||||
writeGeometry(geometry, opt_options) {
|
||||
return JSON.stringify(this.writeGeometryObject(geometry, opt_options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
writeGeometryObject(geometry, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
function getObject(source) {
|
||||
if (typeof source === 'string') {
|
||||
const object = JSON.parse(source);
|
||||
return object ? /** @type {Object} */ (object) : null;
|
||||
} else if (source !== null) {
|
||||
return source;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default JSONFeature;
|
||||
3368
node_modules/ol/src/format/KML.js
generated
vendored
Normal file
3368
node_modules/ol/src/format/KML.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
437
node_modules/ol/src/format/MVT.js
generated
vendored
Normal file
437
node_modules/ol/src/format/MVT.js
generated
vendored
Normal file
@@ -0,0 +1,437 @@
|
||||
/**
|
||||
* @module ol/format/MVT
|
||||
*/
|
||||
//FIXME Implement projection handling
|
||||
|
||||
import FeatureFormat, {transformGeometryWithOptions} from './Feature.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import MultiPoint from '../geom/MultiPoint.js';
|
||||
import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import PBF from 'pbf';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import Projection from '../proj/Projection.js';
|
||||
import RenderFeature from '../render/Feature.js';
|
||||
import Units from '../proj/Units.js';
|
||||
import {assert} from '../asserts.js';
|
||||
import {get} from '../proj.js';
|
||||
import {inflateEnds} from '../geom/flat/orient.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {import("../Feature.js").FeatureClass} [featureClass] Class for features returned by
|
||||
* {@link module:ol/format/MVT~MVT#readFeatures}. Set to {@link module:ol/Feature~Feature} to get full editing and geometry
|
||||
* support at the cost of decreased rendering performance. The default is
|
||||
* {@link module:ol/render/Feature~RenderFeature}, which is optimized for rendering and hit detection.
|
||||
* @property {string} [geometryName='geometry'] Geometry name to use when creating features.
|
||||
* @property {string} [layerName='layer'] Name of the feature attribute that holds the layer name.
|
||||
* @property {Array<string>} [layers] Layers to read features from. If not provided, features will be read from all
|
||||
* @property {string} [idProperty] Optional property that will be assigned as the feature id and removed from the properties.
|
||||
* layers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading data in the Mapbox MVT format.
|
||||
*
|
||||
* @param {Options} [opt_options] Options.
|
||||
* @api
|
||||
*/
|
||||
class MVT extends FeatureFormat {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {Projection}
|
||||
*/
|
||||
this.dataProjection = new Projection({
|
||||
code: '',
|
||||
units: Units.TILE_PIXELS,
|
||||
});
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../Feature.js").FeatureClass}
|
||||
*/
|
||||
this.featureClass_ = options.featureClass
|
||||
? options.featureClass
|
||||
: RenderFeature;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.geometryName_ = options.geometryName;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.layerName_ = options.layerName ? options.layerName : 'layer';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<string>|null}
|
||||
*/
|
||||
this.layers_ = options.layers ? options.layers : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.idProperty_ = options.idProperty;
|
||||
|
||||
this.supportedMediaTypes = [
|
||||
'application/vnd.mapbox-vector-tile',
|
||||
'application/x-protobuf',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the raw geometry from the pbf offset stored in a raw feature's geometry
|
||||
* property.
|
||||
* @param {PBF} pbf PBF.
|
||||
* @param {Object} feature Raw feature.
|
||||
* @param {Array<number>} flatCoordinates Array to store flat coordinates in.
|
||||
* @param {Array<number>} ends Array to store ends in.
|
||||
* @private
|
||||
*/
|
||||
readRawGeometry_(pbf, feature, flatCoordinates, ends) {
|
||||
pbf.pos = feature.geometry;
|
||||
|
||||
const end = pbf.readVarint() + pbf.pos;
|
||||
let cmd = 1;
|
||||
let length = 0;
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
let coordsLen = 0;
|
||||
let currentEnd = 0;
|
||||
|
||||
while (pbf.pos < end) {
|
||||
if (!length) {
|
||||
const cmdLen = pbf.readVarint();
|
||||
cmd = cmdLen & 0x7;
|
||||
length = cmdLen >> 3;
|
||||
}
|
||||
|
||||
length--;
|
||||
|
||||
if (cmd === 1 || cmd === 2) {
|
||||
x += pbf.readSVarint();
|
||||
y += pbf.readSVarint();
|
||||
|
||||
if (cmd === 1) {
|
||||
// moveTo
|
||||
if (coordsLen > currentEnd) {
|
||||
ends.push(coordsLen);
|
||||
currentEnd = coordsLen;
|
||||
}
|
||||
}
|
||||
|
||||
flatCoordinates.push(x, y);
|
||||
coordsLen += 2;
|
||||
} else if (cmd === 7) {
|
||||
if (coordsLen > currentEnd) {
|
||||
// close polygon
|
||||
flatCoordinates.push(
|
||||
flatCoordinates[currentEnd],
|
||||
flatCoordinates[currentEnd + 1]
|
||||
);
|
||||
coordsLen += 2;
|
||||
}
|
||||
} else {
|
||||
assert(false, 59); // Invalid command found in the PBF
|
||||
}
|
||||
}
|
||||
|
||||
if (coordsLen > currentEnd) {
|
||||
ends.push(coordsLen);
|
||||
currentEnd = coordsLen;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {PBF} pbf PBF
|
||||
* @param {Object} rawFeature Raw Mapbox feature.
|
||||
* @param {import("./Feature.js").ReadOptions} options Read options.
|
||||
* @return {import("../Feature.js").FeatureLike|null} Feature.
|
||||
*/
|
||||
createFeature_(pbf, rawFeature, options) {
|
||||
const type = rawFeature.type;
|
||||
if (type === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let feature;
|
||||
const values = rawFeature.properties;
|
||||
|
||||
let id;
|
||||
if (!this.idProperty_) {
|
||||
id = rawFeature.id;
|
||||
} else {
|
||||
id = values[this.idProperty_];
|
||||
delete values[this.idProperty_];
|
||||
}
|
||||
|
||||
values[this.layerName_] = rawFeature.layer.name;
|
||||
|
||||
const flatCoordinates = /** @type {Array<number>} */ ([]);
|
||||
const ends = /** @type {Array<number>} */ ([]);
|
||||
this.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);
|
||||
|
||||
const geometryType = getGeometryType(type, ends.length);
|
||||
|
||||
if (this.featureClass_ === RenderFeature) {
|
||||
feature = new this.featureClass_(
|
||||
geometryType,
|
||||
flatCoordinates,
|
||||
ends,
|
||||
values,
|
||||
id
|
||||
);
|
||||
feature.transform(options.dataProjection);
|
||||
} else {
|
||||
let geom;
|
||||
if (geometryType == 'Polygon') {
|
||||
const endss = inflateEnds(flatCoordinates, ends);
|
||||
geom =
|
||||
endss.length > 1
|
||||
? new MultiPolygon(flatCoordinates, GeometryLayout.XY, endss)
|
||||
: new Polygon(flatCoordinates, GeometryLayout.XY, ends);
|
||||
} else {
|
||||
geom =
|
||||
geometryType === 'Point'
|
||||
? new Point(flatCoordinates, GeometryLayout.XY)
|
||||
: geometryType === 'LineString'
|
||||
? new LineString(flatCoordinates, GeometryLayout.XY)
|
||||
: geometryType === 'MultiPoint'
|
||||
? new MultiPoint(flatCoordinates, GeometryLayout.XY)
|
||||
: geometryType === 'MultiLineString'
|
||||
? new MultiLineString(flatCoordinates, GeometryLayout.XY, ends)
|
||||
: null;
|
||||
}
|
||||
const ctor = /** @type {typeof import("../Feature.js").default} */ (
|
||||
this.featureClass_
|
||||
);
|
||||
feature = new ctor();
|
||||
if (this.geometryName_) {
|
||||
feature.setGeometryName(this.geometryName_);
|
||||
}
|
||||
const geometry = transformGeometryWithOptions(geom, false, options);
|
||||
feature.setGeometry(geometry);
|
||||
if (id !== undefined) {
|
||||
feature.setId(id);
|
||||
}
|
||||
feature.setProperties(values, true);
|
||||
}
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./Feature.js").Type} Format.
|
||||
*/
|
||||
getType() {
|
||||
return 'arraybuffer';
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all features.
|
||||
*
|
||||
* @param {ArrayBuffer} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {Array<import("../Feature.js").FeatureLike>} Features.
|
||||
* @api
|
||||
*/
|
||||
readFeatures(source, opt_options) {
|
||||
const layers = this.layers_;
|
||||
const options = /** @type {import("./Feature.js").ReadOptions} */ (
|
||||
this.adaptOptions(opt_options)
|
||||
);
|
||||
const dataProjection = get(options.dataProjection);
|
||||
dataProjection.setWorldExtent(options.extent);
|
||||
options.dataProjection = dataProjection;
|
||||
|
||||
const pbf = new PBF(/** @type {ArrayBuffer} */ (source));
|
||||
const pbfLayers = pbf.readFields(layersPBFReader, {});
|
||||
const features = [];
|
||||
for (const name in pbfLayers) {
|
||||
if (layers && layers.indexOf(name) == -1) {
|
||||
continue;
|
||||
}
|
||||
const pbfLayer = pbfLayers[name];
|
||||
|
||||
const extent = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;
|
||||
dataProjection.setExtent(extent);
|
||||
|
||||
for (let i = 0, ii = pbfLayer.length; i < ii; ++i) {
|
||||
const rawFeature = readRawFeature(pbf, pbfLayer, i);
|
||||
const feature = this.createFeature_(pbf, rawFeature, options);
|
||||
if (feature !== null) {
|
||||
features.push(feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection from the source.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
* @api
|
||||
*/
|
||||
readProjection(source) {
|
||||
return this.dataProjection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the layers that features will be read from.
|
||||
* @param {Array<string>} layers Layers.
|
||||
* @api
|
||||
*/
|
||||
setLayers(layers) {
|
||||
this.layers_ = layers;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reader callback for parsing layers.
|
||||
* @param {number} tag The tag.
|
||||
* @param {Object} layers The layers object.
|
||||
* @param {PBF} pbf The PBF.
|
||||
*/
|
||||
function layersPBFReader(tag, layers, pbf) {
|
||||
if (tag === 3) {
|
||||
const layer = {
|
||||
keys: [],
|
||||
values: [],
|
||||
features: [],
|
||||
};
|
||||
const end = pbf.readVarint() + pbf.pos;
|
||||
pbf.readFields(layerPBFReader, layer, end);
|
||||
layer.length = layer.features.length;
|
||||
if (layer.length) {
|
||||
layers[layer.name] = layer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reader callback for parsing layer.
|
||||
* @param {number} tag The tag.
|
||||
* @param {Object} layer The layer object.
|
||||
* @param {PBF} pbf The PBF.
|
||||
*/
|
||||
function layerPBFReader(tag, layer, pbf) {
|
||||
if (tag === 15) {
|
||||
layer.version = pbf.readVarint();
|
||||
} else if (tag === 1) {
|
||||
layer.name = pbf.readString();
|
||||
} else if (tag === 5) {
|
||||
layer.extent = pbf.readVarint();
|
||||
} else if (tag === 2) {
|
||||
layer.features.push(pbf.pos);
|
||||
} else if (tag === 3) {
|
||||
layer.keys.push(pbf.readString());
|
||||
} else if (tag === 4) {
|
||||
let value = null;
|
||||
const end = pbf.readVarint() + pbf.pos;
|
||||
while (pbf.pos < end) {
|
||||
tag = pbf.readVarint() >> 3;
|
||||
value =
|
||||
tag === 1
|
||||
? pbf.readString()
|
||||
: tag === 2
|
||||
? pbf.readFloat()
|
||||
: tag === 3
|
||||
? pbf.readDouble()
|
||||
: tag === 4
|
||||
? pbf.readVarint64()
|
||||
: tag === 5
|
||||
? pbf.readVarint()
|
||||
: tag === 6
|
||||
? pbf.readSVarint()
|
||||
: tag === 7
|
||||
? pbf.readBoolean()
|
||||
: null;
|
||||
}
|
||||
layer.values.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reader callback for parsing feature.
|
||||
* @param {number} tag The tag.
|
||||
* @param {Object} feature The feature object.
|
||||
* @param {PBF} pbf The PBF.
|
||||
*/
|
||||
function featurePBFReader(tag, feature, pbf) {
|
||||
if (tag == 1) {
|
||||
feature.id = pbf.readVarint();
|
||||
} else if (tag == 2) {
|
||||
const end = pbf.readVarint() + pbf.pos;
|
||||
while (pbf.pos < end) {
|
||||
const key = feature.layer.keys[pbf.readVarint()];
|
||||
const value = feature.layer.values[pbf.readVarint()];
|
||||
feature.properties[key] = value;
|
||||
}
|
||||
} else if (tag == 3) {
|
||||
feature.type = pbf.readVarint();
|
||||
} else if (tag == 4) {
|
||||
feature.geometry = pbf.pos;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a raw feature from the pbf offset stored at index `i` in the raw layer.
|
||||
* @param {PBF} pbf PBF.
|
||||
* @param {Object} layer Raw layer.
|
||||
* @param {number} i Index of the feature in the raw layer's `features` array.
|
||||
* @return {Object} Raw feature.
|
||||
*/
|
||||
function readRawFeature(pbf, layer, i) {
|
||||
pbf.pos = layer.features[i];
|
||||
const end = pbf.readVarint() + pbf.pos;
|
||||
|
||||
const feature = {
|
||||
layer: layer,
|
||||
type: 0,
|
||||
properties: {},
|
||||
};
|
||||
pbf.readFields(featurePBFReader, feature, end);
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} type The raw feature's geometry type
|
||||
* @param {number} numEnds Number of ends of the flat coordinates of the
|
||||
* geometry.
|
||||
* @return {import("../geom/Geometry.js").Type} The geometry type.
|
||||
*/
|
||||
function getGeometryType(type, numEnds) {
|
||||
/** @type {import("../geom/Geometry.js").Type} */
|
||||
let geometryType;
|
||||
if (type === 1) {
|
||||
geometryType = numEnds === 1 ? 'Point' : 'MultiPoint';
|
||||
} else if (type === 2) {
|
||||
geometryType = numEnds === 1 ? 'LineString' : 'MultiLineString';
|
||||
} else if (type === 3) {
|
||||
geometryType = 'Polygon';
|
||||
// MultiPolygon not relevant for rendering - winding order determines
|
||||
// outer rings of polygons.
|
||||
}
|
||||
return geometryType;
|
||||
}
|
||||
|
||||
export default MVT;
|
||||
197
node_modules/ol/src/format/OSMXML.js
generated
vendored
Normal file
197
node_modules/ol/src/format/OSMXML.js
generated
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @module ol/format/OSMXML
|
||||
*/
|
||||
// FIXME add typedef for stack state objects
|
||||
import Feature from '../Feature.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import XMLFeature from './XMLFeature.js';
|
||||
import {extend} from '../array.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {isEmpty} from '../obj.js';
|
||||
import {makeStructureNS, pushParseAndPop} from '../xml.js';
|
||||
import {transformGeometryWithOptions} from './Feature.js';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array<null>}
|
||||
*/
|
||||
const NAMESPACE_URIS = [null];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const WAY_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'nd': readNd,
|
||||
'tag': readTag,
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'node': readNode,
|
||||
'way': readWay,
|
||||
});
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading data in the
|
||||
* [OSMXML format](https://wiki.openstreetmap.org/wiki/OSM_XML).
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class OSMXML extends XMLFeature {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
/**
|
||||
* @type {import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.dataProjection = getProjection('EPSG:4326');
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromNode(node, opt_options) {
|
||||
const options = this.getReadOptions(node, opt_options);
|
||||
if (node.localName == 'osm') {
|
||||
const state = pushParseAndPop(
|
||||
{
|
||||
nodes: {},
|
||||
ways: [],
|
||||
features: [],
|
||||
},
|
||||
PARSERS,
|
||||
node,
|
||||
[options]
|
||||
);
|
||||
// parse nodes in ways
|
||||
for (let j = 0; j < state.ways.length; j++) {
|
||||
const values = /** @type {Object} */ (state.ways[j]);
|
||||
/** @type {Array<number>} */
|
||||
const flatCoordinates = [];
|
||||
for (let i = 0, ii = values.ndrefs.length; i < ii; i++) {
|
||||
const point = state.nodes[values.ndrefs[i]];
|
||||
extend(flatCoordinates, point);
|
||||
}
|
||||
let geometry;
|
||||
if (values.ndrefs[0] == values.ndrefs[values.ndrefs.length - 1]) {
|
||||
// closed way
|
||||
geometry = new Polygon(flatCoordinates, GeometryLayout.XY, [
|
||||
flatCoordinates.length,
|
||||
]);
|
||||
} else {
|
||||
geometry = new LineString(flatCoordinates, GeometryLayout.XY);
|
||||
}
|
||||
transformGeometryWithOptions(geometry, false, options);
|
||||
const feature = new Feature(geometry);
|
||||
if (values.id !== undefined) {
|
||||
feature.setId(values.id);
|
||||
}
|
||||
feature.setProperties(values.tags, true);
|
||||
state.features.push(feature);
|
||||
}
|
||||
if (state.features) {
|
||||
return state.features;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const NODE_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'tag': readTag,
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function readNode(node, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").ReadOptions} */ (
|
||||
objectStack[0]
|
||||
);
|
||||
const state = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
const id = node.getAttribute('id');
|
||||
/** @type {import("../coordinate.js").Coordinate} */
|
||||
const coordinates = [
|
||||
parseFloat(node.getAttribute('lon')),
|
||||
parseFloat(node.getAttribute('lat')),
|
||||
];
|
||||
state.nodes[id] = coordinates;
|
||||
|
||||
const values = pushParseAndPop(
|
||||
{
|
||||
tags: {},
|
||||
},
|
||||
NODE_PARSERS,
|
||||
node,
|
||||
objectStack
|
||||
);
|
||||
if (!isEmpty(values.tags)) {
|
||||
const geometry = new Point(coordinates);
|
||||
transformGeometryWithOptions(geometry, false, options);
|
||||
const feature = new Feature(geometry);
|
||||
if (id !== undefined) {
|
||||
feature.setId(id);
|
||||
}
|
||||
feature.setProperties(values.tags, true);
|
||||
state.features.push(feature);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function readWay(node, objectStack) {
|
||||
const id = node.getAttribute('id');
|
||||
const values = pushParseAndPop(
|
||||
{
|
||||
id: id,
|
||||
ndrefs: [],
|
||||
tags: {},
|
||||
},
|
||||
WAY_PARSERS,
|
||||
node,
|
||||
objectStack
|
||||
);
|
||||
const state = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
state.ways.push(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function readNd(node, objectStack) {
|
||||
const values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
values.ndrefs.push(node.getAttribute('ref'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
*/
|
||||
function readTag(node, objectStack) {
|
||||
const values = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
values.tags[node.getAttribute('k')] = node.getAttribute('v');
|
||||
}
|
||||
|
||||
export default OSMXML;
|
||||
325
node_modules/ol/src/format/OWS.js
generated
vendored
Normal file
325
node_modules/ol/src/format/OWS.js
generated
vendored
Normal file
@@ -0,0 +1,325 @@
|
||||
/**
|
||||
* @module ol/format/OWS
|
||||
*/
|
||||
import XML from './XML.js';
|
||||
import {
|
||||
makeObjectPropertyPusher,
|
||||
makeObjectPropertySetter,
|
||||
makeStructureNS,
|
||||
pushParseAndPop,
|
||||
} from '../xml.js';
|
||||
import {readHref} from './xlink.js';
|
||||
import {readString} from './xsd.js';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array<null|string>}
|
||||
*/
|
||||
const NAMESPACE_URIS = [null, 'http://www.opengis.net/ows/1.1'];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'ServiceIdentification': makeObjectPropertySetter(readServiceIdentification),
|
||||
'ServiceProvider': makeObjectPropertySetter(readServiceProvider),
|
||||
'OperationsMetadata': makeObjectPropertySetter(readOperationsMetadata),
|
||||
});
|
||||
|
||||
class OWS extends XML {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @return {Object} Object
|
||||
*/
|
||||
readFromNode(node) {
|
||||
const owsObject = pushParseAndPop({}, PARSERS, node, []);
|
||||
return owsObject ? owsObject : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const ADDRESS_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'DeliveryPoint': makeObjectPropertySetter(readString),
|
||||
'City': makeObjectPropertySetter(readString),
|
||||
'AdministrativeArea': makeObjectPropertySetter(readString),
|
||||
'PostalCode': makeObjectPropertySetter(readString),
|
||||
'Country': makeObjectPropertySetter(readString),
|
||||
'ElectronicMailAddress': makeObjectPropertySetter(readString),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const ALLOWED_VALUES_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Value': makeObjectPropertyPusher(readValue),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const CONSTRAINT_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'AllowedValues': makeObjectPropertySetter(readAllowedValues),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const CONTACT_INFO_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Phone': makeObjectPropertySetter(readPhone),
|
||||
'Address': makeObjectPropertySetter(readAddress),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const DCP_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'HTTP': makeObjectPropertySetter(readHttp),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const HTTP_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Get': makeObjectPropertyPusher(readGet),
|
||||
'Post': undefined, // TODO
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const OPERATION_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'DCP': makeObjectPropertySetter(readDcp),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const OPERATIONS_METADATA_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Operation': readOperation,
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const PHONE_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Voice': makeObjectPropertySetter(readString),
|
||||
'Facsimile': makeObjectPropertySetter(readString),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const REQUEST_METHOD_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Constraint': makeObjectPropertyPusher(readConstraint),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const SERVICE_CONTACT_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'IndividualName': makeObjectPropertySetter(readString),
|
||||
'PositionName': makeObjectPropertySetter(readString),
|
||||
'ContactInfo': makeObjectPropertySetter(readContactInfo),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const SERVICE_IDENTIFICATION_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Abstract': makeObjectPropertySetter(readString),
|
||||
'AccessConstraints': makeObjectPropertySetter(readString),
|
||||
'Fees': makeObjectPropertySetter(readString),
|
||||
'Title': makeObjectPropertySetter(readString),
|
||||
'ServiceTypeVersion': makeObjectPropertySetter(readString),
|
||||
'ServiceType': makeObjectPropertySetter(readString),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const SERVICE_PROVIDER_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'ProviderName': makeObjectPropertySetter(readString),
|
||||
'ProviderSite': makeObjectPropertySetter(readHref),
|
||||
'ServiceContact': makeObjectPropertySetter(readServiceContact),
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The address.
|
||||
*/
|
||||
function readAddress(node, objectStack) {
|
||||
return pushParseAndPop({}, ADDRESS_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The values.
|
||||
*/
|
||||
function readAllowedValues(node, objectStack) {
|
||||
return pushParseAndPop({}, ALLOWED_VALUES_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The constraint.
|
||||
*/
|
||||
function readConstraint(node, objectStack) {
|
||||
const name = node.getAttribute('name');
|
||||
if (!name) {
|
||||
return undefined;
|
||||
}
|
||||
return pushParseAndPop({'name': name}, CONSTRAINT_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The contact info.
|
||||
*/
|
||||
function readContactInfo(node, objectStack) {
|
||||
return pushParseAndPop({}, CONTACT_INFO_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The DCP.
|
||||
*/
|
||||
function readDcp(node, objectStack) {
|
||||
return pushParseAndPop({}, DCP_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The GET object.
|
||||
*/
|
||||
function readGet(node, objectStack) {
|
||||
const href = readHref(node);
|
||||
if (!href) {
|
||||
return undefined;
|
||||
}
|
||||
return pushParseAndPop(
|
||||
{'href': href},
|
||||
REQUEST_METHOD_PARSERS,
|
||||
node,
|
||||
objectStack
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The HTTP object.
|
||||
*/
|
||||
function readHttp(node, objectStack) {
|
||||
return pushParseAndPop({}, HTTP_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The operation.
|
||||
*/
|
||||
function readOperation(node, objectStack) {
|
||||
const name = node.getAttribute('name');
|
||||
const value = pushParseAndPop({}, OPERATION_PARSERS, node, objectStack);
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
const object = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
object[name] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The operations metadata.
|
||||
*/
|
||||
function readOperationsMetadata(node, objectStack) {
|
||||
return pushParseAndPop({}, OPERATIONS_METADATA_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The phone.
|
||||
*/
|
||||
function readPhone(node, objectStack) {
|
||||
return pushParseAndPop({}, PHONE_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The service identification.
|
||||
*/
|
||||
function readServiceIdentification(node, objectStack) {
|
||||
return pushParseAndPop({}, SERVICE_IDENTIFICATION_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The service contact.
|
||||
*/
|
||||
function readServiceContact(node, objectStack) {
|
||||
return pushParseAndPop({}, SERVICE_CONTACT_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} The service provider.
|
||||
*/
|
||||
function readServiceProvider(node, objectStack) {
|
||||
return pushParseAndPop({}, SERVICE_PROVIDER_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {string|undefined} The value.
|
||||
*/
|
||||
function readValue(node, objectStack) {
|
||||
return readString(node);
|
||||
}
|
||||
|
||||
export default OWS;
|
||||
357
node_modules/ol/src/format/Polyline.js
generated
vendored
Normal file
357
node_modules/ol/src/format/Polyline.js
generated
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
/**
|
||||
* @module ol/format/Polyline
|
||||
*/
|
||||
import Feature from '../Feature.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import TextFeature from './TextFeature.js';
|
||||
import {assert} from '../asserts.js';
|
||||
import {flipXY} from '../geom/flat/flip.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {getStrideForLayout} from '../geom/SimpleGeometry.js';
|
||||
import {inflateCoordinates} from '../geom/flat/inflate.js';
|
||||
import {transformGeometryWithOptions} from './Feature.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {number} [factor=1e5] The factor by which the coordinates values will be scaled.
|
||||
* @property {GeometryLayout} [geometryLayout='XY'] Layout of the
|
||||
* feature geometries created by the format reader.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading and writing data in the Encoded
|
||||
* Polyline Algorithm Format.
|
||||
*
|
||||
* When reading features, the coordinates are assumed to be in two dimensions
|
||||
* and in [latitude, longitude] order.
|
||||
*
|
||||
* As Polyline sources contain a single feature,
|
||||
* {@link module:ol/format/Polyline~Polyline#readFeatures} will return the
|
||||
* feature in an array.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Polyline extends TextFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Optional configuration object.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @type {import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.dataProjection = getProjection('EPSG:4326');
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.factor_ = options.factor ? options.factor : 1e5;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../geom/GeometryLayout").default}
|
||||
*/
|
||||
this.geometryLayout_ = options.geometryLayout
|
||||
? options.geometryLayout
|
||||
: GeometryLayout.XY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromText(text, opt_options) {
|
||||
const geometry = this.readGeometryFromText(text, opt_options);
|
||||
return new Feature(geometry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {Array<Feature>} Features.
|
||||
*/
|
||||
readFeaturesFromText(text, opt_options) {
|
||||
const feature = this.readFeatureFromText(text, opt_options);
|
||||
return [feature];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromText(text, opt_options) {
|
||||
const stride = getStrideForLayout(this.geometryLayout_);
|
||||
const flatCoordinates = decodeDeltas(text, stride, this.factor_);
|
||||
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
|
||||
const coordinates = inflateCoordinates(
|
||||
flatCoordinates,
|
||||
0,
|
||||
flatCoordinates.length,
|
||||
stride
|
||||
);
|
||||
const lineString = new LineString(coordinates, this.geometryLayout_);
|
||||
|
||||
return transformGeometryWithOptions(
|
||||
lineString,
|
||||
false,
|
||||
this.adaptOptions(opt_options)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default<LineString>} feature Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeFeatureText(feature, opt_options) {
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
return this.writeGeometryText(geometry, opt_options);
|
||||
} else {
|
||||
assert(false, 40); // Expected `feature` to have a geometry
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<import("../Feature.js").default<LineString>>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeFeaturesText(features, opt_options) {
|
||||
return this.writeFeatureText(features[0], opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LineString} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeGeometryText(geometry, opt_options) {
|
||||
geometry =
|
||||
/** @type {LineString} */
|
||||
(
|
||||
transformGeometryWithOptions(
|
||||
geometry,
|
||||
true,
|
||||
this.adaptOptions(opt_options)
|
||||
)
|
||||
);
|
||||
const flatCoordinates = geometry.getFlatCoordinates();
|
||||
const stride = geometry.getStride();
|
||||
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
|
||||
return encodeDeltas(flatCoordinates, stride, this.factor_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a list of n-dimensional points and return an encoded string
|
||||
*
|
||||
* Attention: This function will modify the passed array!
|
||||
*
|
||||
* @param {Array<number>} numbers A list of n-dimensional points.
|
||||
* @param {number} stride The number of dimension of the points in the list.
|
||||
* @param {number} [opt_factor] The factor by which the numbers will be
|
||||
* multiplied. The remaining decimal places will get rounded away.
|
||||
* Default is `1e5`.
|
||||
* @return {string} The encoded string.
|
||||
* @api
|
||||
*/
|
||||
export function encodeDeltas(numbers, stride, opt_factor) {
|
||||
const factor = opt_factor ? opt_factor : 1e5;
|
||||
let d;
|
||||
|
||||
const lastNumbers = new Array(stride);
|
||||
for (d = 0; d < stride; ++d) {
|
||||
lastNumbers[d] = 0;
|
||||
}
|
||||
|
||||
for (let i = 0, ii = numbers.length; i < ii; ) {
|
||||
for (d = 0; d < stride; ++d, ++i) {
|
||||
const num = numbers[i];
|
||||
const delta = num - lastNumbers[d];
|
||||
lastNumbers[d] = num;
|
||||
|
||||
numbers[i] = delta;
|
||||
}
|
||||
}
|
||||
|
||||
return encodeFloats(numbers, factor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a list of n-dimensional points from an encoded string
|
||||
*
|
||||
* @param {string} encoded An encoded string.
|
||||
* @param {number} stride The number of dimension of the points in the
|
||||
* encoded string.
|
||||
* @param {number} [opt_factor] The factor by which the resulting numbers will
|
||||
* be divided. Default is `1e5`.
|
||||
* @return {Array<number>} A list of n-dimensional points.
|
||||
* @api
|
||||
*/
|
||||
export function decodeDeltas(encoded, stride, opt_factor) {
|
||||
const factor = opt_factor ? opt_factor : 1e5;
|
||||
let d;
|
||||
|
||||
/** @type {Array<number>} */
|
||||
const lastNumbers = new Array(stride);
|
||||
for (d = 0; d < stride; ++d) {
|
||||
lastNumbers[d] = 0;
|
||||
}
|
||||
|
||||
const numbers = decodeFloats(encoded, factor);
|
||||
|
||||
for (let i = 0, ii = numbers.length; i < ii; ) {
|
||||
for (d = 0; d < stride; ++d, ++i) {
|
||||
lastNumbers[d] += numbers[i];
|
||||
|
||||
numbers[i] = lastNumbers[d];
|
||||
}
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a list of floating point numbers and return an encoded string
|
||||
*
|
||||
* Attention: This function will modify the passed array!
|
||||
*
|
||||
* @param {Array<number>} numbers A list of floating point numbers.
|
||||
* @param {number} [opt_factor] The factor by which the numbers will be
|
||||
* multiplied. The remaining decimal places will get rounded away.
|
||||
* Default is `1e5`.
|
||||
* @return {string} The encoded string.
|
||||
* @api
|
||||
*/
|
||||
export function encodeFloats(numbers, opt_factor) {
|
||||
const factor = opt_factor ? opt_factor : 1e5;
|
||||
for (let i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
numbers[i] = Math.round(numbers[i] * factor);
|
||||
}
|
||||
|
||||
return encodeSignedIntegers(numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a list of floating point numbers from an encoded string
|
||||
*
|
||||
* @param {string} encoded An encoded string.
|
||||
* @param {number} [opt_factor] The factor by which the result will be divided.
|
||||
* Default is `1e5`.
|
||||
* @return {Array<number>} A list of floating point numbers.
|
||||
* @api
|
||||
*/
|
||||
export function decodeFloats(encoded, opt_factor) {
|
||||
const factor = opt_factor ? opt_factor : 1e5;
|
||||
const numbers = decodeSignedIntegers(encoded);
|
||||
for (let i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
numbers[i] /= factor;
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a list of signed integers and return an encoded string
|
||||
*
|
||||
* Attention: This function will modify the passed array!
|
||||
*
|
||||
* @param {Array<number>} numbers A list of signed integers.
|
||||
* @return {string} The encoded string.
|
||||
*/
|
||||
export function encodeSignedIntegers(numbers) {
|
||||
for (let i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
const num = numbers[i];
|
||||
numbers[i] = num < 0 ? ~(num << 1) : num << 1;
|
||||
}
|
||||
return encodeUnsignedIntegers(numbers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a list of signed integers from an encoded string
|
||||
*
|
||||
* @param {string} encoded An encoded string.
|
||||
* @return {Array<number>} A list of signed integers.
|
||||
*/
|
||||
export function decodeSignedIntegers(encoded) {
|
||||
const numbers = decodeUnsignedIntegers(encoded);
|
||||
for (let i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
const num = numbers[i];
|
||||
numbers[i] = num & 1 ? ~(num >> 1) : num >> 1;
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a list of unsigned integers and return an encoded string
|
||||
*
|
||||
* @param {Array<number>} numbers A list of unsigned integers.
|
||||
* @return {string} The encoded string.
|
||||
*/
|
||||
export function encodeUnsignedIntegers(numbers) {
|
||||
let encoded = '';
|
||||
for (let i = 0, ii = numbers.length; i < ii; ++i) {
|
||||
encoded += encodeUnsignedInteger(numbers[i]);
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a list of unsigned integers from an encoded string
|
||||
*
|
||||
* @param {string} encoded An encoded string.
|
||||
* @return {Array<number>} A list of unsigned integers.
|
||||
*/
|
||||
export function decodeUnsignedIntegers(encoded) {
|
||||
const numbers = [];
|
||||
let current = 0;
|
||||
let shift = 0;
|
||||
for (let i = 0, ii = encoded.length; i < ii; ++i) {
|
||||
const b = encoded.charCodeAt(i) - 63;
|
||||
current |= (b & 0x1f) << shift;
|
||||
if (b < 0x20) {
|
||||
numbers.push(current);
|
||||
current = 0;
|
||||
shift = 0;
|
||||
} else {
|
||||
shift += 5;
|
||||
}
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode one single unsigned integer and return an encoded string
|
||||
*
|
||||
* @param {number} num Unsigned integer that should be encoded.
|
||||
* @return {string} The encoded string.
|
||||
*/
|
||||
export function encodeUnsignedInteger(num) {
|
||||
let value,
|
||||
encoded = '';
|
||||
while (num >= 0x20) {
|
||||
value = (0x20 | (num & 0x1f)) + 63;
|
||||
encoded += String.fromCharCode(value);
|
||||
num >>= 5;
|
||||
}
|
||||
value = num + 63;
|
||||
encoded += String.fromCharCode(value);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
export default Polyline;
|
||||
207
node_modules/ol/src/format/TextFeature.js
generated
vendored
Normal file
207
node_modules/ol/src/format/TextFeature.js
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
/**
|
||||
* @module ol/format/TextFeature
|
||||
*/
|
||||
import FeatureFormat from '../format/Feature.js';
|
||||
import {abstract} from '../util.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for text feature formats.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
class TextFeature extends FeatureFormat {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./Feature.js").Type} Format.
|
||||
*/
|
||||
getType() {
|
||||
return 'text';
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the feature from the source.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
* @api
|
||||
*/
|
||||
readFeature(source, opt_options) {
|
||||
return this.readFeatureFromText(
|
||||
getText(source),
|
||||
this.adaptOptions(opt_options)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromText(text, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the features from the source.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
* @api
|
||||
*/
|
||||
readFeatures(source, opt_options) {
|
||||
return this.readFeaturesFromText(
|
||||
getText(source),
|
||||
this.adaptOptions(opt_options)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromText(text, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the geometry from the source.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
* @api
|
||||
*/
|
||||
readGeometry(source, opt_options) {
|
||||
return this.readGeometryFromText(
|
||||
getText(source),
|
||||
this.adaptOptions(opt_options)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromText(text, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection from the source.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @return {import("../proj/Projection.js").default|undefined} Projection.
|
||||
* @api
|
||||
*/
|
||||
readProjection(source) {
|
||||
return this.readProjectionFromText(getText(source));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @protected
|
||||
* @return {import("../proj/Projection.js").default|undefined} Projection.
|
||||
*/
|
||||
readProjectionFromText(text) {
|
||||
return this.dataProjection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature as a string.
|
||||
*
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Encoded feature.
|
||||
* @api
|
||||
*/
|
||||
writeFeature(feature, opt_options) {
|
||||
return this.writeFeatureText(feature, this.adaptOptions(opt_options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {import("../Feature.js").default} feature Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeFeatureText(feature, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features as string.
|
||||
*
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Encoded features.
|
||||
* @api
|
||||
*/
|
||||
writeFeatures(features, opt_options) {
|
||||
return this.writeFeaturesText(features, this.adaptOptions(opt_options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeFeaturesText(features, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single geometry.
|
||||
*
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Geometry.
|
||||
* @api
|
||||
*/
|
||||
writeGeometry(geometry, opt_options) {
|
||||
return this.writeGeometryText(geometry, this.adaptOptions(opt_options));
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeGeometryText(geometry, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @return {string} Text.
|
||||
*/
|
||||
function getText(source) {
|
||||
if (typeof source === 'string') {
|
||||
return source;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export default TextFeature;
|
||||
447
node_modules/ol/src/format/TopoJSON.js
generated
vendored
Normal file
447
node_modules/ol/src/format/TopoJSON.js
generated
vendored
Normal file
@@ -0,0 +1,447 @@
|
||||
/**
|
||||
* @module ol/format/TopoJSON
|
||||
*/
|
||||
import Feature from '../Feature.js';
|
||||
import JSONFeature from './JSONFeature.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import MultiPoint from '../geom/MultiPoint.js';
|
||||
import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {transformGeometryWithOptions} from './Feature.js';
|
||||
|
||||
/**
|
||||
* @typedef {import("topojson-specification").Topology} TopoJSONTopology
|
||||
* @typedef {import("topojson-specification").GeometryCollection} TopoJSONGeometryCollection
|
||||
* @typedef {import("topojson-specification").GeometryObject} TopoJSONGeometry
|
||||
* @typedef {import("topojson-specification").Point} TopoJSONPoint
|
||||
* @typedef {import("topojson-specification").MultiPoint} TopoJSONMultiPoint
|
||||
* @typedef {import("topojson-specification").LineString} TopoJSONLineString
|
||||
* @typedef {import("topojson-specification").MultiLineString} TopoJSONMultiLineString
|
||||
* @typedef {import("topojson-specification").Polygon} TopoJSONPolygon
|
||||
* @typedef {import("topojson-specification").MultiPolygon} TopoJSONMultiPolygon
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {import("../proj.js").ProjectionLike} [dataProjection='EPSG:4326'] Default data projection.
|
||||
* @property {string} [layerName] Set the name of the TopoJSON topology
|
||||
* `objects`'s children as feature property with the specified name. This means
|
||||
* that when set to `'layer'`, a topology like
|
||||
* ```
|
||||
* {
|
||||
* "type": "Topology",
|
||||
* "objects": {
|
||||
* "example": {
|
||||
* "type": "GeometryCollection",
|
||||
* "geometries": []
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* will result in features that have a property `'layer'` set to `'example'`.
|
||||
* When not set, no property will be added to features.
|
||||
* @property {Array<string>} [layers] Names of the TopoJSON topology's
|
||||
* `objects`'s children to read features from. If not provided, features will
|
||||
* be read from all children.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Feature format for reading data in the TopoJSON format.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class TopoJSON extends JSONFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.layerName_ = options.layerName;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {?Array<string>}
|
||||
*/
|
||||
this.layers_ = options.layers ? options.layers : null;
|
||||
|
||||
/**
|
||||
* @type {import("../proj/Projection.js").default}
|
||||
*/
|
||||
this.dataProjection = getProjection(
|
||||
options.dataProjection ? options.dataProjection : 'EPSG:4326'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {Array<Feature>} Features.
|
||||
*/
|
||||
readFeaturesFromObject(object, opt_options) {
|
||||
if (object.type == 'Topology') {
|
||||
const topoJSONTopology = /** @type {TopoJSONTopology} */ (object);
|
||||
let transform,
|
||||
scale = null,
|
||||
translate = null;
|
||||
if (topoJSONTopology['transform']) {
|
||||
transform = topoJSONTopology['transform'];
|
||||
scale = transform['scale'];
|
||||
translate = transform['translate'];
|
||||
}
|
||||
const arcs = topoJSONTopology['arcs'];
|
||||
if (transform) {
|
||||
transformArcs(arcs, scale, translate);
|
||||
}
|
||||
/** @type {Array<Feature>} */
|
||||
const features = [];
|
||||
const topoJSONFeatures = topoJSONTopology['objects'];
|
||||
const property = this.layerName_;
|
||||
let feature;
|
||||
for (const objectName in topoJSONFeatures) {
|
||||
if (this.layers_ && this.layers_.indexOf(objectName) == -1) {
|
||||
continue;
|
||||
}
|
||||
if (topoJSONFeatures[objectName].type === 'GeometryCollection') {
|
||||
feature = /** @type {TopoJSONGeometryCollection} */ (
|
||||
topoJSONFeatures[objectName]
|
||||
);
|
||||
features.push.apply(
|
||||
features,
|
||||
readFeaturesFromGeometryCollection(
|
||||
feature,
|
||||
arcs,
|
||||
scale,
|
||||
translate,
|
||||
property,
|
||||
objectName,
|
||||
opt_options
|
||||
)
|
||||
);
|
||||
} else {
|
||||
feature = /** @type {TopoJSONGeometry} */ (
|
||||
topoJSONFeatures[objectName]
|
||||
);
|
||||
features.push(
|
||||
readFeatureFromGeometry(
|
||||
feature,
|
||||
arcs,
|
||||
scale,
|
||||
translate,
|
||||
property,
|
||||
objectName,
|
||||
opt_options
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return features;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} object Object.
|
||||
* @protected
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjectionFromObject(object) {
|
||||
return this.dataProjection;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, function(TopoJSONGeometry, Array, ...Array=): import("../geom/Geometry.js").default>}
|
||||
*/
|
||||
const GEOMETRY_READERS = {
|
||||
'Point': readPointGeometry,
|
||||
'LineString': readLineStringGeometry,
|
||||
'Polygon': readPolygonGeometry,
|
||||
'MultiPoint': readMultiPointGeometry,
|
||||
'MultiLineString': readMultiLineStringGeometry,
|
||||
'MultiPolygon': readMultiPolygonGeometry,
|
||||
};
|
||||
|
||||
/**
|
||||
* Concatenate arcs into a coordinate array.
|
||||
* @param {Array<number>} indices Indices of arcs to concatenate. Negative
|
||||
* values indicate arcs need to be reversed.
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>>} arcs Array of arcs (already
|
||||
* transformed).
|
||||
* @return {Array<import("../coordinate.js").Coordinate>} Coordinates array.
|
||||
*/
|
||||
function concatenateArcs(indices, arcs) {
|
||||
/** @type {Array<import("../coordinate.js").Coordinate>} */
|
||||
const coordinates = [];
|
||||
let index;
|
||||
for (let i = 0, ii = indices.length; i < ii; ++i) {
|
||||
index = indices[i];
|
||||
if (i > 0) {
|
||||
// splicing together arcs, discard last point
|
||||
coordinates.pop();
|
||||
}
|
||||
if (index >= 0) {
|
||||
// forward arc
|
||||
const arc = arcs[index];
|
||||
for (let j = 0, jj = arc.length; j < jj; ++j) {
|
||||
coordinates.push(arc[j].slice(0));
|
||||
}
|
||||
} else {
|
||||
// reverse arc
|
||||
const arc = arcs[~index];
|
||||
for (let j = arc.length - 1; j >= 0; --j) {
|
||||
coordinates.push(arc[j].slice(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a point from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONPoint} object TopoJSON object.
|
||||
* @param {Array<number>} scale Scale for each dimension.
|
||||
* @param {Array<number>} translate Translation for each dimension.
|
||||
* @return {Point} Geometry.
|
||||
*/
|
||||
function readPointGeometry(object, scale, translate) {
|
||||
const coordinates = object['coordinates'];
|
||||
if (scale && translate) {
|
||||
transformVertex(coordinates, scale, translate);
|
||||
}
|
||||
return new Point(coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multi-point from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONMultiPoint} object TopoJSON object.
|
||||
* @param {Array<number>} scale Scale for each dimension.
|
||||
* @param {Array<number>} translate Translation for each dimension.
|
||||
* @return {MultiPoint} Geometry.
|
||||
*/
|
||||
function readMultiPointGeometry(object, scale, translate) {
|
||||
const coordinates = object['coordinates'];
|
||||
if (scale && translate) {
|
||||
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
transformVertex(coordinates[i], scale, translate);
|
||||
}
|
||||
}
|
||||
return new MultiPoint(coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a linestring from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONLineString} object TopoJSON object.
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>>} arcs Array of arcs.
|
||||
* @return {LineString} Geometry.
|
||||
*/
|
||||
function readLineStringGeometry(object, arcs) {
|
||||
const coordinates = concatenateArcs(object['arcs'], arcs);
|
||||
return new LineString(coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multi-linestring from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONMultiLineString} object TopoJSON object.
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>>} arcs Array of arcs.
|
||||
* @return {MultiLineString} Geometry.
|
||||
*/
|
||||
function readMultiLineStringGeometry(object, arcs) {
|
||||
const coordinates = [];
|
||||
for (let i = 0, ii = object['arcs'].length; i < ii; ++i) {
|
||||
coordinates[i] = concatenateArcs(object['arcs'][i], arcs);
|
||||
}
|
||||
return new MultiLineString(coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a polygon from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONPolygon} object TopoJSON object.
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>>} arcs Array of arcs.
|
||||
* @return {Polygon} Geometry.
|
||||
*/
|
||||
function readPolygonGeometry(object, arcs) {
|
||||
const coordinates = [];
|
||||
for (let i = 0, ii = object['arcs'].length; i < ii; ++i) {
|
||||
coordinates[i] = concatenateArcs(object['arcs'][i], arcs);
|
||||
}
|
||||
return new Polygon(coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a multi-polygon from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONMultiPolygon} object TopoJSON object.
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>>} arcs Array of arcs.
|
||||
* @return {MultiPolygon} Geometry.
|
||||
*/
|
||||
function readMultiPolygonGeometry(object, arcs) {
|
||||
const coordinates = [];
|
||||
for (let i = 0, ii = object['arcs'].length; i < ii; ++i) {
|
||||
// for each polygon
|
||||
const polyArray = object['arcs'][i];
|
||||
const ringCoords = [];
|
||||
for (let j = 0, jj = polyArray.length; j < jj; ++j) {
|
||||
// for each ring
|
||||
ringCoords[j] = concatenateArcs(polyArray[j], arcs);
|
||||
}
|
||||
coordinates[i] = ringCoords;
|
||||
}
|
||||
return new MultiPolygon(coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create features from a TopoJSON GeometryCollection object.
|
||||
*
|
||||
* @param {TopoJSONGeometryCollection} collection TopoJSON Geometry
|
||||
* object.
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>>} arcs Array of arcs.
|
||||
* @param {Array<number>} scale Scale for each dimension.
|
||||
* @param {Array<number>} translate Translation for each dimension.
|
||||
* @param {string|undefined} property Property to set the `GeometryCollection`'s parent
|
||||
* object to.
|
||||
* @param {string} name Name of the `Topology`'s child object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {Array<Feature>} Array of features.
|
||||
*/
|
||||
function readFeaturesFromGeometryCollection(
|
||||
collection,
|
||||
arcs,
|
||||
scale,
|
||||
translate,
|
||||
property,
|
||||
name,
|
||||
opt_options
|
||||
) {
|
||||
const geometries = collection['geometries'];
|
||||
const features = [];
|
||||
for (let i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
features[i] = readFeatureFromGeometry(
|
||||
geometries[i],
|
||||
arcs,
|
||||
scale,
|
||||
translate,
|
||||
property,
|
||||
name,
|
||||
opt_options
|
||||
);
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a feature from a TopoJSON geometry object.
|
||||
*
|
||||
* @param {TopoJSONGeometry} object TopoJSON geometry object.
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>>} arcs Array of arcs.
|
||||
* @param {Array<number>} scale Scale for each dimension.
|
||||
* @param {Array<number>} translate Translation for each dimension.
|
||||
* @param {string|undefined} property Property to set the `GeometryCollection`'s parent
|
||||
* object to.
|
||||
* @param {string} name Name of the `Topology`'s child object.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {Feature} Feature.
|
||||
*/
|
||||
function readFeatureFromGeometry(
|
||||
object,
|
||||
arcs,
|
||||
scale,
|
||||
translate,
|
||||
property,
|
||||
name,
|
||||
opt_options
|
||||
) {
|
||||
let geometry = null;
|
||||
const type = object.type;
|
||||
if (type) {
|
||||
const geometryReader = GEOMETRY_READERS[type];
|
||||
if (type === 'Point' || type === 'MultiPoint') {
|
||||
geometry = geometryReader(object, scale, translate);
|
||||
} else {
|
||||
geometry = geometryReader(object, arcs);
|
||||
}
|
||||
geometry = transformGeometryWithOptions(geometry, false, opt_options);
|
||||
}
|
||||
const feature = new Feature({geometry: geometry});
|
||||
if (object.id !== undefined) {
|
||||
feature.setId(object.id);
|
||||
}
|
||||
let properties = object.properties;
|
||||
if (property) {
|
||||
if (!properties) {
|
||||
properties = {};
|
||||
}
|
||||
properties[property] = name;
|
||||
}
|
||||
if (properties) {
|
||||
feature.setProperties(properties, true);
|
||||
}
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a linear transform to array of arcs. The provided array of arcs is
|
||||
* modified in place.
|
||||
*
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>>} arcs Array of arcs.
|
||||
* @param {Array<number>} scale Scale for each dimension.
|
||||
* @param {Array<number>} translate Translation for each dimension.
|
||||
*/
|
||||
function transformArcs(arcs, scale, translate) {
|
||||
for (let i = 0, ii = arcs.length; i < ii; ++i) {
|
||||
transformArc(arcs[i], scale, translate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a linear transform to an arc. The provided arc is modified in place.
|
||||
*
|
||||
* @param {Array<import("../coordinate.js").Coordinate>} arc Arc.
|
||||
* @param {Array<number>} scale Scale for each dimension.
|
||||
* @param {Array<number>} translate Translation for each dimension.
|
||||
*/
|
||||
function transformArc(arc, scale, translate) {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
for (let i = 0, ii = arc.length; i < ii; ++i) {
|
||||
const vertex = arc[i];
|
||||
x += vertex[0];
|
||||
y += vertex[1];
|
||||
vertex[0] = x;
|
||||
vertex[1] = y;
|
||||
transformVertex(vertex, scale, translate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a linear transform to a vertex. The provided vertex is modified in
|
||||
* place.
|
||||
*
|
||||
* @param {import("../coordinate.js").Coordinate} vertex Vertex.
|
||||
* @param {Array<number>} scale Scale for each dimension.
|
||||
* @param {Array<number>} translate Translation for each dimension.
|
||||
*/
|
||||
function transformVertex(vertex, scale, translate) {
|
||||
vertex[0] = vertex[0] * scale[0] + translate[0];
|
||||
vertex[1] = vertex[1] * scale[1] + translate[1];
|
||||
}
|
||||
|
||||
export default TopoJSON;
|
||||
1373
node_modules/ol/src/format/WFS.js
generated
vendored
Normal file
1373
node_modules/ol/src/format/WFS.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
892
node_modules/ol/src/format/WKB.js
generated
vendored
Normal file
892
node_modules/ol/src/format/WKB.js
generated
vendored
Normal file
@@ -0,0 +1,892 @@
|
||||
/**
|
||||
* @module ol/format/WKB
|
||||
*/
|
||||
import Feature from '../Feature.js';
|
||||
import FeatureFormat, {transformGeometryWithOptions} from './Feature.js';
|
||||
import GeometryCollection from '../geom/GeometryCollection.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import MultiPoint from '../geom/MultiPoint.js';
|
||||
import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
|
||||
import SimpleGeometry from '../geom/SimpleGeometry.js';
|
||||
import {assign} from '../obj.js';
|
||||
|
||||
// WKB spec: https://www.ogc.org/standards/sfa
|
||||
// EWKB spec: https://raw.githubusercontent.com/postgis/postgis/2.1.0/doc/ZMSgeoms.txt
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @enum {number}
|
||||
*/
|
||||
const WKBGeometryType = {
|
||||
POINT: 1,
|
||||
LINE_STRING: 2,
|
||||
POLYGON: 3,
|
||||
MULTI_POINT: 4,
|
||||
MULTI_LINE_STRING: 5,
|
||||
MULTI_POLYGON: 6,
|
||||
GEOMETRY_COLLECTION: 7,
|
||||
|
||||
/*
|
||||
CIRCULAR_STRING: 8,
|
||||
COMPOUND_CURVE: 9,
|
||||
CURVE_POLYGON: 10,
|
||||
|
||||
MULTI_CURVE: 11,
|
||||
MULTI_SURFACE: 12,
|
||||
CURVE: 13,
|
||||
SURFACE: 14,
|
||||
*/
|
||||
|
||||
POLYHEDRAL_SURFACE: 15,
|
||||
TIN: 16,
|
||||
TRIANGLE: 17,
|
||||
};
|
||||
|
||||
class WkbReader {
|
||||
/**
|
||||
* @param {DataView} view source to read
|
||||
*/
|
||||
constructor(view) {
|
||||
this.view_ = view;
|
||||
this.pos_ = 0;
|
||||
|
||||
this.initialized_ = false;
|
||||
this.isLittleEndian_ = false;
|
||||
this.hasZ_ = false;
|
||||
this.hasM_ = false;
|
||||
/** @type {number|null} */
|
||||
this.srid_ = null;
|
||||
|
||||
this.layout_ = GeometryLayout.XY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} value
|
||||
*/
|
||||
readUint8() {
|
||||
return this.view_.getUint8(this.pos_++);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} [isLittleEndian] Whether read value as little endian
|
||||
* @return {number} value
|
||||
*/
|
||||
readUint32(isLittleEndian) {
|
||||
return this.view_.getUint32(
|
||||
(this.pos_ += 4) - 4,
|
||||
isLittleEndian !== undefined ? isLittleEndian : this.isLittleEndian_
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} [isLittleEndian] Whether read value as little endian
|
||||
* @return {number} value
|
||||
*/
|
||||
readDouble(isLittleEndian) {
|
||||
return this.view_.getFloat64(
|
||||
(this.pos_ += 8) - 8,
|
||||
isLittleEndian !== undefined ? isLittleEndian : this.isLittleEndian_
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import('../coordinate.js').Coordinate} coords for Point
|
||||
*/
|
||||
readPoint() {
|
||||
/** @type import('../coordinate.js').Coordinate */
|
||||
const coords = [];
|
||||
|
||||
coords.push(this.readDouble());
|
||||
coords.push(this.readDouble());
|
||||
if (this.hasZ_) {
|
||||
coords.push(this.readDouble());
|
||||
}
|
||||
if (this.hasM_) {
|
||||
coords.push(this.readDouble());
|
||||
}
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<import('../coordinate.js').Coordinate>} coords for LineString / LinearRing
|
||||
*/
|
||||
readLineString() {
|
||||
const numPoints = this.readUint32();
|
||||
|
||||
/** @type Array<import('../coordinate.js').Coordinate> */
|
||||
const coords = [];
|
||||
for (let i = 0; i < numPoints; i++) {
|
||||
coords.push(this.readPoint());
|
||||
}
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<import('../coordinate.js').Coordinate>>} coords for Polygon like
|
||||
*/
|
||||
readPolygon() {
|
||||
const numRings = this.readUint32();
|
||||
|
||||
/** @type Array<Array<import('../coordinate.js').Coordinate>> */
|
||||
const rings = [];
|
||||
for (let i = 0; i < numRings; i++) {
|
||||
rings.push(this.readLineString()); // as a LinearRing
|
||||
}
|
||||
|
||||
return rings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} [expectedTypeId] Expected WKB Type ID
|
||||
* @return {number} WKB Type ID
|
||||
*/
|
||||
readWkbHeader(expectedTypeId) {
|
||||
const byteOrder = this.readUint8();
|
||||
const isLittleEndian = byteOrder > 0;
|
||||
|
||||
const wkbType = this.readUint32(isLittleEndian);
|
||||
const wkbTypeThousandth = Math.floor((wkbType & 0x0fffffff) / 1000);
|
||||
const hasZ =
|
||||
Boolean(wkbType & 0x80000000) ||
|
||||
wkbTypeThousandth === 1 ||
|
||||
wkbTypeThousandth === 3;
|
||||
const hasM =
|
||||
Boolean(wkbType & 0x40000000) ||
|
||||
wkbTypeThousandth === 2 ||
|
||||
wkbTypeThousandth === 3;
|
||||
const hasSRID = Boolean(wkbType & 0x20000000);
|
||||
const typeId = (wkbType & 0x0fffffff) % 1000; // Assume 1000 is an upper limit for type ID
|
||||
const layout = ['XY', hasZ ? 'Z' : '', hasM ? 'M' : ''].join('');
|
||||
|
||||
const srid = hasSRID ? this.readUint32(isLittleEndian) : null;
|
||||
|
||||
if (expectedTypeId !== undefined && expectedTypeId !== typeId) {
|
||||
throw new Error('Unexpected WKB geometry type ' + typeId);
|
||||
}
|
||||
|
||||
if (this.initialized_) {
|
||||
// sanity checks
|
||||
if (this.isLittleEndian_ !== isLittleEndian) {
|
||||
throw new Error('Inconsistent endian');
|
||||
}
|
||||
if (this.layout_ !== layout) {
|
||||
throw new Error('Inconsistent geometry layout');
|
||||
}
|
||||
if (srid && this.srid_ !== srid) {
|
||||
throw new Error('Inconsistent coordinate system (SRID)');
|
||||
}
|
||||
} else {
|
||||
this.isLittleEndian_ = isLittleEndian;
|
||||
this.hasZ_ = hasZ;
|
||||
this.hasM_ = hasM;
|
||||
this.layout_ = layout;
|
||||
this.srid_ = srid;
|
||||
this.initialized_ = true;
|
||||
}
|
||||
|
||||
return typeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} typeId WKB Type ID
|
||||
* @return {any} values read
|
||||
*/
|
||||
readWkbPayload(typeId) {
|
||||
switch (typeId) {
|
||||
case WKBGeometryType.POINT:
|
||||
return this.readPoint();
|
||||
|
||||
case WKBGeometryType.LINE_STRING:
|
||||
return this.readLineString();
|
||||
|
||||
case WKBGeometryType.POLYGON:
|
||||
case WKBGeometryType.TRIANGLE:
|
||||
return this.readPolygon();
|
||||
|
||||
case WKBGeometryType.MULTI_POINT:
|
||||
return this.readMultiPoint();
|
||||
|
||||
case WKBGeometryType.MULTI_LINE_STRING:
|
||||
return this.readMultiLineString();
|
||||
|
||||
case WKBGeometryType.MULTI_POLYGON:
|
||||
case WKBGeometryType.POLYHEDRAL_SURFACE:
|
||||
case WKBGeometryType.TIN:
|
||||
return this.readMultiPolygon();
|
||||
|
||||
case WKBGeometryType.GEOMETRY_COLLECTION:
|
||||
return this.readGeometryCollection();
|
||||
|
||||
default:
|
||||
throw new Error(
|
||||
'Unsupported WKB geometry type ' + typeId + ' is found'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} expectedTypeId Expected WKB Type ID
|
||||
* @return {any} values read
|
||||
*/
|
||||
readWkbBlock(expectedTypeId) {
|
||||
return this.readWkbPayload(this.readWkbHeader(expectedTypeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Function} reader reader function for each item
|
||||
* @param {number} [expectedTypeId] Expected WKB Type ID
|
||||
* @return {any} values read
|
||||
*/
|
||||
readWkbCollection(reader, expectedTypeId) {
|
||||
const num = this.readUint32();
|
||||
|
||||
const items = [];
|
||||
for (let i = 0; i < num; i++) {
|
||||
const result = reader.call(this, expectedTypeId);
|
||||
if (result) {
|
||||
items.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<import('../coordinate.js').Coordinate>} coords for MultiPoint
|
||||
*/
|
||||
readMultiPoint() {
|
||||
return this.readWkbCollection(this.readWkbBlock, WKBGeometryType.POINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<import('../coordinate.js').Coordinate>>} coords for MultiLineString like
|
||||
*/
|
||||
readMultiLineString() {
|
||||
return this.readWkbCollection(
|
||||
this.readWkbBlock,
|
||||
WKBGeometryType.LINE_STRING
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<Array<import('../coordinate.js').Coordinate>>>} coords for MultiPolygon like
|
||||
*/
|
||||
readMultiPolygon() {
|
||||
return this.readWkbCollection(this.readWkbBlock, WKBGeometryType.POLYGON);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<import('../geom/Geometry.js').default>} array of geometries
|
||||
*/
|
||||
readGeometryCollection() {
|
||||
return this.readWkbCollection(this.readGeometry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import('../geom/Geometry.js').default} geometry
|
||||
*/
|
||||
readGeometry() {
|
||||
const typeId = this.readWkbHeader();
|
||||
const result = this.readWkbPayload(typeId);
|
||||
|
||||
switch (typeId) {
|
||||
case WKBGeometryType.POINT:
|
||||
return new Point(
|
||||
/** @type {import('../coordinate.js').Coordinate} */ (result),
|
||||
this.layout_
|
||||
);
|
||||
|
||||
case WKBGeometryType.LINE_STRING:
|
||||
return new LineString(
|
||||
/** @type {Array<import('../coordinate.js').Coordinate>} */ (result),
|
||||
this.layout_
|
||||
);
|
||||
|
||||
case WKBGeometryType.POLYGON:
|
||||
case WKBGeometryType.TRIANGLE:
|
||||
return new Polygon(
|
||||
/** @type {Array<Array<import('../coordinate.js').Coordinate>>} */ (
|
||||
result
|
||||
),
|
||||
this.layout_
|
||||
);
|
||||
|
||||
case WKBGeometryType.MULTI_POINT:
|
||||
return new MultiPoint(
|
||||
/** @type {Array<import('../coordinate.js').Coordinate>} */ (result),
|
||||
this.layout_
|
||||
);
|
||||
|
||||
case WKBGeometryType.MULTI_LINE_STRING:
|
||||
return new MultiLineString(
|
||||
/** @type {Array<Array<import('../coordinate.js').Coordinate>>} */ (
|
||||
result
|
||||
),
|
||||
this.layout_
|
||||
);
|
||||
|
||||
case WKBGeometryType.MULTI_POLYGON:
|
||||
case WKBGeometryType.POLYHEDRAL_SURFACE:
|
||||
case WKBGeometryType.TIN:
|
||||
return new MultiPolygon(
|
||||
/** @type {Array<Array<Array<import('../coordinate.js').Coordinate>>>} */ (
|
||||
result
|
||||
),
|
||||
this.layout_
|
||||
);
|
||||
|
||||
case WKBGeometryType.GEOMETRY_COLLECTION:
|
||||
return new GeometryCollection(
|
||||
/** @type {Array<import('../geom/Geometry.js').default>} */ (result)
|
||||
);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number|null} SRID in the EWKB. `null` if not defined.
|
||||
*/
|
||||
getSrid() {
|
||||
return this.srid_;
|
||||
}
|
||||
}
|
||||
|
||||
class WkbWriter {
|
||||
/**
|
||||
* @type {Object}
|
||||
* @property {string} [layout] geometryLayout
|
||||
* @property {boolean} [littleEndian=true] littleEndian
|
||||
* @property {boolean} [ewkb=true] Whether writes in EWKB format
|
||||
* @property {Object} [nodata] NoData value for each axes
|
||||
* @param {Object} opts options
|
||||
*/
|
||||
constructor(opts) {
|
||||
opts = opts || {};
|
||||
|
||||
/** @type {string} */
|
||||
this.layout_ = opts.layout;
|
||||
this.isLittleEndian_ = opts.littleEndian !== false;
|
||||
|
||||
this.isEWKB_ = opts.ewkb !== false;
|
||||
|
||||
/** @type {Array<Array<number>>} */
|
||||
this.writeQueue_ = [];
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @property {number} X NoData value for X
|
||||
* @property {number} Y NoData value for Y
|
||||
* @property {number} Z NoData value for Z
|
||||
* @property {number} M NoData value for M
|
||||
*/
|
||||
this.nodata_ = assign({X: 0, Y: 0, Z: 0, M: 0}, opts.nodata);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} value value
|
||||
*/
|
||||
writeUint8(value) {
|
||||
this.writeQueue_.push([1, value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} value value
|
||||
*/
|
||||
writeUint32(value) {
|
||||
this.writeQueue_.push([4, value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} value value
|
||||
*/
|
||||
writeDouble(value) {
|
||||
this.writeQueue_.push([8, value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../coordinate.js').Coordinate} coords coords
|
||||
* @param {import("../geom/GeometryLayout").default} layout layout
|
||||
*/
|
||||
writePoint(coords, layout) {
|
||||
/**
|
||||
* @type {Object}
|
||||
* @property {number} X NoData value for X
|
||||
* @property {number} Y NoData value for Y
|
||||
* @property {number} [Z] NoData value for Z
|
||||
* @property {number} [M] NoData value for M
|
||||
*/
|
||||
const coordsObj = assign.apply(
|
||||
null,
|
||||
layout.split('').map((axis, idx) => ({[axis]: coords[idx]}))
|
||||
);
|
||||
|
||||
for (const axis of this.layout_) {
|
||||
this.writeDouble(
|
||||
axis in coordsObj ? coordsObj[axis] : this.nodata_[axis]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<import('../coordinate.js').Coordinate>} coords coords
|
||||
* @param {import("../geom/GeometryLayout").default} layout layout
|
||||
*/
|
||||
writeLineString(coords, layout) {
|
||||
this.writeUint32(coords.length); // numPoints
|
||||
for (let i = 0; i < coords.length; i++) {
|
||||
this.writePoint(coords[i], layout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<Array<import('../coordinate.js').Coordinate>>} rings rings
|
||||
* @param {import("../geom/GeometryLayout").default} layout layout
|
||||
*/
|
||||
writePolygon(rings, layout) {
|
||||
this.writeUint32(rings.length); // numRings
|
||||
for (let i = 0; i < rings.length; i++) {
|
||||
this.writeLineString(rings[i], layout); // as a LinearRing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} wkbType WKB Type ID
|
||||
* @param {number} [srid] SRID
|
||||
*/
|
||||
writeWkbHeader(wkbType, srid) {
|
||||
wkbType %= 1000; // Assume 1000 is an upper limit for type ID
|
||||
if (this.layout_.indexOf('Z') >= 0) {
|
||||
wkbType += this.isEWKB_ ? 0x80000000 : 1000;
|
||||
}
|
||||
if (this.layout_.indexOf('M') >= 0) {
|
||||
wkbType += this.isEWKB_ ? 0x40000000 : 2000;
|
||||
}
|
||||
if (this.isEWKB_ && Number.isInteger(srid)) {
|
||||
wkbType |= 0x20000000;
|
||||
}
|
||||
|
||||
this.writeUint8(this.isLittleEndian_ ? 1 : 0);
|
||||
this.writeUint32(wkbType);
|
||||
if (this.isEWKB_ && Number.isInteger(srid)) {
|
||||
this.writeUint32(srid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<import('../coordinate.js').Coordinate>} coords coords
|
||||
* @param {string} layout layout
|
||||
*/
|
||||
writeMultiPoint(coords, layout) {
|
||||
this.writeUint32(coords.length); // numItems
|
||||
for (let i = 0; i < coords.length; i++) {
|
||||
this.writeWkbHeader(1);
|
||||
this.writePoint(coords[i], layout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<Array<import('../coordinate.js').Coordinate>>} coords coords
|
||||
* @param {string} layout layout
|
||||
*/
|
||||
writeMultiLineString(coords, layout) {
|
||||
this.writeUint32(coords.length); // numItems
|
||||
for (let i = 0; i < coords.length; i++) {
|
||||
this.writeWkbHeader(2);
|
||||
this.writeLineString(coords[i], layout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<Array<Array<import('../coordinate.js').Coordinate>>>} coords coords
|
||||
* @param {string} layout layout
|
||||
*/
|
||||
writeMultiPolygon(coords, layout) {
|
||||
this.writeUint32(coords.length); // numItems
|
||||
for (let i = 0; i < coords.length; i++) {
|
||||
this.writeWkbHeader(3);
|
||||
this.writePolygon(coords[i], layout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<import('../geom/Geometry.js').default>} geometries geometries
|
||||
*/
|
||||
writeGeometryCollection(geometries) {
|
||||
this.writeUint32(geometries.length); // numItems
|
||||
|
||||
for (let i = 0; i < geometries.length; i++) {
|
||||
this.writeGeometry(geometries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Geometry.js").default} geom geometry
|
||||
* @param {import("../geom/GeometryLayout.js").default} [layout] layout
|
||||
* @return {import("../geom/GeometryLayout.js").default} minumum layout made by common axes
|
||||
*/
|
||||
findMinimumLayout(geom, layout = GeometryLayout.XYZM) {
|
||||
/**
|
||||
* @param {import("../geom/GeometryLayout.js").default} a A
|
||||
* @param {import("../geom/GeometryLayout.js").default} b B
|
||||
* @return {import("../geom/GeometryLayout.js").default} minumum layout made by common axes
|
||||
*/
|
||||
const GeometryLayout_min = (a, b) => {
|
||||
if (a === b) {
|
||||
return a;
|
||||
}
|
||||
|
||||
if (a === GeometryLayout.XYZM) {
|
||||
// anything `b` is minimum
|
||||
return b;
|
||||
}
|
||||
if (b === GeometryLayout.XYZM) {
|
||||
// anything `a` is minimum
|
||||
return a;
|
||||
}
|
||||
|
||||
// otherwise, incompatible
|
||||
return GeometryLayout.XY;
|
||||
};
|
||||
|
||||
if (geom instanceof SimpleGeometry) {
|
||||
return GeometryLayout_min(geom.getLayout(), layout);
|
||||
}
|
||||
|
||||
if (geom instanceof GeometryCollection) {
|
||||
const geoms = geom.getGeometriesArray();
|
||||
for (let i = 0; i < geoms.length && layout !== GeometryLayout.XY; i++) {
|
||||
layout = this.findMinimumLayout(geoms[i], layout);
|
||||
}
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Geometry.js").default} geom geometry
|
||||
* @param {number} [srid] SRID
|
||||
*/
|
||||
writeGeometry(geom, srid) {
|
||||
/**
|
||||
* @type {Object<import("../geom/Geometry.js").Type, WKBGeometryType>}
|
||||
*/
|
||||
const wkblut = {
|
||||
Point: WKBGeometryType.POINT,
|
||||
LineString: WKBGeometryType.LINE_STRING,
|
||||
Polygon: WKBGeometryType.POLYGON,
|
||||
MultiPoint: WKBGeometryType.MULTI_POINT,
|
||||
MultiLineString: WKBGeometryType.MULTI_LINE_STRING,
|
||||
MultiPolygon: WKBGeometryType.MULTI_POLYGON,
|
||||
GeometryCollection: WKBGeometryType.GEOMETRY_COLLECTION,
|
||||
};
|
||||
const geomType = geom.getType();
|
||||
const typeId = wkblut[geomType];
|
||||
|
||||
if (!typeId) {
|
||||
throw new Error('GeometryType ' + geomType + ' is not supported');
|
||||
}
|
||||
|
||||
// first call of writeGeometry() traverse whole geometries to determine its output layout if not specified on constructor.
|
||||
if (!this.layout_) {
|
||||
this.layout_ = this.findMinimumLayout(geom);
|
||||
}
|
||||
|
||||
this.writeWkbHeader(typeId, srid);
|
||||
|
||||
if (geom instanceof SimpleGeometry) {
|
||||
const writerLUT = {
|
||||
Point: this.writePoint,
|
||||
LineString: this.writeLineString,
|
||||
Polygon: this.writePolygon,
|
||||
MultiPoint: this.writeMultiPoint,
|
||||
MultiLineString: this.writeMultiLineString,
|
||||
MultiPolygon: this.writeMultiPolygon,
|
||||
};
|
||||
writerLUT[geomType].call(this, geom.getCoordinates(), geom.getLayout());
|
||||
} else if (geom instanceof GeometryCollection) {
|
||||
this.writeGeometryCollection(geom.getGeometriesArray());
|
||||
}
|
||||
}
|
||||
|
||||
getBuffer() {
|
||||
const byteLength = this.writeQueue_.reduce((acc, item) => acc + item[0], 0);
|
||||
const buffer = new ArrayBuffer(byteLength);
|
||||
const view = new DataView(buffer);
|
||||
|
||||
let pos = 0;
|
||||
this.writeQueue_.forEach((item) => {
|
||||
switch (item[0]) {
|
||||
case 1:
|
||||
view.setUint8(pos, item[1]);
|
||||
break;
|
||||
case 4:
|
||||
view.setUint32(pos, item[1], this.isLittleEndian_);
|
||||
break;
|
||||
case 8:
|
||||
view.setFloat64(pos, item[1], this.isLittleEndian_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pos += item[0];
|
||||
});
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {boolean} [splitCollection=false] Whether to split GeometryCollections into multiple features on reading.
|
||||
* @property {boolean} [hex=true] Returns hex string instead of ArrayBuffer for output. This also is used as a hint internally whether it should load contents as text or ArrayBuffer on reading.
|
||||
* @property {boolean} [littleEndian=true] Use littleEndian for output.
|
||||
* @property {boolean} [ewkb=true] Use EWKB format for output.
|
||||
* @property {import("../geom/GeometryLayout").default} [geometryLayout=null] Use specific coordinate layout for output features (null: auto detect)
|
||||
* @property {number} [nodataZ=0] If the `geometryLayout` doesn't match with geometry to be output, this value is used to fill missing coordinate value of Z.
|
||||
* @property {number} [nodataM=0] If the `geometryLayout` doesn't match with geometry to be output, this value is used to fill missing coordinate value of M.
|
||||
* @property {number|boolean} [srid=true] SRID for output. Specify integer value to enforce the value as a SRID. Specify `true` to extract from `dataProjection`. `false` to suppress the output. This option only takes effect when `ewkb` is `true`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Geometry format for reading and writing data in the `Well-Known Binary` (WKB) format.
|
||||
* Also supports `Extended Well-Known Binary` (EWKB) format, used in PostGIS for example.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class WKB extends FeatureFormat {
|
||||
/**
|
||||
* @param {Options} [opt_options] Optional configuration object.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
this.splitCollection = Boolean(options.splitCollection);
|
||||
|
||||
this.viewCache_ = null;
|
||||
|
||||
this.hex_ = options.hex !== false;
|
||||
this.littleEndian_ = options.littleEndian !== false;
|
||||
this.ewkb_ = options.ewkb !== false;
|
||||
|
||||
this.layout_ = options.geometryLayout; // null for auto detect
|
||||
this.nodataZ_ = options.nodataZ || 0;
|
||||
this.nodataM_ = options.nodataM || 0;
|
||||
|
||||
this.srid_ = options.srid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./Feature.js").Type} Format.
|
||||
*/
|
||||
getType() {
|
||||
return this.hex_ ? 'text' : 'arraybuffer';
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single feature from a source.
|
||||
*
|
||||
* @param {string|ArrayBuffer|ArrayBufferView} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
* @api
|
||||
*/
|
||||
readFeature(source, opt_options) {
|
||||
return new Feature({
|
||||
geometry: this.readGeometry(source, opt_options),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all features from a source.
|
||||
*
|
||||
* @param {string|ArrayBuffer|ArrayBufferView} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
* @api
|
||||
*/
|
||||
readFeatures(source, opt_options) {
|
||||
let geometries = [];
|
||||
const geometry = this.readGeometry(source, opt_options);
|
||||
if (this.splitCollection && geometry instanceof GeometryCollection) {
|
||||
geometries = geometry.getGeometriesArray();
|
||||
} else {
|
||||
geometries = [geometry];
|
||||
}
|
||||
return geometries.map((geometry) => new Feature({geometry}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single geometry from a source.
|
||||
*
|
||||
* @param {string|ArrayBuffer|ArrayBufferView} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
* @api
|
||||
*/
|
||||
readGeometry(source, opt_options) {
|
||||
const view = getDataView(source);
|
||||
if (!view) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const reader = new WkbReader(view);
|
||||
const geometry = reader.readGeometry();
|
||||
|
||||
this.viewCache_ = view; // cache for internal subsequent call of readProjection()
|
||||
const options = this.getReadOptions(source, opt_options);
|
||||
this.viewCache_ = null; // release
|
||||
|
||||
return transformGeometryWithOptions(geometry, false, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection from a source.
|
||||
*
|
||||
* @param {string|ArrayBuffer|ArrayBufferView} source Source.
|
||||
* @return {import("../proj/Projection.js").default|undefined} Projection.
|
||||
* @api
|
||||
*/
|
||||
readProjection(source) {
|
||||
const view = this.viewCache_ || getDataView(source);
|
||||
if (!view) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const reader = new WkbReader(view);
|
||||
reader.readWkbHeader();
|
||||
|
||||
return (
|
||||
(reader.getSrid() && getProjection('EPSG:' + reader.getSrid())) ||
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature in this format.
|
||||
*
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string|ArrayBuffer} Result.
|
||||
* @api
|
||||
*/
|
||||
writeFeature(feature, opt_options) {
|
||||
return this.writeGeometry(feature.getGeometry(), opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features in this format.
|
||||
*
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string|ArrayBuffer} Result.
|
||||
* @api
|
||||
*/
|
||||
writeFeatures(features, opt_options) {
|
||||
return this.writeGeometry(
|
||||
new GeometryCollection(features.map((f) => f.getGeometry())),
|
||||
opt_options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single geometry in this format.
|
||||
*
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string|ArrayBuffer} Result.
|
||||
* @api
|
||||
*/
|
||||
writeGeometry(geometry, opt_options) {
|
||||
const options = this.adaptOptions(opt_options);
|
||||
|
||||
const writer = new WkbWriter({
|
||||
layout: this.layout_,
|
||||
littleEndian: this.littleEndian_,
|
||||
ewkb: this.ewkb_,
|
||||
|
||||
nodata: {
|
||||
Z: this.nodataZ_,
|
||||
M: this.nodataM_,
|
||||
},
|
||||
});
|
||||
|
||||
// extract SRID from `dataProjection`
|
||||
let srid = Number.isInteger(this.srid_) ? Number(this.srid_) : null;
|
||||
if (this.srid_ !== false && !Number.isInteger(this.srid_)) {
|
||||
const dataProjection =
|
||||
options.dataProjection && getProjection(options.dataProjection);
|
||||
if (dataProjection) {
|
||||
const code = dataProjection.getCode();
|
||||
if (code.indexOf('EPSG:') === 0) {
|
||||
srid = Number(code.substring(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writer.writeGeometry(
|
||||
transformGeometryWithOptions(geometry, true, options),
|
||||
srid
|
||||
);
|
||||
const buffer = writer.getBuffer();
|
||||
|
||||
return this.hex_ ? encodeHexString(buffer) : buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} buffer source buffer
|
||||
* @return {string} encoded hex string
|
||||
*/
|
||||
function encodeHexString(buffer) {
|
||||
const view = new Uint8Array(buffer);
|
||||
return Array.from(view.values())
|
||||
.map((x) => (x < 16 ? '0' : '') + Number(x).toString(16).toUpperCase())
|
||||
.join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text source text
|
||||
* @return {DataView} decoded binary buffer
|
||||
*/
|
||||
function decodeHexString(text) {
|
||||
const buffer = new Uint8Array(text.length / 2);
|
||||
for (let i = 0; i < text.length / 2; i++) {
|
||||
buffer[i] = parseInt(text.substr(i * 2, 2), 16);
|
||||
}
|
||||
return new DataView(buffer.buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | ArrayBuffer | ArrayBufferView} source source
|
||||
* @return {DataView} data view
|
||||
*/
|
||||
function getDataView(source) {
|
||||
if (typeof source === 'string') {
|
||||
return decodeHexString(source);
|
||||
} else if (ArrayBuffer.isView(source)) {
|
||||
if (source instanceof DataView) {
|
||||
return source;
|
||||
}
|
||||
return new DataView(source.buffer, source.byteOffset, source.byteLength);
|
||||
} else if (source instanceof ArrayBuffer) {
|
||||
return new DataView(source);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default WKB;
|
||||
869
node_modules/ol/src/format/WKT.js
generated
vendored
Normal file
869
node_modules/ol/src/format/WKT.js
generated
vendored
Normal file
@@ -0,0 +1,869 @@
|
||||
/**
|
||||
* @module ol/format/WKT
|
||||
*/
|
||||
import Feature from '../Feature.js';
|
||||
import GeometryCollection from '../geom/GeometryCollection.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import MultiPoint from '../geom/MultiPoint.js';
|
||||
import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import TextFeature from './TextFeature.js';
|
||||
import {transformGeometryWithOptions} from './Feature.js';
|
||||
|
||||
/**
|
||||
* Geometry constructors
|
||||
* @enum {function (new:import("../geom/Geometry.js").default, Array, import("../geom/GeometryLayout.js").default)}
|
||||
*/
|
||||
const GeometryConstructor = {
|
||||
'POINT': Point,
|
||||
'LINESTRING': LineString,
|
||||
'POLYGON': Polygon,
|
||||
'MULTIPOINT': MultiPoint,
|
||||
'MULTILINESTRING': MultiLineString,
|
||||
'MULTIPOLYGON': MultiPolygon,
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {boolean} [splitCollection=false] Whether to split GeometryCollections into
|
||||
* multiple features on reading.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Token
|
||||
* @property {number} type Type.
|
||||
* @property {number|string} [value] Value.
|
||||
* @property {number} position Position.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
const EMPTY = 'EMPTY';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
const Z = 'Z';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
const M = 'M';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
const ZM = 'ZM';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @enum {number}
|
||||
*/
|
||||
const TokenType = {
|
||||
START: 0,
|
||||
TEXT: 1,
|
||||
LEFT_PAREN: 2,
|
||||
RIGHT_PAREN: 3,
|
||||
NUMBER: 4,
|
||||
COMMA: 5,
|
||||
EOF: 6,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<import("../geom/Geometry.js").Type, string>}
|
||||
*/
|
||||
const wktTypeLookup = {
|
||||
Point: 'POINT',
|
||||
LineString: 'LINESTRING',
|
||||
Polygon: 'POLYGON',
|
||||
MultiPoint: 'MULTIPOINT',
|
||||
MultiLineString: 'MULTILINESTRING',
|
||||
MultiPolygon: 'MULTIPOLYGON',
|
||||
GeometryCollection: 'GEOMETRYCOLLECTION',
|
||||
Circle: 'CIRCLE',
|
||||
};
|
||||
|
||||
/**
|
||||
* Class to tokenize a WKT string.
|
||||
*/
|
||||
class Lexer {
|
||||
/**
|
||||
* @param {string} wkt WKT string.
|
||||
*/
|
||||
constructor(wkt) {
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.wkt = wkt;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.index_ = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} c Character.
|
||||
* @return {boolean} Whether the character is alphabetic.
|
||||
* @private
|
||||
*/
|
||||
isAlpha_(c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} c Character.
|
||||
* @param {boolean} [opt_decimal] Whether the string number
|
||||
* contains a dot, i.e. is a decimal number.
|
||||
* @return {boolean} Whether the character is numeric.
|
||||
* @private
|
||||
*/
|
||||
isNumeric_(c, opt_decimal) {
|
||||
const decimal = opt_decimal !== undefined ? opt_decimal : false;
|
||||
return (c >= '0' && c <= '9') || (c == '.' && !decimal);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} c Character.
|
||||
* @return {boolean} Whether the character is whitespace.
|
||||
* @private
|
||||
*/
|
||||
isWhiteSpace_(c) {
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {string} Next string character.
|
||||
* @private
|
||||
*/
|
||||
nextChar_() {
|
||||
return this.wkt.charAt(++this.index_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and return the next token.
|
||||
* @return {Token} Next string token.
|
||||
*/
|
||||
nextToken() {
|
||||
const c = this.nextChar_();
|
||||
const position = this.index_;
|
||||
/** @type {number|string} */
|
||||
let value = c;
|
||||
let type;
|
||||
|
||||
if (c == '(') {
|
||||
type = TokenType.LEFT_PAREN;
|
||||
} else if (c == ',') {
|
||||
type = TokenType.COMMA;
|
||||
} else if (c == ')') {
|
||||
type = TokenType.RIGHT_PAREN;
|
||||
} else if (this.isNumeric_(c) || c == '-') {
|
||||
type = TokenType.NUMBER;
|
||||
value = this.readNumber_();
|
||||
} else if (this.isAlpha_(c)) {
|
||||
type = TokenType.TEXT;
|
||||
value = this.readText_();
|
||||
} else if (this.isWhiteSpace_(c)) {
|
||||
return this.nextToken();
|
||||
} else if (c === '') {
|
||||
type = TokenType.EOF;
|
||||
} else {
|
||||
throw new Error('Unexpected character: ' + c);
|
||||
}
|
||||
|
||||
return {position: position, value: value, type: type};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Numeric token value.
|
||||
* @private
|
||||
*/
|
||||
readNumber_() {
|
||||
let c;
|
||||
const index = this.index_;
|
||||
let decimal = false;
|
||||
let scientificNotation = false;
|
||||
do {
|
||||
if (c == '.') {
|
||||
decimal = true;
|
||||
} else if (c == 'e' || c == 'E') {
|
||||
scientificNotation = true;
|
||||
}
|
||||
c = this.nextChar_();
|
||||
} while (
|
||||
this.isNumeric_(c, decimal) ||
|
||||
// if we haven't detected a scientific number before, 'e' or 'E'
|
||||
// hint that we should continue to read
|
||||
(!scientificNotation && (c == 'e' || c == 'E')) ||
|
||||
// once we know that we have a scientific number, both '-' and '+'
|
||||
// are allowed
|
||||
(scientificNotation && (c == '-' || c == '+'))
|
||||
);
|
||||
return parseFloat(this.wkt.substring(index, this.index_--));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {string} String token value.
|
||||
* @private
|
||||
*/
|
||||
readText_() {
|
||||
let c;
|
||||
const index = this.index_;
|
||||
do {
|
||||
c = this.nextChar_();
|
||||
} while (this.isAlpha_(c));
|
||||
return this.wkt.substring(index, this.index_--).toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to parse the tokens from the WKT string.
|
||||
*/
|
||||
class Parser {
|
||||
/**
|
||||
* @param {Lexer} lexer The lexer.
|
||||
*/
|
||||
constructor(lexer) {
|
||||
/**
|
||||
* @type {Lexer}
|
||||
* @private
|
||||
*/
|
||||
this.lexer_ = lexer;
|
||||
|
||||
/**
|
||||
* @type {Token}
|
||||
* @private
|
||||
*/
|
||||
this.token_ = {
|
||||
position: 0,
|
||||
type: TokenType.START,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {import("../geom/GeometryLayout.js").default}
|
||||
* @private
|
||||
*/
|
||||
this.layout_ = GeometryLayout.XY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the next token form the lexer and replace the active token.
|
||||
* @private
|
||||
*/
|
||||
consume_() {
|
||||
this.token_ = this.lexer_.nextToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the given type matches the type of the current token.
|
||||
* @param {TokenType} type Token type.
|
||||
* @return {boolean} Whether the token matches the given type.
|
||||
*/
|
||||
isTokenType(type) {
|
||||
return this.token_.type == type;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given type matches the current token, consume it.
|
||||
* @param {TokenType} type Token type.
|
||||
* @return {boolean} Whether the token matches the given type.
|
||||
*/
|
||||
match(type) {
|
||||
const isMatch = this.isTokenType(type);
|
||||
if (isMatch) {
|
||||
this.consume_();
|
||||
}
|
||||
return isMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to parse the tokens provided by the lexer.
|
||||
* @return {import("../geom/Geometry.js").default} The geometry.
|
||||
*/
|
||||
parse() {
|
||||
this.consume_();
|
||||
return this.parseGeometry_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to parse the dimensional info.
|
||||
* @return {import("../geom/GeometryLayout.js").default} The layout.
|
||||
* @private
|
||||
*/
|
||||
parseGeometryLayout_() {
|
||||
let layout = GeometryLayout.XY;
|
||||
const dimToken = this.token_;
|
||||
if (this.isTokenType(TokenType.TEXT)) {
|
||||
const dimInfo = dimToken.value;
|
||||
if (dimInfo === Z) {
|
||||
layout = GeometryLayout.XYZ;
|
||||
} else if (dimInfo === M) {
|
||||
layout = GeometryLayout.XYM;
|
||||
} else if (dimInfo === ZM) {
|
||||
layout = GeometryLayout.XYZM;
|
||||
}
|
||||
if (layout !== GeometryLayout.XY) {
|
||||
this.consume_();
|
||||
}
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<import("../geom/Geometry.js").default>} A collection of geometries.
|
||||
* @private
|
||||
*/
|
||||
parseGeometryCollectionText_() {
|
||||
if (this.match(TokenType.LEFT_PAREN)) {
|
||||
const geometries = [];
|
||||
do {
|
||||
geometries.push(this.parseGeometry_());
|
||||
} while (this.match(TokenType.COMMA));
|
||||
if (this.match(TokenType.RIGHT_PAREN)) {
|
||||
return geometries;
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<number>} All values in a point.
|
||||
* @private
|
||||
*/
|
||||
parsePointText_() {
|
||||
if (this.match(TokenType.LEFT_PAREN)) {
|
||||
const coordinates = this.parsePoint_();
|
||||
if (this.match(TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<number>>} All points in a linestring.
|
||||
* @private
|
||||
*/
|
||||
parseLineStringText_() {
|
||||
if (this.match(TokenType.LEFT_PAREN)) {
|
||||
const coordinates = this.parsePointList_();
|
||||
if (this.match(TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<Array<number>>>} All points in a polygon.
|
||||
* @private
|
||||
*/
|
||||
parsePolygonText_() {
|
||||
if (this.match(TokenType.LEFT_PAREN)) {
|
||||
const coordinates = this.parseLineStringTextList_();
|
||||
if (this.match(TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<number>>} All points in a multipoint.
|
||||
* @private
|
||||
*/
|
||||
parseMultiPointText_() {
|
||||
if (this.match(TokenType.LEFT_PAREN)) {
|
||||
let coordinates;
|
||||
if (this.token_.type == TokenType.LEFT_PAREN) {
|
||||
coordinates = this.parsePointTextList_();
|
||||
} else {
|
||||
coordinates = this.parsePointList_();
|
||||
}
|
||||
if (this.match(TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<Array<number>>>} All linestring points
|
||||
* in a multilinestring.
|
||||
* @private
|
||||
*/
|
||||
parseMultiLineStringText_() {
|
||||
if (this.match(TokenType.LEFT_PAREN)) {
|
||||
const coordinates = this.parseLineStringTextList_();
|
||||
if (this.match(TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<Array<Array<number>>>>} All polygon points in a multipolygon.
|
||||
* @private
|
||||
*/
|
||||
parseMultiPolygonText_() {
|
||||
if (this.match(TokenType.LEFT_PAREN)) {
|
||||
const coordinates = this.parsePolygonTextList_();
|
||||
if (this.match(TokenType.RIGHT_PAREN)) {
|
||||
return coordinates;
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<number>} A point.
|
||||
* @private
|
||||
*/
|
||||
parsePoint_() {
|
||||
const coordinates = [];
|
||||
const dimensions = this.layout_.length;
|
||||
for (let i = 0; i < dimensions; ++i) {
|
||||
const token = this.token_;
|
||||
if (this.match(TokenType.NUMBER)) {
|
||||
coordinates.push(/** @type {number} */ (token.value));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (coordinates.length == dimensions) {
|
||||
return coordinates;
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<number>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
parsePointList_() {
|
||||
const coordinates = [this.parsePoint_()];
|
||||
while (this.match(TokenType.COMMA)) {
|
||||
coordinates.push(this.parsePoint_());
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<number>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
parsePointTextList_() {
|
||||
const coordinates = [this.parsePointText_()];
|
||||
while (this.match(TokenType.COMMA)) {
|
||||
coordinates.push(this.parsePointText_());
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<Array<number>>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
parseLineStringTextList_() {
|
||||
const coordinates = [this.parseLineStringText_()];
|
||||
while (this.match(TokenType.COMMA)) {
|
||||
coordinates.push(this.parseLineStringText_());
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<Array<Array<Array<number>>>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
parsePolygonTextList_() {
|
||||
const coordinates = [this.parsePolygonText_()];
|
||||
while (this.match(TokenType.COMMA)) {
|
||||
coordinates.push(this.parsePolygonText_());
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the token implies an empty geometry.
|
||||
* @private
|
||||
*/
|
||||
isEmptyGeometry_() {
|
||||
const isEmpty =
|
||||
this.isTokenType(TokenType.TEXT) && this.token_.value == EMPTY;
|
||||
if (isEmpty) {
|
||||
this.consume_();
|
||||
}
|
||||
return isEmpty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an error message for an unexpected token error.
|
||||
* @return {string} Error message.
|
||||
* @private
|
||||
*/
|
||||
formatErrorMessage_() {
|
||||
return (
|
||||
'Unexpected `' +
|
||||
this.token_.value +
|
||||
'` at position ' +
|
||||
this.token_.position +
|
||||
' in `' +
|
||||
this.lexer_.wkt +
|
||||
'`'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("../geom/Geometry.js").default} The geometry.
|
||||
* @private
|
||||
*/
|
||||
parseGeometry_() {
|
||||
const token = this.token_;
|
||||
if (this.match(TokenType.TEXT)) {
|
||||
const geomType = /** @type {string} */ (token.value);
|
||||
this.layout_ = this.parseGeometryLayout_();
|
||||
const isEmpty = this.isEmptyGeometry_();
|
||||
if (geomType == 'GEOMETRYCOLLECTION') {
|
||||
if (isEmpty) {
|
||||
return new GeometryCollection([]);
|
||||
}
|
||||
const geometries = this.parseGeometryCollectionText_();
|
||||
return new GeometryCollection(geometries);
|
||||
} else {
|
||||
const ctor = GeometryConstructor[geomType];
|
||||
if (!ctor) {
|
||||
throw new Error('Invalid geometry type: ' + geomType);
|
||||
}
|
||||
|
||||
let coordinates;
|
||||
|
||||
if (isEmpty) {
|
||||
if (geomType == 'POINT') {
|
||||
coordinates = [NaN, NaN];
|
||||
} else {
|
||||
coordinates = [];
|
||||
}
|
||||
} else {
|
||||
switch (geomType) {
|
||||
case 'POINT': {
|
||||
coordinates = this.parsePointText_();
|
||||
break;
|
||||
}
|
||||
case 'LINESTRING': {
|
||||
coordinates = this.parseLineStringText_();
|
||||
break;
|
||||
}
|
||||
case 'POLYGON': {
|
||||
coordinates = this.parsePolygonText_();
|
||||
break;
|
||||
}
|
||||
case 'MULTIPOINT': {
|
||||
coordinates = this.parseMultiPointText_();
|
||||
break;
|
||||
}
|
||||
case 'MULTILINESTRING': {
|
||||
coordinates = this.parseMultiLineStringText_();
|
||||
break;
|
||||
}
|
||||
case 'MULTIPOLYGON': {
|
||||
coordinates = this.parseMultiPolygonText_();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new ctor(coordinates, this.layout_);
|
||||
}
|
||||
}
|
||||
throw new Error(this.formatErrorMessage_());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Geometry format for reading and writing data in the `WellKnownText` (WKT)
|
||||
* format.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class WKT extends TextFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* Split GeometryCollection into multiple features.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.splitCollection_ =
|
||||
options.splitCollection !== undefined ? options.splitCollection : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a WKT string.
|
||||
* @param {string} wkt WKT string.
|
||||
* @return {import("../geom/Geometry.js").default}
|
||||
* The geometry created.
|
||||
* @private
|
||||
*/
|
||||
parse_(wkt) {
|
||||
const lexer = new Lexer(wkt);
|
||||
const parser = new Parser(lexer);
|
||||
return parser.parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromText(text, opt_options) {
|
||||
const geom = this.readGeometryFromText(text, opt_options);
|
||||
const feature = new Feature();
|
||||
feature.setGeometry(geom);
|
||||
return feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {Array<Feature>} Features.
|
||||
*/
|
||||
readFeaturesFromText(text, opt_options) {
|
||||
let geometries = [];
|
||||
const geometry = this.readGeometryFromText(text, opt_options);
|
||||
if (this.splitCollection_ && geometry.getType() == 'GeometryCollection') {
|
||||
geometries = /** @type {GeometryCollection} */ (
|
||||
geometry
|
||||
).getGeometriesArray();
|
||||
} else {
|
||||
geometries = [geometry];
|
||||
}
|
||||
const features = [];
|
||||
for (let i = 0, ii = geometries.length; i < ii; ++i) {
|
||||
const feature = new Feature();
|
||||
feature.setGeometry(geometries[i]);
|
||||
features.push(feature);
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text Text.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromText(text, opt_options) {
|
||||
const geometry = this.parse_(text);
|
||||
return transformGeometryWithOptions(geometry, false, opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default} feature Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeFeatureText(feature, opt_options) {
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
return this.writeGeometryText(geometry, opt_options);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeFeaturesText(features, opt_options) {
|
||||
if (features.length == 1) {
|
||||
return this.writeFeatureText(features[0], opt_options);
|
||||
}
|
||||
const geometries = [];
|
||||
for (let i = 0, ii = features.length; i < ii; ++i) {
|
||||
geometries.push(features[i].getGeometry());
|
||||
}
|
||||
const collection = new GeometryCollection(geometries);
|
||||
return this.writeGeometryText(collection, opt_options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeGeometryText(geometry, opt_options) {
|
||||
return encode(transformGeometryWithOptions(geometry, true, opt_options));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Point} geom Point geometry.
|
||||
* @return {string} Coordinates part of Point as WKT.
|
||||
*/
|
||||
function encodePointGeometry(geom) {
|
||||
const coordinates = geom.getCoordinates();
|
||||
if (coordinates.length === 0) {
|
||||
return '';
|
||||
}
|
||||
return coordinates.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MultiPoint} geom MultiPoint geometry.
|
||||
* @return {string} Coordinates part of MultiPoint as WKT.
|
||||
*/
|
||||
function encodeMultiPointGeometry(geom) {
|
||||
const array = [];
|
||||
const components = geom.getPoints();
|
||||
for (let i = 0, ii = components.length; i < ii; ++i) {
|
||||
array.push('(' + encodePointGeometry(components[i]) + ')');
|
||||
}
|
||||
return array.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeometryCollection} geom GeometryCollection geometry.
|
||||
* @return {string} Coordinates part of GeometryCollection as WKT.
|
||||
*/
|
||||
function encodeGeometryCollectionGeometry(geom) {
|
||||
const array = [];
|
||||
const geoms = geom.getGeometries();
|
||||
for (let i = 0, ii = geoms.length; i < ii; ++i) {
|
||||
array.push(encode(geoms[i]));
|
||||
}
|
||||
return array.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {LineString|import("../geom/LinearRing.js").default} geom LineString geometry.
|
||||
* @return {string} Coordinates part of LineString as WKT.
|
||||
*/
|
||||
function encodeLineStringGeometry(geom) {
|
||||
const coordinates = geom.getCoordinates();
|
||||
const array = [];
|
||||
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
array.push(coordinates[i].join(' '));
|
||||
}
|
||||
return array.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MultiLineString} geom MultiLineString geometry.
|
||||
* @return {string} Coordinates part of MultiLineString as WKT.
|
||||
*/
|
||||
function encodeMultiLineStringGeometry(geom) {
|
||||
const array = [];
|
||||
const components = geom.getLineStrings();
|
||||
for (let i = 0, ii = components.length; i < ii; ++i) {
|
||||
array.push('(' + encodeLineStringGeometry(components[i]) + ')');
|
||||
}
|
||||
return array.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Polygon} geom Polygon geometry.
|
||||
* @return {string} Coordinates part of Polygon as WKT.
|
||||
*/
|
||||
function encodePolygonGeometry(geom) {
|
||||
const array = [];
|
||||
const rings = geom.getLinearRings();
|
||||
for (let i = 0, ii = rings.length; i < ii; ++i) {
|
||||
array.push('(' + encodeLineStringGeometry(rings[i]) + ')');
|
||||
}
|
||||
return array.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MultiPolygon} geom MultiPolygon geometry.
|
||||
* @return {string} Coordinates part of MultiPolygon as WKT.
|
||||
*/
|
||||
function encodeMultiPolygonGeometry(geom) {
|
||||
const array = [];
|
||||
const components = geom.getPolygons();
|
||||
for (let i = 0, ii = components.length; i < ii; ++i) {
|
||||
array.push('(' + encodePolygonGeometry(components[i]) + ')');
|
||||
}
|
||||
return array.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/SimpleGeometry.js").default} geom SimpleGeometry geometry.
|
||||
* @return {string} Potential dimensional information for WKT type.
|
||||
*/
|
||||
function encodeGeometryLayout(geom) {
|
||||
const layout = geom.getLayout();
|
||||
let dimInfo = '';
|
||||
if (layout === GeometryLayout.XYZ || layout === GeometryLayout.XYZM) {
|
||||
dimInfo += Z;
|
||||
}
|
||||
if (layout === GeometryLayout.XYM || layout === GeometryLayout.XYZM) {
|
||||
dimInfo += M;
|
||||
}
|
||||
return dimInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, function(import("../geom/Geometry.js").default): string>}
|
||||
*/
|
||||
const GeometryEncoder = {
|
||||
'Point': encodePointGeometry,
|
||||
'LineString': encodeLineStringGeometry,
|
||||
'Polygon': encodePolygonGeometry,
|
||||
'MultiPoint': encodeMultiPointGeometry,
|
||||
'MultiLineString': encodeMultiLineStringGeometry,
|
||||
'MultiPolygon': encodeMultiPolygonGeometry,
|
||||
'GeometryCollection': encodeGeometryCollectionGeometry,
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a geometry as WKT.
|
||||
* @param {import("../geom/Geometry.js").default} geom The geometry to encode.
|
||||
* @return {string} WKT string for the geometry.
|
||||
*/
|
||||
function encode(geom) {
|
||||
const type = geom.getType();
|
||||
const geometryEncoder = GeometryEncoder[type];
|
||||
const enc = geometryEncoder(geom);
|
||||
let wktType = wktTypeLookup[type];
|
||||
if (typeof (/** @type {?} */ (geom).getFlatCoordinates) === 'function') {
|
||||
const dimInfo = encodeGeometryLayout(
|
||||
/** @type {import("../geom/SimpleGeometry.js").default} */ (geom)
|
||||
);
|
||||
if (dimInfo.length > 0) {
|
||||
wktType += ' ' + dimInfo;
|
||||
}
|
||||
}
|
||||
if (enc.length === 0) {
|
||||
return wktType + ' ' + EMPTY;
|
||||
}
|
||||
return wktType + '(' + enc + ')';
|
||||
}
|
||||
|
||||
export default WKT;
|
||||
625
node_modules/ol/src/format/WMSCapabilities.js
generated
vendored
Normal file
625
node_modules/ol/src/format/WMSCapabilities.js
generated
vendored
Normal file
@@ -0,0 +1,625 @@
|
||||
/**
|
||||
* @module ol/format/WMSCapabilities
|
||||
*/
|
||||
import XML from './XML.js';
|
||||
import {
|
||||
makeArrayPusher,
|
||||
makeObjectPropertyPusher,
|
||||
makeObjectPropertySetter,
|
||||
makeStructureNS,
|
||||
pushParseAndPop,
|
||||
} from '../xml.js';
|
||||
import {
|
||||
readBooleanString,
|
||||
readDecimal,
|
||||
readDecimalString,
|
||||
readNonNegativeIntegerString,
|
||||
readPositiveInteger,
|
||||
readString,
|
||||
} from './xsd.js';
|
||||
import {readHref} from './xlink.js';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array<null|string>}
|
||||
*/
|
||||
const NAMESPACE_URIS = [null, 'http://www.opengis.net/wms'];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Service': makeObjectPropertySetter(readService),
|
||||
'Capability': makeObjectPropertySetter(readCapability),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const CAPABILITY_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Request': makeObjectPropertySetter(readRequest),
|
||||
'Exception': makeObjectPropertySetter(readException),
|
||||
'Layer': makeObjectPropertySetter(readCapabilityLayer),
|
||||
});
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Format for reading WMS capabilities data
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class WMSCapabilities extends XML {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
/**
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.version = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @return {Object} Object
|
||||
*/
|
||||
readFromNode(node) {
|
||||
this.version = node.getAttribute('version').trim();
|
||||
const wmsCapabilityObject = pushParseAndPop(
|
||||
{
|
||||
'version': this.version,
|
||||
},
|
||||
PARSERS,
|
||||
node,
|
||||
[]
|
||||
);
|
||||
return wmsCapabilityObject ? wmsCapabilityObject : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const SERVICE_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Name': makeObjectPropertySetter(readString),
|
||||
'Title': makeObjectPropertySetter(readString),
|
||||
'Abstract': makeObjectPropertySetter(readString),
|
||||
'KeywordList': makeObjectPropertySetter(readKeywordList),
|
||||
'OnlineResource': makeObjectPropertySetter(readHref),
|
||||
'ContactInformation': makeObjectPropertySetter(readContactInformation),
|
||||
'Fees': makeObjectPropertySetter(readString),
|
||||
'AccessConstraints': makeObjectPropertySetter(readString),
|
||||
'LayerLimit': makeObjectPropertySetter(readPositiveInteger),
|
||||
'MaxWidth': makeObjectPropertySetter(readPositiveInteger),
|
||||
'MaxHeight': makeObjectPropertySetter(readPositiveInteger),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const CONTACT_INFORMATION_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'ContactPersonPrimary': makeObjectPropertySetter(readContactPersonPrimary),
|
||||
'ContactPosition': makeObjectPropertySetter(readString),
|
||||
'ContactAddress': makeObjectPropertySetter(readContactAddress),
|
||||
'ContactVoiceTelephone': makeObjectPropertySetter(readString),
|
||||
'ContactFacsimileTelephone': makeObjectPropertySetter(readString),
|
||||
'ContactElectronicMailAddress': makeObjectPropertySetter(readString),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const CONTACT_PERSON_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'ContactPerson': makeObjectPropertySetter(readString),
|
||||
'ContactOrganization': makeObjectPropertySetter(readString),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const CONTACT_ADDRESS_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'AddressType': makeObjectPropertySetter(readString),
|
||||
'Address': makeObjectPropertySetter(readString),
|
||||
'City': makeObjectPropertySetter(readString),
|
||||
'StateOrProvince': makeObjectPropertySetter(readString),
|
||||
'PostCode': makeObjectPropertySetter(readString),
|
||||
'Country': makeObjectPropertySetter(readString),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const EXCEPTION_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Format': makeArrayPusher(readString),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const LAYER_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Name': makeObjectPropertySetter(readString),
|
||||
'Title': makeObjectPropertySetter(readString),
|
||||
'Abstract': makeObjectPropertySetter(readString),
|
||||
'KeywordList': makeObjectPropertySetter(readKeywordList),
|
||||
'CRS': makeObjectPropertyPusher(readString),
|
||||
'EX_GeographicBoundingBox': makeObjectPropertySetter(
|
||||
readEXGeographicBoundingBox
|
||||
),
|
||||
'BoundingBox': makeObjectPropertyPusher(readBoundingBox),
|
||||
'Dimension': makeObjectPropertyPusher(readDimension),
|
||||
'Attribution': makeObjectPropertySetter(readAttribution),
|
||||
'AuthorityURL': makeObjectPropertyPusher(readAuthorityURL),
|
||||
'Identifier': makeObjectPropertyPusher(readString),
|
||||
'MetadataURL': makeObjectPropertyPusher(readMetadataURL),
|
||||
'DataURL': makeObjectPropertyPusher(readFormatOnlineresource),
|
||||
'FeatureListURL': makeObjectPropertyPusher(readFormatOnlineresource),
|
||||
'Style': makeObjectPropertyPusher(readStyle),
|
||||
'MinScaleDenominator': makeObjectPropertySetter(readDecimal),
|
||||
'MaxScaleDenominator': makeObjectPropertySetter(readDecimal),
|
||||
'Layer': makeObjectPropertyPusher(readLayer),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const ATTRIBUTION_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Title': makeObjectPropertySetter(readString),
|
||||
'OnlineResource': makeObjectPropertySetter(readHref),
|
||||
'LogoURL': makeObjectPropertySetter(readSizedFormatOnlineresource),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const EX_GEOGRAPHIC_BOUNDING_BOX_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'westBoundLongitude': makeObjectPropertySetter(readDecimal),
|
||||
'eastBoundLongitude': makeObjectPropertySetter(readDecimal),
|
||||
'southBoundLatitude': makeObjectPropertySetter(readDecimal),
|
||||
'northBoundLatitude': makeObjectPropertySetter(readDecimal),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const REQUEST_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'GetCapabilities': makeObjectPropertySetter(readOperationType),
|
||||
'GetMap': makeObjectPropertySetter(readOperationType),
|
||||
'GetFeatureInfo': makeObjectPropertySetter(readOperationType),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const OPERATIONTYPE_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Format': makeObjectPropertyPusher(readString),
|
||||
'DCPType': makeObjectPropertyPusher(readDCPType),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const DCPTYPE_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'HTTP': makeObjectPropertySetter(readHTTP),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const HTTP_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Get': makeObjectPropertySetter(readFormatOnlineresource),
|
||||
'Post': makeObjectPropertySetter(readFormatOnlineresource),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const STYLE_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Name': makeObjectPropertySetter(readString),
|
||||
'Title': makeObjectPropertySetter(readString),
|
||||
'Abstract': makeObjectPropertySetter(readString),
|
||||
'LegendURL': makeObjectPropertyPusher(readSizedFormatOnlineresource),
|
||||
'StyleSheetURL': makeObjectPropertySetter(readFormatOnlineresource),
|
||||
'StyleURL': makeObjectPropertySetter(readFormatOnlineresource),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const FORMAT_ONLINERESOURCE_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Format': makeObjectPropertySetter(readString),
|
||||
'OnlineResource': makeObjectPropertySetter(readHref),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const KEYWORDLIST_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Keyword': makeArrayPusher(readString),
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Attribution object.
|
||||
*/
|
||||
function readAttribution(node, objectStack) {
|
||||
return pushParseAndPop({}, ATTRIBUTION_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object} Bounding box object.
|
||||
*/
|
||||
function readBoundingBox(node, objectStack) {
|
||||
const extent = [
|
||||
readDecimalString(node.getAttribute('minx')),
|
||||
readDecimalString(node.getAttribute('miny')),
|
||||
readDecimalString(node.getAttribute('maxx')),
|
||||
readDecimalString(node.getAttribute('maxy')),
|
||||
];
|
||||
|
||||
const resolutions = [
|
||||
readDecimalString(node.getAttribute('resx')),
|
||||
readDecimalString(node.getAttribute('resy')),
|
||||
];
|
||||
|
||||
return {
|
||||
'crs': node.getAttribute('CRS'),
|
||||
'extent': extent,
|
||||
'res': resolutions,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {import("../extent.js").Extent|undefined} Bounding box object.
|
||||
*/
|
||||
function readEXGeographicBoundingBox(node, objectStack) {
|
||||
const geographicBoundingBox = pushParseAndPop(
|
||||
{},
|
||||
EX_GEOGRAPHIC_BOUNDING_BOX_PARSERS,
|
||||
node,
|
||||
objectStack
|
||||
);
|
||||
if (!geographicBoundingBox) {
|
||||
return undefined;
|
||||
}
|
||||
const westBoundLongitude =
|
||||
/** @type {number|undefined} */
|
||||
(geographicBoundingBox['westBoundLongitude']);
|
||||
const southBoundLatitude =
|
||||
/** @type {number|undefined} */
|
||||
(geographicBoundingBox['southBoundLatitude']);
|
||||
const eastBoundLongitude =
|
||||
/** @type {number|undefined} */
|
||||
(geographicBoundingBox['eastBoundLongitude']);
|
||||
const northBoundLatitude =
|
||||
/** @type {number|undefined} */
|
||||
(geographicBoundingBox['northBoundLatitude']);
|
||||
if (
|
||||
westBoundLongitude === undefined ||
|
||||
southBoundLatitude === undefined ||
|
||||
eastBoundLongitude === undefined ||
|
||||
northBoundLatitude === undefined
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
return [
|
||||
westBoundLongitude,
|
||||
southBoundLatitude,
|
||||
eastBoundLongitude,
|
||||
northBoundLatitude,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Capability object.
|
||||
*/
|
||||
function readCapability(node, objectStack) {
|
||||
return pushParseAndPop({}, CAPABILITY_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Service object.
|
||||
*/
|
||||
function readService(node, objectStack) {
|
||||
return pushParseAndPop({}, SERVICE_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Contact information object.
|
||||
*/
|
||||
function readContactInformation(node, objectStack) {
|
||||
return pushParseAndPop({}, CONTACT_INFORMATION_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Contact person object.
|
||||
*/
|
||||
function readContactPersonPrimary(node, objectStack) {
|
||||
return pushParseAndPop({}, CONTACT_PERSON_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Contact address object.
|
||||
*/
|
||||
function readContactAddress(node, objectStack) {
|
||||
return pushParseAndPop({}, CONTACT_ADDRESS_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Array<string>|undefined} Format array.
|
||||
*/
|
||||
function readException(node, objectStack) {
|
||||
return pushParseAndPop([], EXCEPTION_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Layer object.
|
||||
*/
|
||||
function readCapabilityLayer(node, objectStack) {
|
||||
const layerObject = pushParseAndPop({}, LAYER_PARSERS, node, objectStack);
|
||||
|
||||
if (layerObject['Layer'] === undefined) {
|
||||
return Object.assign(layerObject, readLayer(node, objectStack));
|
||||
}
|
||||
|
||||
return layerObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Layer object.
|
||||
*/
|
||||
function readLayer(node, objectStack) {
|
||||
const parentLayerObject = /** @type {!Object<string,*>} */ (
|
||||
objectStack[objectStack.length - 1]
|
||||
);
|
||||
|
||||
const layerObject = pushParseAndPop({}, LAYER_PARSERS, node, objectStack);
|
||||
|
||||
if (!layerObject) {
|
||||
return undefined;
|
||||
}
|
||||
let queryable = readBooleanString(node.getAttribute('queryable'));
|
||||
if (queryable === undefined) {
|
||||
queryable = parentLayerObject['queryable'];
|
||||
}
|
||||
layerObject['queryable'] = queryable !== undefined ? queryable : false;
|
||||
|
||||
let cascaded = readNonNegativeIntegerString(node.getAttribute('cascaded'));
|
||||
if (cascaded === undefined) {
|
||||
cascaded = parentLayerObject['cascaded'];
|
||||
}
|
||||
layerObject['cascaded'] = cascaded;
|
||||
|
||||
let opaque = readBooleanString(node.getAttribute('opaque'));
|
||||
if (opaque === undefined) {
|
||||
opaque = parentLayerObject['opaque'];
|
||||
}
|
||||
layerObject['opaque'] = opaque !== undefined ? opaque : false;
|
||||
|
||||
let noSubsets = readBooleanString(node.getAttribute('noSubsets'));
|
||||
if (noSubsets === undefined) {
|
||||
noSubsets = parentLayerObject['noSubsets'];
|
||||
}
|
||||
layerObject['noSubsets'] = noSubsets !== undefined ? noSubsets : false;
|
||||
|
||||
let fixedWidth = readDecimalString(node.getAttribute('fixedWidth'));
|
||||
if (!fixedWidth) {
|
||||
fixedWidth = parentLayerObject['fixedWidth'];
|
||||
}
|
||||
layerObject['fixedWidth'] = fixedWidth;
|
||||
|
||||
let fixedHeight = readDecimalString(node.getAttribute('fixedHeight'));
|
||||
if (!fixedHeight) {
|
||||
fixedHeight = parentLayerObject['fixedHeight'];
|
||||
}
|
||||
layerObject['fixedHeight'] = fixedHeight;
|
||||
|
||||
// See 7.2.4.8
|
||||
const addKeys = ['Style', 'CRS', 'AuthorityURL'];
|
||||
addKeys.forEach(function (key) {
|
||||
if (key in parentLayerObject) {
|
||||
const childValue = layerObject[key] || [];
|
||||
layerObject[key] = childValue.concat(parentLayerObject[key]);
|
||||
}
|
||||
});
|
||||
|
||||
const replaceKeys = [
|
||||
'EX_GeographicBoundingBox',
|
||||
'BoundingBox',
|
||||
'Dimension',
|
||||
'Attribution',
|
||||
'MinScaleDenominator',
|
||||
'MaxScaleDenominator',
|
||||
];
|
||||
replaceKeys.forEach(function (key) {
|
||||
if (!(key in layerObject)) {
|
||||
const parentValue = parentLayerObject[key];
|
||||
layerObject[key] = parentValue;
|
||||
}
|
||||
});
|
||||
|
||||
return layerObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object} Dimension object.
|
||||
*/
|
||||
function readDimension(node, objectStack) {
|
||||
const dimensionObject = {
|
||||
'name': node.getAttribute('name'),
|
||||
'units': node.getAttribute('units'),
|
||||
'unitSymbol': node.getAttribute('unitSymbol'),
|
||||
'default': node.getAttribute('default'),
|
||||
'multipleValues': readBooleanString(node.getAttribute('multipleValues')),
|
||||
'nearestValue': readBooleanString(node.getAttribute('nearestValue')),
|
||||
'current': readBooleanString(node.getAttribute('current')),
|
||||
'values': readString(node),
|
||||
};
|
||||
return dimensionObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Online resource object.
|
||||
*/
|
||||
function readFormatOnlineresource(node, objectStack) {
|
||||
return pushParseAndPop({}, FORMAT_ONLINERESOURCE_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Request object.
|
||||
*/
|
||||
function readRequest(node, objectStack) {
|
||||
return pushParseAndPop({}, REQUEST_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} DCP type object.
|
||||
*/
|
||||
function readDCPType(node, objectStack) {
|
||||
return pushParseAndPop({}, DCPTYPE_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} HTTP object.
|
||||
*/
|
||||
function readHTTP(node, objectStack) {
|
||||
return pushParseAndPop({}, HTTP_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Operation type object.
|
||||
*/
|
||||
function readOperationType(node, objectStack) {
|
||||
return pushParseAndPop({}, OPERATIONTYPE_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Online resource object.
|
||||
*/
|
||||
function readSizedFormatOnlineresource(node, objectStack) {
|
||||
const formatOnlineresource = readFormatOnlineresource(node, objectStack);
|
||||
if (formatOnlineresource) {
|
||||
const size = [
|
||||
readNonNegativeIntegerString(node.getAttribute('width')),
|
||||
readNonNegativeIntegerString(node.getAttribute('height')),
|
||||
];
|
||||
formatOnlineresource['size'] = size;
|
||||
return formatOnlineresource;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Authority URL object.
|
||||
*/
|
||||
function readAuthorityURL(node, objectStack) {
|
||||
const authorityObject = readFormatOnlineresource(node, objectStack);
|
||||
if (authorityObject) {
|
||||
authorityObject['name'] = node.getAttribute('name');
|
||||
return authorityObject;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Metadata URL object.
|
||||
*/
|
||||
function readMetadataURL(node, objectStack) {
|
||||
const metadataObject = readFormatOnlineresource(node, objectStack);
|
||||
if (metadataObject) {
|
||||
metadataObject['type'] = node.getAttribute('type');
|
||||
return metadataObject;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Style object.
|
||||
*/
|
||||
function readStyle(node, objectStack) {
|
||||
return pushParseAndPop({}, STYLE_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Array<string>|undefined} Keyword list.
|
||||
*/
|
||||
function readKeywordList(node, objectStack) {
|
||||
return pushParseAndPop([], KEYWORDLIST_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
export default WMSCapabilities;
|
||||
166
node_modules/ol/src/format/WMSGetFeatureInfo.js
generated
vendored
Normal file
166
node_modules/ol/src/format/WMSGetFeatureInfo.js
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* @module ol/format/WMSGetFeatureInfo
|
||||
*/
|
||||
import GML2 from './GML2.js';
|
||||
import XMLFeature from './XMLFeature.js';
|
||||
import {assign} from '../obj.js';
|
||||
import {extend, includes} from '../array.js';
|
||||
import {makeArrayPusher, makeStructureNS, pushParseAndPop} from '../xml.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {Array<string>} [layers] If set, only features of the given layers will be returned by the format when read.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
const featureIdentifier = '_feature';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {string}
|
||||
*/
|
||||
const layerIdentifier = '_layer';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Format for reading WMSGetFeatureInfo format. It uses
|
||||
* {@link module:ol/format/GML2~GML2} to read features.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class WMSGetFeatureInfo extends XMLFeature {
|
||||
/**
|
||||
* @param {Options} [opt_options] Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
*/
|
||||
this.featureNS_ = 'http://mapserver.gis.umn.edu/mapserver';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {GML2}
|
||||
*/
|
||||
this.gmlFormat_ = new GML2();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<string>|null}
|
||||
*/
|
||||
this.layers_ = options.layers ? options.layers : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<string>|null} layers
|
||||
*/
|
||||
getLayers() {
|
||||
return this.layers_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<string>|null} layers Layers to parse.
|
||||
*/
|
||||
setLayers(layers) {
|
||||
this.layers_ = layers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
* @private
|
||||
*/
|
||||
readFeatures_(node, objectStack) {
|
||||
node.setAttribute('namespaceURI', this.featureNS_);
|
||||
const localName = node.localName;
|
||||
/** @type {Array<import("../Feature.js").default>} */
|
||||
let features = [];
|
||||
if (node.childNodes.length === 0) {
|
||||
return features;
|
||||
}
|
||||
if (localName == 'msGMLOutput') {
|
||||
for (let i = 0, ii = node.childNodes.length; i < ii; i++) {
|
||||
const layer = node.childNodes[i];
|
||||
if (layer.nodeType !== Node.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const layerElement = /** @type {Element} */ (layer);
|
||||
const context = objectStack[0];
|
||||
|
||||
const toRemove = layerIdentifier;
|
||||
const layerName = layerElement.localName.replace(toRemove, '');
|
||||
|
||||
if (this.layers_ && !includes(this.layers_, layerName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const featureType = layerName + featureIdentifier;
|
||||
|
||||
context['featureType'] = featureType;
|
||||
context['featureNS'] = this.featureNS_;
|
||||
|
||||
/** @type {Object<string, import("../xml.js").Parser>} */
|
||||
const parsers = {};
|
||||
parsers[featureType] = makeArrayPusher(
|
||||
this.gmlFormat_.readFeatureElement,
|
||||
this.gmlFormat_
|
||||
);
|
||||
const parsersNS = makeStructureNS(
|
||||
[context['featureNS'], null],
|
||||
parsers
|
||||
);
|
||||
layerElement.setAttribute('namespaceURI', this.featureNS_);
|
||||
const layerFeatures = pushParseAndPop(
|
||||
[],
|
||||
// @ts-ignore
|
||||
parsersNS,
|
||||
layerElement,
|
||||
objectStack,
|
||||
this.gmlFormat_
|
||||
);
|
||||
if (layerFeatures) {
|
||||
extend(features, layerFeatures);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (localName == 'FeatureCollection') {
|
||||
const gmlFeatures = pushParseAndPop(
|
||||
[],
|
||||
this.gmlFormat_.FEATURE_COLLECTION_PARSERS,
|
||||
node,
|
||||
[{}],
|
||||
this.gmlFormat_
|
||||
);
|
||||
if (gmlFeatures) {
|
||||
features = gmlFeatures;
|
||||
}
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromNode(node, opt_options) {
|
||||
const options = {};
|
||||
if (opt_options) {
|
||||
assign(options, this.getReadOptions(node, opt_options));
|
||||
}
|
||||
return this.readFeatures_(node, [options]);
|
||||
}
|
||||
}
|
||||
|
||||
export default WMSGetFeatureInfo;
|
||||
380
node_modules/ol/src/format/WMTSCapabilities.js
generated
vendored
Normal file
380
node_modules/ol/src/format/WMTSCapabilities.js
generated
vendored
Normal file
@@ -0,0 +1,380 @@
|
||||
/**
|
||||
* @module ol/format/WMTSCapabilities
|
||||
*/
|
||||
import OWS from './OWS.js';
|
||||
import XML from './XML.js';
|
||||
import {boundingExtent} from '../extent.js';
|
||||
import {
|
||||
makeArrayPusher,
|
||||
makeObjectPropertyPusher,
|
||||
makeObjectPropertySetter,
|
||||
makeStructureNS,
|
||||
pushParseAndPop,
|
||||
} from '../xml.js';
|
||||
import {readDecimal, readPositiveInteger, readString} from './xsd.js';
|
||||
import {readHref} from './xlink.js';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array<null|string>}
|
||||
*/
|
||||
const NAMESPACE_URIS = [null, 'http://www.opengis.net/wmts/1.0'];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Array<null|string>}
|
||||
*/
|
||||
const OWS_NAMESPACE_URIS = [null, 'http://www.opengis.net/ows/1.1'];
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Contents': makeObjectPropertySetter(readContents),
|
||||
});
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Format for reading WMTS capabilities data.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class WMTSCapabilities extends XML {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
/**
|
||||
* @type {OWS}
|
||||
* @private
|
||||
*/
|
||||
this.owsParser_ = new OWS();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @return {Object} Object
|
||||
*/
|
||||
readFromNode(node) {
|
||||
let version = node.getAttribute('version');
|
||||
if (version) {
|
||||
version = version.trim();
|
||||
}
|
||||
let WMTSCapabilityObject = this.owsParser_.readFromNode(node);
|
||||
if (!WMTSCapabilityObject) {
|
||||
return null;
|
||||
}
|
||||
WMTSCapabilityObject['version'] = version;
|
||||
WMTSCapabilityObject = pushParseAndPop(
|
||||
WMTSCapabilityObject,
|
||||
PARSERS,
|
||||
node,
|
||||
[]
|
||||
);
|
||||
return WMTSCapabilityObject ? WMTSCapabilityObject : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const CONTENTS_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'Layer': makeObjectPropertyPusher(readLayer),
|
||||
'TileMatrixSet': makeObjectPropertyPusher(readTileMatrixSet),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const LAYER_PARSERS = makeStructureNS(
|
||||
NAMESPACE_URIS,
|
||||
{
|
||||
'Style': makeObjectPropertyPusher(readStyle),
|
||||
'Format': makeObjectPropertyPusher(readString),
|
||||
'TileMatrixSetLink': makeObjectPropertyPusher(readTileMatrixSetLink),
|
||||
'Dimension': makeObjectPropertyPusher(readDimensions),
|
||||
'ResourceURL': makeObjectPropertyPusher(readResourceUrl),
|
||||
},
|
||||
makeStructureNS(OWS_NAMESPACE_URIS, {
|
||||
'Title': makeObjectPropertySetter(readString),
|
||||
'Abstract': makeObjectPropertySetter(readString),
|
||||
'WGS84BoundingBox': makeObjectPropertySetter(readBoundingBox),
|
||||
'Identifier': makeObjectPropertySetter(readString),
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const STYLE_PARSERS = makeStructureNS(
|
||||
NAMESPACE_URIS,
|
||||
{
|
||||
'LegendURL': makeObjectPropertyPusher(readLegendUrl),
|
||||
},
|
||||
makeStructureNS(OWS_NAMESPACE_URIS, {
|
||||
'Title': makeObjectPropertySetter(readString),
|
||||
'Identifier': makeObjectPropertySetter(readString),
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TMS_LINKS_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'TileMatrixSet': makeObjectPropertySetter(readString),
|
||||
'TileMatrixSetLimits': makeObjectPropertySetter(readTileMatrixLimitsList),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TMS_LIMITS_LIST_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'TileMatrixLimits': makeArrayPusher(readTileMatrixLimits),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TMS_LIMITS_PARSERS = makeStructureNS(NAMESPACE_URIS, {
|
||||
'TileMatrix': makeObjectPropertySetter(readString),
|
||||
'MinTileRow': makeObjectPropertySetter(readPositiveInteger),
|
||||
'MaxTileRow': makeObjectPropertySetter(readPositiveInteger),
|
||||
'MinTileCol': makeObjectPropertySetter(readPositiveInteger),
|
||||
'MaxTileCol': makeObjectPropertySetter(readPositiveInteger),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const DIMENSION_PARSERS = makeStructureNS(
|
||||
NAMESPACE_URIS,
|
||||
{
|
||||
'Default': makeObjectPropertySetter(readString),
|
||||
'Value': makeObjectPropertyPusher(readString),
|
||||
},
|
||||
makeStructureNS(OWS_NAMESPACE_URIS, {
|
||||
'Identifier': makeObjectPropertySetter(readString),
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const WGS84_BBOX_READERS = makeStructureNS(OWS_NAMESPACE_URIS, {
|
||||
'LowerCorner': makeArrayPusher(readCoordinates),
|
||||
'UpperCorner': makeArrayPusher(readCoordinates),
|
||||
});
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TMS_PARSERS = makeStructureNS(
|
||||
NAMESPACE_URIS,
|
||||
{
|
||||
'WellKnownScaleSet': makeObjectPropertySetter(readString),
|
||||
'TileMatrix': makeObjectPropertyPusher(readTileMatrix),
|
||||
},
|
||||
makeStructureNS(OWS_NAMESPACE_URIS, {
|
||||
'SupportedCRS': makeObjectPropertySetter(readString),
|
||||
'Identifier': makeObjectPropertySetter(readString),
|
||||
'BoundingBox': makeObjectPropertySetter(readBoundingBox),
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
*/
|
||||
// @ts-ignore
|
||||
const TM_PARSERS = makeStructureNS(
|
||||
NAMESPACE_URIS,
|
||||
{
|
||||
'TopLeftCorner': makeObjectPropertySetter(readCoordinates),
|
||||
'ScaleDenominator': makeObjectPropertySetter(readDecimal),
|
||||
'TileWidth': makeObjectPropertySetter(readPositiveInteger),
|
||||
'TileHeight': makeObjectPropertySetter(readPositiveInteger),
|
||||
'MatrixWidth': makeObjectPropertySetter(readPositiveInteger),
|
||||
'MatrixHeight': makeObjectPropertySetter(readPositiveInteger),
|
||||
},
|
||||
makeStructureNS(OWS_NAMESPACE_URIS, {
|
||||
'Identifier': makeObjectPropertySetter(readString),
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Attribution object.
|
||||
*/
|
||||
function readContents(node, objectStack) {
|
||||
return pushParseAndPop({}, CONTENTS_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Layers object.
|
||||
*/
|
||||
function readLayer(node, objectStack) {
|
||||
return pushParseAndPop({}, LAYER_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Tile Matrix Set object.
|
||||
*/
|
||||
function readTileMatrixSet(node, objectStack) {
|
||||
return pushParseAndPop({}, TMS_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Style object.
|
||||
*/
|
||||
function readStyle(node, objectStack) {
|
||||
const style = pushParseAndPop({}, STYLE_PARSERS, node, objectStack);
|
||||
if (!style) {
|
||||
return undefined;
|
||||
}
|
||||
const isDefault = node.getAttribute('isDefault') === 'true';
|
||||
style['isDefault'] = isDefault;
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Tile Matrix Set Link object.
|
||||
*/
|
||||
function readTileMatrixSetLink(node, objectStack) {
|
||||
return pushParseAndPop({}, TMS_LINKS_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Dimension object.
|
||||
*/
|
||||
function readDimensions(node, objectStack) {
|
||||
return pushParseAndPop({}, DIMENSION_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Resource URL object.
|
||||
*/
|
||||
function readResourceUrl(node, objectStack) {
|
||||
const format = node.getAttribute('format');
|
||||
const template = node.getAttribute('template');
|
||||
const resourceType = node.getAttribute('resourceType');
|
||||
const resource = {};
|
||||
if (format) {
|
||||
resource['format'] = format;
|
||||
}
|
||||
if (template) {
|
||||
resource['template'] = template;
|
||||
}
|
||||
if (resourceType) {
|
||||
resource['resourceType'] = resourceType;
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} BBox object.
|
||||
*/
|
||||
function readBoundingBox(node, objectStack) {
|
||||
const coordinates = pushParseAndPop(
|
||||
[],
|
||||
WGS84_BBOX_READERS,
|
||||
node,
|
||||
objectStack
|
||||
);
|
||||
if (coordinates.length != 2) {
|
||||
return undefined;
|
||||
}
|
||||
return boundingExtent(coordinates);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Legend object.
|
||||
*/
|
||||
function readLegendUrl(node, objectStack) {
|
||||
const legend = {};
|
||||
legend['format'] = node.getAttribute('format');
|
||||
legend['href'] = readHref(node);
|
||||
return legend;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} Coordinates object.
|
||||
*/
|
||||
function readCoordinates(node, objectStack) {
|
||||
const coordinates = readString(node).split(/\s+/);
|
||||
if (!coordinates || coordinates.length != 2) {
|
||||
return undefined;
|
||||
}
|
||||
const x = +coordinates[0];
|
||||
const y = +coordinates[1];
|
||||
if (isNaN(x) || isNaN(y)) {
|
||||
return undefined;
|
||||
}
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} TileMatrix object.
|
||||
*/
|
||||
function readTileMatrix(node, objectStack) {
|
||||
return pushParseAndPop({}, TM_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} TileMatrixSetLimits Object.
|
||||
*/
|
||||
function readTileMatrixLimitsList(node, objectStack) {
|
||||
return pushParseAndPop([], TMS_LIMITS_LIST_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Object|undefined} TileMatrixLimits Array.
|
||||
*/
|
||||
function readTileMatrixLimits(node, objectStack) {
|
||||
return pushParseAndPop({}, TMS_LIMITS_PARSERS, node, objectStack);
|
||||
}
|
||||
|
||||
export default WMTSCapabilities;
|
||||
54
node_modules/ol/src/format/XML.js
generated
vendored
Normal file
54
node_modules/ol/src/format/XML.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @module ol/format/XML
|
||||
*/
|
||||
import {isDocument, parse} from '../xml.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Generic format for reading non-feature XML data
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
class XML {
|
||||
/**
|
||||
* Read the source document.
|
||||
*
|
||||
* @param {Document|Element|string} source The XML source.
|
||||
* @return {Object} An object representing the source.
|
||||
* @api
|
||||
*/
|
||||
read(source) {
|
||||
if (!source) {
|
||||
return null;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readFromDocument(doc);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readFromDocument(/** @type {Document} */ (source));
|
||||
} else {
|
||||
return this.readFromNode(/** @type {Element} */ (source));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @return {Object} Object
|
||||
*/
|
||||
readFromDocument(doc) {
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
return this.readFromNode(/** @type {Element} */ (n));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Element} node Node.
|
||||
* @return {Object} Object
|
||||
*/
|
||||
readFromNode(node) {}
|
||||
}
|
||||
|
||||
export default XML;
|
||||
293
node_modules/ol/src/format/XMLFeature.js
generated
vendored
Normal file
293
node_modules/ol/src/format/XMLFeature.js
generated
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
/**
|
||||
* @module ol/format/XMLFeature
|
||||
*/
|
||||
import FeatureFormat from '../format/Feature.js';
|
||||
import {abstract} from '../util.js';
|
||||
import {extend} from '../array.js';
|
||||
import {getXMLSerializer, isDocument, parse} from '../xml.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not
|
||||
* instantiated in apps.
|
||||
* Base class for XML feature formats.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
class XMLFeature extends FeatureFormat {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
/**
|
||||
* @type {XMLSerializer}
|
||||
* @private
|
||||
*/
|
||||
this.xmlSerializer_ = getXMLSerializer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./Feature.js").Type} Format.
|
||||
*/
|
||||
getType() {
|
||||
return 'xml';
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single feature.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
* @api
|
||||
*/
|
||||
readFeature(source, opt_options) {
|
||||
if (!source) {
|
||||
return null;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readFeatureFromDocument(doc, opt_options);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readFeatureFromDocument(
|
||||
/** @type {Document} */ (source),
|
||||
opt_options
|
||||
);
|
||||
} else {
|
||||
return this.readFeatureFromNode(
|
||||
/** @type {Element} */ (source),
|
||||
opt_options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromDocument(doc, opt_options) {
|
||||
const features = this.readFeaturesFromDocument(doc, opt_options);
|
||||
if (features.length > 0) {
|
||||
return features[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromNode(node, opt_options) {
|
||||
return null; // not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all features from a feature collection.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
* @api
|
||||
*/
|
||||
readFeatures(source, opt_options) {
|
||||
if (!source) {
|
||||
return [];
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readFeaturesFromDocument(doc, opt_options);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readFeaturesFromDocument(
|
||||
/** @type {Document} */ (source),
|
||||
opt_options
|
||||
);
|
||||
} else {
|
||||
return this.readFeaturesFromNode(
|
||||
/** @type {Element} */ (source),
|
||||
opt_options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @protected
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromDocument(doc, opt_options) {
|
||||
/** @type {Array<import("../Feature.js").default>} */
|
||||
const features = [];
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
extend(
|
||||
features,
|
||||
this.readFeaturesFromNode(/** @type {Element} */ (n), opt_options)
|
||||
);
|
||||
}
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @protected
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromNode(node, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single geometry from a source.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Read options.
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometry(source, opt_options) {
|
||||
if (!source) {
|
||||
return null;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readGeometryFromDocument(doc, opt_options);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readGeometryFromDocument(
|
||||
/** @type {Document} */ (source),
|
||||
opt_options
|
||||
);
|
||||
} else {
|
||||
return this.readGeometryFromNode(
|
||||
/** @type {Element} */ (source),
|
||||
opt_options
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromDocument(doc, opt_options) {
|
||||
return null; // not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {import("./Feature.js").ReadOptions} [opt_options] Options.
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromNode(node, opt_options) {
|
||||
return null; // not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection from the source.
|
||||
*
|
||||
* @param {Document|Element|Object|string} source Source.
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
* @api
|
||||
*/
|
||||
readProjection(source) {
|
||||
if (!source) {
|
||||
return null;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readProjectionFromDocument(doc);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readProjectionFromDocument(/** @type {Document} */ (source));
|
||||
} else {
|
||||
return this.readProjectionFromNode(/** @type {Element} */ (source));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Document} doc Document.
|
||||
* @protected
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjectionFromDocument(doc) {
|
||||
return this.dataProjection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @protected
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjectionFromNode(node) {
|
||||
return this.dataProjection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature as string.
|
||||
*
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Encoded feature.
|
||||
*/
|
||||
writeFeature(feature, opt_options) {
|
||||
const node = this.writeFeatureNode(feature, opt_options);
|
||||
return this.xmlSerializer_.serializeToString(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default} feature Feature.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Options.
|
||||
* @protected
|
||||
* @return {Node} Node.
|
||||
*/
|
||||
writeFeatureNode(feature, opt_options) {
|
||||
return null; // not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features as string.
|
||||
*
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Result.
|
||||
* @api
|
||||
*/
|
||||
writeFeatures(features, opt_options) {
|
||||
const node = this.writeFeaturesNode(features, opt_options);
|
||||
return this.xmlSerializer_.serializeToString(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Array<import("../Feature.js").default>} features Features.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Options.
|
||||
* @return {Node} Node.
|
||||
*/
|
||||
writeFeaturesNode(features, opt_options) {
|
||||
return null; // not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a geometry as string.
|
||||
*
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Write options.
|
||||
* @return {string} Encoded geometry.
|
||||
*/
|
||||
writeGeometry(geometry, opt_options) {
|
||||
const node = this.writeGeometryNode(geometry, opt_options);
|
||||
return this.xmlSerializer_.serializeToString(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions} [opt_options] Options.
|
||||
* @return {Node} Node.
|
||||
*/
|
||||
writeGeometryNode(geometry, opt_options) {
|
||||
return null; // not implemented
|
||||
}
|
||||
}
|
||||
|
||||
export default XMLFeature;
|
||||
301
node_modules/ol/src/format/filter.js
generated
vendored
Normal file
301
node_modules/ol/src/format/filter.js
generated
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* @module ol/format/filter
|
||||
*/
|
||||
import And from './filter/And.js';
|
||||
import Bbox from './filter/Bbox.js';
|
||||
import Contains from './filter/Contains.js';
|
||||
import DWithin from './filter/DWithin.js';
|
||||
import Disjoint from './filter/Disjoint.js';
|
||||
import During from './filter/During.js';
|
||||
import EqualTo from './filter/EqualTo.js';
|
||||
import GreaterThan from './filter/GreaterThan.js';
|
||||
import GreaterThanOrEqualTo from './filter/GreaterThanOrEqualTo.js';
|
||||
import Intersects from './filter/Intersects.js';
|
||||
import IsBetween from './filter/IsBetween.js';
|
||||
import IsLike from './filter/IsLike.js';
|
||||
import IsNull from './filter/IsNull.js';
|
||||
import LessThan from './filter/LessThan.js';
|
||||
import LessThanOrEqualTo from './filter/LessThanOrEqualTo.js';
|
||||
import Not from './filter/Not.js';
|
||||
import NotEqualTo from './filter/NotEqualTo.js';
|
||||
import Or from './filter/Or.js';
|
||||
import ResourceId from './filter/ResourceId.js';
|
||||
import Within from './filter/Within.js';
|
||||
|
||||
/**
|
||||
* Create a logical `<And>` operator between two or more filter conditions.
|
||||
*
|
||||
* @param {...import("./filter/Filter.js").default} conditions Filter conditions.
|
||||
* @return {!And} `<And>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function and(conditions) {
|
||||
const params = [null].concat(Array.prototype.slice.call(arguments));
|
||||
return new (Function.prototype.bind.apply(And, params))();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a logical `<Or>` operator between two or more filter conditions.
|
||||
*
|
||||
* @param {...import("./filter/Filter.js").default} conditions Filter conditions.
|
||||
* @return {!Or} `<Or>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function or(conditions) {
|
||||
const params = [null].concat(Array.prototype.slice.call(arguments));
|
||||
return new (Function.prototype.bind.apply(Or, params))();
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a logical `<Not>` operator for a filter condition.
|
||||
*
|
||||
* @param {!import("./filter/Filter.js").default} condition Filter condition.
|
||||
* @return {!Not} `<Not>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function not(condition) {
|
||||
return new Not(condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `<BBOX>` operator to test whether a geometry-valued property
|
||||
* intersects a fixed bounding box
|
||||
*
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../extent.js").Extent} extent Extent.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @return {!Bbox} `<BBOX>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function bbox(geometryName, extent, opt_srsName) {
|
||||
return new Bbox(geometryName, extent, opt_srsName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `<Contains>` operator to test whether a geometry-valued property
|
||||
* contains a given geometry.
|
||||
*
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @return {!Contains} `<Contains>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function contains(geometryName, geometry, opt_srsName) {
|
||||
return new Contains(geometryName, geometry, opt_srsName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `<Intersects>` operator to test whether a geometry-valued property
|
||||
* intersects a given geometry.
|
||||
*
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @return {!Intersects} `<Intersects>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function intersects(geometryName, geometry, opt_srsName) {
|
||||
return new Intersects(geometryName, geometry, opt_srsName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `<Disjoint>` operator to test whether a geometry-valued property
|
||||
* is disjoint to a given geometry.
|
||||
*
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @return {!Disjoint} `<Disjoint>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function disjoint(geometryName, geometry, opt_srsName) {
|
||||
return new Disjoint(geometryName, geometry, opt_srsName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `<Within>` operator to test whether a geometry-valued property
|
||||
* is within a given geometry.
|
||||
*
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @return {!Within} `<Within>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function within(geometryName, geometry, opt_srsName) {
|
||||
return new Within(geometryName, geometry, opt_srsName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `<DWithin>` operator to test whether a geometry-valued property
|
||||
* is within a distance to a given geometry.
|
||||
*
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {!number} distance Distance.
|
||||
* @param {!string} unit Unit.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @return {!DWithin} `<DWithin>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function dwithin(geometryName, geometry, distance, unit, opt_srsName) {
|
||||
return new DWithin(geometryName, geometry, distance, unit, opt_srsName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `<PropertyIsEqualTo>` comparison operator.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!(string|number)} expression The value to compare.
|
||||
* @param {boolean} [opt_matchCase] Case-sensitive?
|
||||
* @return {!EqualTo} `<PropertyIsEqualTo>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function equalTo(propertyName, expression, opt_matchCase) {
|
||||
return new EqualTo(propertyName, expression, opt_matchCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `<PropertyIsNotEqualTo>` comparison operator.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!(string|number)} expression The value to compare.
|
||||
* @param {boolean} [opt_matchCase] Case-sensitive?
|
||||
* @return {!NotEqualTo} `<PropertyIsNotEqualTo>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function notEqualTo(propertyName, expression, opt_matchCase) {
|
||||
return new NotEqualTo(propertyName, expression, opt_matchCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `<PropertyIsLessThan>` comparison operator.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} expression The value to compare.
|
||||
* @return {!LessThan} `<PropertyIsLessThan>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function lessThan(propertyName, expression) {
|
||||
return new LessThan(propertyName, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `<PropertyIsLessThanOrEqualTo>` comparison operator.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} expression The value to compare.
|
||||
* @return {!LessThanOrEqualTo} `<PropertyIsLessThanOrEqualTo>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function lessThanOrEqualTo(propertyName, expression) {
|
||||
return new LessThanOrEqualTo(propertyName, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `<PropertyIsGreaterThan>` comparison operator.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} expression The value to compare.
|
||||
* @return {!GreaterThan} `<PropertyIsGreaterThan>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function greaterThan(propertyName, expression) {
|
||||
return new GreaterThan(propertyName, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `<PropertyIsGreaterThanOrEqualTo>` comparison operator.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} expression The value to compare.
|
||||
* @return {!GreaterThanOrEqualTo} `<PropertyIsGreaterThanOrEqualTo>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function greaterThanOrEqualTo(propertyName, expression) {
|
||||
return new GreaterThanOrEqualTo(propertyName, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `<PropertyIsNull>` comparison operator to test whether a property value
|
||||
* is null.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @return {!IsNull} `<PropertyIsNull>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function isNull(propertyName) {
|
||||
return new IsNull(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `<PropertyIsBetween>` comparison operator to test whether an expression
|
||||
* value lies within a range given by a lower and upper bound (inclusive).
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} lowerBoundary The lower bound of the range.
|
||||
* @param {!number} upperBoundary The upper bound of the range.
|
||||
* @return {!IsBetween} `<PropertyIsBetween>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function between(propertyName, lowerBoundary, upperBoundary) {
|
||||
return new IsBetween(propertyName, lowerBoundary, upperBoundary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a `<PropertyIsLike>` comparison operator that matches a string property
|
||||
* value against a text pattern.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!string} pattern Text pattern.
|
||||
* @param {string} [opt_wildCard] Pattern character which matches any sequence of
|
||||
* zero or more string characters. Default is '*'.
|
||||
* @param {string} [opt_singleChar] pattern character which matches any single
|
||||
* string character. Default is '.'.
|
||||
* @param {string} [opt_escapeChar] Escape character which can be used to escape
|
||||
* the pattern characters. Default is '!'.
|
||||
* @param {boolean} [opt_matchCase] Case-sensitive?
|
||||
* @return {!IsLike} `<PropertyIsLike>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function like(
|
||||
propertyName,
|
||||
pattern,
|
||||
opt_wildCard,
|
||||
opt_singleChar,
|
||||
opt_escapeChar,
|
||||
opt_matchCase
|
||||
) {
|
||||
return new IsLike(
|
||||
propertyName,
|
||||
pattern,
|
||||
opt_wildCard,
|
||||
opt_singleChar,
|
||||
opt_escapeChar,
|
||||
opt_matchCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `<During>` temporal operator.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!string} begin The begin date in ISO-8601 format.
|
||||
* @param {!string} end The end date in ISO-8601 format.
|
||||
* @return {!During} `<During>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function during(propertyName, begin, end) {
|
||||
return new During(propertyName, begin, end);
|
||||
}
|
||||
|
||||
export function resourceId(rid) {
|
||||
return new ResourceId(rid);
|
||||
}
|
||||
21
node_modules/ol/src/format/filter/And.js
generated
vendored
Normal file
21
node_modules/ol/src/format/filter/And.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @module ol/format/filter/And
|
||||
*/
|
||||
import LogicalNary from './LogicalNary.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Represents a logical `<And>` operator between two or more filter conditions.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
class And extends LogicalNary {
|
||||
/**
|
||||
* @param {...import("./Filter.js").default} conditions Conditions.
|
||||
*/
|
||||
constructor(conditions) {
|
||||
super('And', Array.prototype.slice.call(arguments));
|
||||
}
|
||||
}
|
||||
|
||||
export default And;
|
||||
45
node_modules/ol/src/format/filter/Bbox.js
generated
vendored
Normal file
45
node_modules/ol/src/format/filter/Bbox.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @module ol/format/filter/Bbox
|
||||
*/
|
||||
import Filter from './Filter.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Represents a `<BBOX>` operator to test whether a geometry-valued property
|
||||
* intersects a fixed bounding box
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
class Bbox extends Filter {
|
||||
/**
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../../extent.js").Extent} extent Extent.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be set
|
||||
* on geometries when this is not provided.
|
||||
*/
|
||||
constructor(geometryName, extent, opt_srsName) {
|
||||
super('BBOX');
|
||||
|
||||
/**
|
||||
* @type {!string}
|
||||
*/
|
||||
this.geometryName = geometryName;
|
||||
|
||||
/**
|
||||
* @type {import("../../extent.js").Extent}
|
||||
*/
|
||||
this.extent = extent;
|
||||
if (extent.length !== 4) {
|
||||
throw new Error(
|
||||
'Expected an extent with four values ([minX, minY, maxX, maxY])'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
this.srsName = opt_srsName;
|
||||
}
|
||||
}
|
||||
|
||||
export default Bbox;
|
||||
28
node_modules/ol/src/format/filter/Comparison.js
generated
vendored
Normal file
28
node_modules/ol/src/format/filter/Comparison.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @module ol/format/filter/Comparison
|
||||
*/
|
||||
import Filter from './Filter.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract class; normally only used for creating subclasses and not instantiated in apps.
|
||||
* Base class for WFS GetFeature property comparison filters.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
class Comparison extends Filter {
|
||||
/**
|
||||
* @param {!string} tagName The XML tag name for this filter.
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
*/
|
||||
constructor(tagName, propertyName) {
|
||||
super(tagName);
|
||||
|
||||
/**
|
||||
* @type {!string}
|
||||
*/
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
}
|
||||
|
||||
export default Comparison;
|
||||
35
node_modules/ol/src/format/filter/ComparisonBinary.js
generated
vendored
Normal file
35
node_modules/ol/src/format/filter/ComparisonBinary.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @module ol/format/filter/ComparisonBinary
|
||||
*/
|
||||
import Comparison from './Comparison.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract class; normally only used for creating subclasses and not instantiated in apps.
|
||||
* Base class for WFS GetFeature property binary comparison filters.
|
||||
*
|
||||
* @abstract
|
||||
*/
|
||||
class ComparisonBinary extends Comparison {
|
||||
/**
|
||||
* @param {!string} tagName The XML tag name for this filter.
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!(string|number)} expression The value to compare.
|
||||
* @param {boolean} [opt_matchCase] Case-sensitive?
|
||||
*/
|
||||
constructor(tagName, propertyName, expression, opt_matchCase) {
|
||||
super(tagName, propertyName);
|
||||
|
||||
/**
|
||||
* @type {!(string|number)}
|
||||
*/
|
||||
this.expression = expression;
|
||||
|
||||
/**
|
||||
* @type {boolean|undefined}
|
||||
*/
|
||||
this.matchCase = opt_matchCase;
|
||||
}
|
||||
}
|
||||
|
||||
export default ComparisonBinary;
|
||||
24
node_modules/ol/src/format/filter/Contains.js
generated
vendored
Normal file
24
node_modules/ol/src/format/filter/Contains.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @module ol/format/filter/Contains
|
||||
*/
|
||||
import Spatial from './Spatial.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Represents a `<Contains>` operator to test whether a geometry-valued property
|
||||
* contains a given geometry.
|
||||
* @api
|
||||
*/
|
||||
class Contains extends Spatial {
|
||||
/**
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
*/
|
||||
constructor(geometryName, geometry, opt_srsName) {
|
||||
super('Contains', geometryName, geometry, opt_srsName);
|
||||
}
|
||||
}
|
||||
|
||||
export default Contains;
|
||||
38
node_modules/ol/src/format/filter/DWithin.js
generated
vendored
Normal file
38
node_modules/ol/src/format/filter/DWithin.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @module ol/format/filter/DWithin
|
||||
*/
|
||||
import Spatial from './Spatial.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Represents a `<DWithin>` operator to test whether a geometry-valued property
|
||||
* is within a distance to a given geometry.
|
||||
* @api
|
||||
*/
|
||||
class DWithin extends Spatial {
|
||||
/**
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {!number} distance Distance.
|
||||
* @param {!string} unit Unit.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
*/
|
||||
constructor(geometryName, geometry, distance, unit, opt_srsName) {
|
||||
super('DWithin', geometryName, geometry, opt_srsName);
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {!number}
|
||||
*/
|
||||
this.distance = distance;
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @type {!string}
|
||||
*/
|
||||
this.unit = unit;
|
||||
}
|
||||
}
|
||||
|
||||
export default DWithin;
|
||||
24
node_modules/ol/src/format/filter/Disjoint.js
generated
vendored
Normal file
24
node_modules/ol/src/format/filter/Disjoint.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @module ol/format/filter/Disjoint
|
||||
*/
|
||||
import Spatial from './Spatial.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Represents a `<Disjoint>` operator to test whether a geometry-valued property
|
||||
* is disjoint to a given geometry.
|
||||
* @api
|
||||
*/
|
||||
class Disjoint extends Spatial {
|
||||
/**
|
||||
* @param {!string} geometryName Geometry name to use.
|
||||
* @param {!import("../../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string} [opt_srsName] SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
*/
|
||||
constructor(geometryName, geometry, opt_srsName) {
|
||||
super('Disjoint', geometryName, geometry, opt_srsName);
|
||||
}
|
||||
}
|
||||
|
||||
export default Disjoint;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user