planning
All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s

This commit is contained in:
2024-10-14 09:15:30 +02:00
parent bcba00a730
commit 6e64e138e2
21059 changed files with 2317811 additions and 1 deletions

46
node_modules/ol/src/AssertionError.js generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

317
node_modules/ol/src/Tile.js generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

11
node_modules/ol/src/ViewHint.js generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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='&#160;'] 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 = '&#160;';
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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

344
node_modules/ol/src/format/GML32.js generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

437
node_modules/ol/src/format/MVT.js generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

892
node_modules/ol/src/format/WKB.js generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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