vue3-openlayers
Version:
OpenLayers Wrapper for Vue3
1,533 lines • 993 kB
JavaScript
"use strict";
const vue = require("vue");
const Feature = require("ol/Feature");
const Geometry = require("ol/geom/Geometry");
const Geolocation = require("ol/Geolocation");
const Map = require("ol/Map");
const Overlay = require("ol/Overlay");
const proj4$2 = require("ol/proj/proj4");
const Projection$1 = require("ol/proj/Projection");
const View = require("ol/View");
const proj = require("ol/proj");
const source = require("ol/source");
const AnimatedCluster = require("ol-ext/layer/AnimatedCluster");
const Graticule = require("ol/layer/Graticule");
const HeatmapLayer = require("ol/layer/Heatmap");
const ImageLayer = require("ol/layer/Image");
const LayerGroup = require("ol/layer/Group");
const TileLayer = require("ol/layer/Tile");
const TileSource = require("ol/source/Tile");
const VectorLayer = require("ol/layer/Vector");
const VectorTileLayer = require("ol/layer/VectorTile");
const VectorImageLayer = require("ol/layer/VectorImage");
const TileLayer$1 = require("ol/layer/WebGLTile");
const WebGLVectorLayer = require("ol/layer/WebGLVector");
const BingMaps = require("ol/source/BingMaps");
const VectorSource = require("ol/source/Vector");
const ImageSource = require("ol/source/Image");
const Cluster = require("ol/source/Cluster");
const Static = require("ol/source/ImageStatic");
const ImageWMS = require("ol/source/ImageWMS");
const OSM = require("ol/source/OSM");
const StadiaMaps = require("ol/source/StadiaMaps");
const WMTSSource = require("ol/source/WMTS");
const TileGridWMTS = require("ol/tilegrid/WMTS");
const TileArcGISRest = require("ol/source/TileArcGISRest");
const tilegrid = require("ol/tilegrid");
const TileDebug = require("ol/source/TileDebug");
const GeoTIFF = require("ol/source/GeoTIFF");
const TileJSON = require("ol/source/TileJSON");
const TileWMS = require("ol/source/TileWMS");
const ol = require("ol");
const VectorTileSource = require("ol/source/VectorTile");
const XYZ = require("ol/source/XYZ");
const extent = require("ol/extent");
const Attribution = require("ol/control/Attribution");
const Bar = require("ol-ext/control/Bar");
const Button = require("ol-ext/control/Button");
const ContextMenu = require("ol-contextmenu");
const FullScreen = require("ol/control/FullScreen");
const LayerSwitcher = require("ol-ext/control/LayerSwitcher");
const LayerSwitcherImage = require("ol-ext/control/LayerSwitcherImage");
const MousePosition = require("ol/control/MousePosition");
const OverviewMap = require("ol/control/OverviewMap");
const PrintDialog = require("ol-ext/control/PrintDialog");
const Profile = require("ol-ext/control/Profile");
const Rotate = require("ol/control/Rotate");
const ScaleLine = require("ol/control/ScaleLine");
const Search = require("ol-ext/control/Search");
const Swipe = require("ol-ext/control/Swipe");
const Toggle = require("ol-ext/control/Toggle");
const VideoRecorder = require("ol-ext/control/VideoRecorder");
const MapZone = require("ol-ext/control/MapZone");
const Zoom = require("ol/control/Zoom");
const ZoomSlider = require("ol/control/ZoomSlider");
const ZoomToExtent = require("ol/control/ZoomToExtent");
const Circle = require("ol/geom/Circle");
const LineString = require("ol/geom/LineString");
const MultiLineString = require("ol/geom/MultiLineString");
const MultiPoint = require("ol/geom/MultiPoint");
const MultiPolygon = require("ol/geom/MultiPolygon");
const Point$1 = require("ol/geom/Point");
const Polygon = require("ol/geom/Polygon");
const Style = require("ol/style/Style");
const Draw = require("ol/interaction/Draw");
const Modify = require("ol/interaction/Modify");
const CircleStyle = require("ol/style/Circle");
const Fill = require("ol/style/Fill");
const Stroke = require("ol/style/Stroke");
const interaction = require("ol/interaction");
const Icon = require("ol/style/Icon");
const Text = require("ol/style/Text");
const FlowLine = require("ol-ext/style/FlowLine");
const SelectCluster = require("ol-ext/interaction/SelectCluster");
const DragBox = require("ol/interaction/DragBox");
const DragRotate = require("ol/interaction/DragRotate");
const DragRotateAndZoom = require("ol/interaction/DragRotateAndZoom");
const Link = require("ol/interaction/Link");
const Select = require("ol/interaction/Select");
const Pointer = require("ol/interaction/Pointer");
const Snap = require("ol/interaction/Snap");
const Transform = require("ol-ext/interaction/Transform");
const selectconditions = require("ol/events/condition");
const functions = require("ol/functions");
const MouseWheelZoom = require("ol/interaction/MouseWheelZoom");
const Synchronize = require("ol-ext/interaction/Synchronize");
const Drop = require("ol-ext/featureanimation/Drop");
const animations = require("ol/easing");
require("ol-ext/featureanimation/FeatureAnimation");
const Fade = require("ol-ext/featureanimation/Fade");
const Path = require("ol-ext/featureanimation/Path");
const Shake = require("ol-ext/featureanimation/Shake");
const Slide = require("ol-ext/featureanimation/Slide");
const Teleport = require("ol-ext/featureanimation/Teleport");
const Zoom$1 = require("ol-ext/featureanimation/Zoom");
const geom = require("ol/geom");
const format = require("ol/format");
const loadingstrategy = require("ol/loadingstrategy");
require("ol-contextmenu/ol-contextmenu.css");
require("ol-ext/dist/ol-ext.css");
require("ol/ol.css");
function _interopNamespaceDefault(e) {
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
if (e) {
for (const k2 in e) {
if (k2 !== "default") {
const d2 = Object.getOwnPropertyDescriptor(e, k2);
Object.defineProperty(n, k2, d2.get ? d2 : {
enumerable: true,
get: () => e[k2]
});
}
}
}
n.default = e;
return Object.freeze(n);
}
const extent__namespace = /* @__PURE__ */ _interopNamespaceDefault(extent);
const selectconditions__namespace = /* @__PURE__ */ _interopNamespaceDefault(selectconditions);
const animations__namespace = /* @__PURE__ */ _interopNamespaceDefault(animations);
const geom__namespace = /* @__PURE__ */ _interopNamespaceDefault(geom);
const format__namespace = /* @__PURE__ */ _interopNamespaceDefault(format);
const loadingstrategy__namespace = /* @__PURE__ */ _interopNamespaceDefault(loadingstrategy);
const _sfc_main$1n = /* @__PURE__ */ vue.defineComponent({
__name: "OlFeature",
props: {
properties: {}
},
setup(__props, { expose: __expose }) {
const props = __props;
const vectorSource = vue.inject("vectorSource");
const vectorLayer = vue.inject(
"vectorLayer",
null
);
const heatmapLayer = vue.inject("heatmapLayer", null);
const layer = heatmapLayer || vectorLayer;
const animation = vue.inject(
"animation",
null
);
const feature = vue.ref(
new Feature({ ...props.properties })
);
vue.watch(
() => props.properties,
// Needed as props.properties is optional
(properties) => {
if (properties instanceof Geometry) {
feature.value.setGeometry(properties);
feature.value.setProperties({});
} else if (typeof properties !== "undefined") {
feature.value.setGeometry(void 0);
feature.value.setProperties(properties);
} else {
feature.value.setGeometry(void 0);
feature.value.setProperties({});
}
}
);
vue.watch(
() => vectorSource,
(newVal, oldVal) => {
oldVal?.value?.removeFeature(feature.value);
newVal?.value?.addFeature(feature.value);
newVal?.value?.changed();
}
);
vue.onMounted(() => {
if (animation?.value) {
layer?.value?.animateFeature(feature.value, animation.value);
}
vue.nextTick(() => {
vectorSource?.value?.addFeature(feature.value);
});
});
vue.onUnmounted(() => {
vectorSource?.value?.removeFeature(feature.value);
});
vue.provide("feature", feature);
vue.provide("stylable", feature);
__expose({
feature
});
return (_ctx, _cache) => {
return vue.renderSlot(_ctx.$slots, "default");
};
}
});
function checkAndUpdateStylePropDef(options) {
if ("styles" in options) {
const { styles, ...rest } = vue.toRefs(vue.reactive(options));
return { style: styles, ...rest };
} else {
return options;
}
}
function usePropsAsObjectProperties(props) {
const instance = vue.getCurrentInstance();
let globalOptions = {
debug: false
};
if (instance) {
globalOptions = vue.inject("ol-options", globalOptions);
}
const revisedProps = checkAndUpdateStylePropDef(props);
const properties = vue.reactive(revisedProps);
if (globalOptions?.debug) {
console.debug("[Vue3-OpenLayers Debug] PROPS", {
in: props,
out: properties
});
}
return properties;
}
const COMMON_EVENTS = ["change", "error", "propertychange"];
const LAYER_EVENTS = [
"change:extent",
"change:maxResolution",
"change:maxZoom",
"change:minResolution",
"change:minZoom",
"change:opacity",
"change:source",
"change:visible",
"change:zIndex",
"postrender",
"prerender",
"sourceready"
];
const TILE_SOURCE_EVENTS = [
"tileloadend",
"tileloaderror",
"tileloadstart"
];
const IMAGE_SOURCE_EVENTS = [
"imageloadend",
"imageloaderror",
"imageloadstart"
];
const VECTOR_SOURCE_EVENTS = [
"addfeature",
"changefeature",
"clear",
"featuresloadend",
"featuresloaderror",
"featuresloadstart",
"removefeature"
];
function useOpenLayersEvents(feature, eventNames) {
const instance = vue.getCurrentInstance();
let globalOptions = {
debug: false
};
if (instance) {
globalOptions = vue.inject("ol-options", globalOptions);
}
function updateOpenLayersEventHandlers() {
[...COMMON_EVENTS, ...eventNames].forEach((eventName) => {
let unwrappedFeature;
if (vue.isRef(feature)) {
unwrappedFeature = feature.value;
} else {
unwrappedFeature = feature;
}
unwrappedFeature.on(eventName, (...args) => {
if (globalOptions?.debug) {
console.debug("[Vue3-OpenLayers Debug] EVENT", eventName, {
eventName,
args,
source: feature
});
}
instance?.emit(eventName, ...args);
});
});
}
if (instance) {
vue.onMounted(() => {
updateOpenLayersEventHandlers();
});
}
return {
updateOpenLayersEventHandlers
};
}
const _sfc_main$1m = /* @__PURE__ */ vue.defineComponent({
...{
inheritAttrs: false
},
__name: "OlGeoLocation",
props: {
tracking: { type: Boolean, default: true },
trackingOptions: { default: () => ({
enableHighAccuracy: true
}) },
projection: { default: "EPSG:3857" }
},
emits: ["change", "error", "propertychange", "change:accuracy", "change:accuracyGeometry", "change:altitude", "change:altitudeAccuracy", "change:heading", "change:position", "change:projection", "change:speed", "change:tracking", "change:trackingOptions"],
setup(__props, { expose: __expose }) {
const props = __props;
const properties = usePropsAsObjectProperties(props);
const geoLoc = vue.computed(() => new Geolocation(properties));
useOpenLayersEvents(geoLoc, [
"change:accuracy",
"change:accuracyGeometry",
"change:altitude",
"change:altitudeAccuracy",
"change:heading",
"change:position",
"change:projection",
"change:speed",
"change:tracking",
"change:trackingOptions"
]);
const position = vue.ref([]);
const accuracy = vue.ref(0);
const altitude = vue.ref(0);
const altitudeAccuracy = vue.ref(0);
const speed = vue.ref(0);
const heading = vue.ref(0);
const accuracyGeometry = vue.ref(null);
__expose({
geoLoc,
position,
accuracy,
altitude,
altitudeAccuracy,
speed,
heading,
accuracyGeometry
});
return (_ctx, _cache) => {
return vue.renderSlot(_ctx.$slots, "default", {
position: position.value,
speed: speed.value,
heading: heading.value,
accuracy: accuracy.value,
altitude: altitude.value,
altitudeAccuracy: altitudeAccuracy.value,
accuracyGeometry: accuracyGeometry.value
});
};
}
});
function mergeProperties(existingProperties, newProperties) {
for (const key in newProperties) {
if (Object.prototype.hasOwnProperty.call(newProperties, key)) {
if (newProperties[key] !== void 0) {
existingProperties[key] = newProperties[key];
}
}
}
return existingProperties;
}
const _sfc_main$1l = /* @__PURE__ */ vue.defineComponent({
__name: "OlMap",
props: {
controls: {},
pixelRatio: {},
interactions: {},
keyboardEventTarget: {},
layers: {},
maxTilesLoading: {},
moveTolerance: {},
overlays: {},
target: {},
view: {},
instance: {}
},
emits: ["change", "error", "propertychange", "change:layerGroup", "change:size", "change:target", "change:view", "click", "dblclick", "singleclick", "loadstart", "loadend", "pointerdrag", "pointermove", "movestart", "moveend", "postrender", "precompose", "postcompose", "rendercomplete"],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emit = __emit;
const properties = usePropsAsObjectProperties({
...props,
instance: void 0
});
const mapRef = vue.ref(void 0);
let map = props.instance || new Map({ ...properties });
vue.watch(
properties,
() => {
const p2 = props.instance ? mergeProperties(properties, props.instance.getProperties()) : properties;
map?.setProperties(p2);
},
{ immediate: true }
);
vue.onMounted(() => {
if (!props.instance) {
map?.setTarget(mapRef.value);
}
});
vue.onBeforeUnmount(() => {
if (!props.instance) {
map?.setTarget(void 0);
}
});
vue.onUnmounted(() => {
map = void 0;
});
vue.provide("map", map);
const forEachFeatureAtPixel = (pixel, callback, options) => map?.forEachFeatureAtPixel(pixel, callback, options);
const getCoordinateFromPixel = (pixel) => map?.getCoordinateFromPixel(pixel);
const render = () => map?.render();
const updateSize = () => map?.updateSize();
map.on("change", (event) => emit("change", event));
map.on("error", (event) => emit("error", event));
map.on("propertychange", (event) => emit("propertychange", event));
map.on("click", (event) => emit("click", event));
map.on("change:size", (event) => emit("change:size", event));
map.on("change:target", (event) => emit("change:target", event));
map.on("change:view", (event) => emit("change:view", event));
map.on("dblclick", (event) => emit("dblclick", event));
map.on("singleclick", (event) => emit("singleclick", event));
map.on("pointerdrag", (event) => emit("pointerdrag", event));
map.on("pointermove", (event) => emit("pointermove", event));
map.on("movestart", (event) => emit("movestart", event));
map.on("moveend", (event) => emit("moveend", event));
map.on("postrender", (event) => emit("postrender", event));
map.on("precompose", (event) => emit("precompose", event));
map.on("postcompose", (event) => emit("postcompose", event));
map.on("rendercomplete", (event) => emit("rendercomplete", event));
map.on("loadstart", (event) => {
map?.getTargetElement().classList.add("ol-map");
map?.getTargetElement().classList.add("ol-map-loading");
map?.getTargetElement().classList.remove("ol-map-fully-loaded");
emit("loadstart", event);
});
map.on("loadend", (event) => {
map?.getTargetElement().classList.add("ol-map-fully-loaded");
map?.getTargetElement().classList.remove("ol-map-loading");
emit("loadend", event);
});
__expose({
map,
mapRef,
forEachFeatureAtPixel,
getCoordinateFromPixel,
render,
updateSize
});
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", {
ref_key: "mapRef",
ref: mapRef
}, [
vue.renderSlot(_ctx.$slots, "default")
], 512);
};
}
});
const _sfc_main$1k = /* @__PURE__ */ vue.defineComponent({
...{
inheritAttrs: false
},
__name: "OlOverlay",
props: {
id: {},
element: {},
offset: {},
position: {},
positioning: {},
stopEvent: { type: Boolean, default: true },
insertFirst: { type: Boolean, default: true },
autoPan: { type: [Boolean, Object] },
className: {}
},
emits: ["change", "error", "propertychange", "change:element", "change:map", "change:offset", "change:position", "change:positioning"],
setup(__props, { expose: __expose }) {
const props = __props;
const map = vue.inject("map");
const htmlContent = vue.ref();
const properties = usePropsAsObjectProperties(props);
const overlay = vue.shallowRef(new Overlay(properties));
useOpenLayersEvents(overlay, [
"change:element",
"change:map",
"change:offset",
"change:position",
"change:positioning"
]);
const getOffset = () => overlay.value.getOffset();
const getPosition = () => overlay.value.getPosition();
const getPositioning = () => overlay.value.getPositioning();
const panIntoView = (optPanIntoViewOptions) => overlay.value.panIntoView(optPanIntoViewOptions);
const setElement = (element) => overlay.value.setElement(element);
const setOffset = (offset) => overlay.value.setOffset(offset);
const setPosition = (position) => overlay.value.setPosition(position);
const setPositioning = (positioning) => overlay.value.setPositioning(positioning);
function removeOverlay(ov) {
const removed = map?.removeOverlay(ov);
if (!removed) {
console.warn("couldn't find matching overlay to remove", overlay.value);
}
}
vue.onMounted(() => {
map?.addOverlay(overlay.value);
});
vue.onUnmounted(() => removeOverlay(overlay.value));
vue.watch(
() => properties,
(newValue) => {
for (const key in newValue) {
const keyInObj = key;
if (newValue[keyInObj] !== void 0) {
overlay.value.set(key, newValue[keyInObj]);
}
}
},
{ deep: true }
);
vue.watchEffect(
() => {
setElement(htmlContent.value);
},
{
flush: "post"
}
);
__expose({
overlay,
htmlContent,
getOffset,
getPosition,
getPositioning,
panIntoView,
setElement,
setOffset,
setPosition,
setPositioning
});
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", {
ref_key: "htmlContent",
ref: htmlContent
}, [
vue.renderSlot(_ctx.$slots, "default", { position: _ctx.position })
], 512);
};
}
});
function globals(defs2) {
defs2("EPSG:4326", "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees");
defs2("EPSG:4269", "+title=NAD83 (long/lat) +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees");
defs2("EPSG:3857", "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs");
for (var i2 = 1; i2 <= 60; ++i2) {
defs2("EPSG:" + (32600 + i2), "+proj=utm +zone=" + i2 + " +datum=WGS84 +units=m");
defs2("EPSG:" + (32700 + i2), "+proj=utm +zone=" + i2 + " +south +datum=WGS84 +units=m");
}
defs2.WGS84 = defs2["EPSG:4326"];
defs2["EPSG:3785"] = defs2["EPSG:3857"];
defs2.GOOGLE = defs2["EPSG:3857"];
defs2["EPSG:900913"] = defs2["EPSG:3857"];
defs2["EPSG:102113"] = defs2["EPSG:3857"];
}
var PJD_3PARAM = 1;
var PJD_7PARAM = 2;
var PJD_GRIDSHIFT = 3;
var PJD_WGS84 = 4;
var PJD_NODATUM = 5;
var SRS_WGS84_SEMIMAJOR = 6378137;
var SRS_WGS84_SEMIMINOR = 6356752314e-3;
var SRS_WGS84_ESQUARED = 0.0066943799901413165;
var SEC_TO_RAD = 484813681109536e-20;
var HALF_PI = Math.PI / 2;
var SIXTH = 0.16666666666666666;
var RA4 = 0.04722222222222222;
var RA6 = 0.022156084656084655;
var EPSLN = 1e-10;
var D2R$1 = 0.017453292519943295;
var R2D = 57.29577951308232;
var FORTPI = Math.PI / 4;
var TWO_PI = Math.PI * 2;
var SPI = 3.14159265359;
var primeMeridian = {};
primeMeridian.greenwich = 0;
primeMeridian.lisbon = -9.131906111111;
primeMeridian.paris = 2.337229166667;
primeMeridian.bogota = -74.080916666667;
primeMeridian.madrid = -3.687938888889;
primeMeridian.rome = 12.452333333333;
primeMeridian.bern = 7.439583333333;
primeMeridian.jakarta = 106.807719444444;
primeMeridian.ferro = -17.666666666667;
primeMeridian.brussels = 4.367975;
primeMeridian.stockholm = 18.058277777778;
primeMeridian.athens = 23.7163375;
primeMeridian.oslo = 10.722916666667;
const units = {
mm: { to_meter: 1e-3 },
cm: { to_meter: 0.01 },
ft: { to_meter: 0.3048 },
"us-ft": { to_meter: 1200 / 3937 },
fath: { to_meter: 1.8288 },
kmi: { to_meter: 1852 },
"us-ch": { to_meter: 20.1168402336805 },
"us-mi": { to_meter: 1609.34721869444 },
km: { to_meter: 1e3 },
"ind-ft": { to_meter: 0.30479841 },
"ind-yd": { to_meter: 0.91439523 },
mi: { to_meter: 1609.344 },
yd: { to_meter: 0.9144 },
ch: { to_meter: 20.1168 },
link: { to_meter: 0.201168 },
dm: { to_meter: 0.1 },
in: { to_meter: 0.0254 },
"ind-ch": { to_meter: 20.11669506 },
"us-in": { to_meter: 0.025400050800101 },
"us-yd": { to_meter: 0.914401828803658 }
};
var ignoredChar = /[\s_\-\/\(\)]/g;
function match(obj, key) {
if (obj[key]) {
return obj[key];
}
var keys = Object.keys(obj);
var lkey = key.toLowerCase().replace(ignoredChar, "");
var i2 = -1;
var testkey, processedKey;
while (++i2 < keys.length) {
testkey = keys[i2];
processedKey = testkey.toLowerCase().replace(ignoredChar, "");
if (processedKey === lkey) {
return obj[testkey];
}
}
}
function projStr(defData) {
var self2 = {};
var paramObj = defData.split("+").map(function(v2) {
return v2.trim();
}).filter(function(a2) {
return a2;
}).reduce(function(p2, a2) {
var split = a2.split("=");
split.push(true);
p2[split[0].toLowerCase()] = split[1];
return p2;
}, {});
var paramName, paramVal, paramOutname;
var params2 = {
proj: "projName",
datum: "datumCode",
rf: function(v2) {
self2.rf = parseFloat(v2);
},
lat_0: function(v2) {
self2.lat0 = v2 * D2R$1;
},
lat_1: function(v2) {
self2.lat1 = v2 * D2R$1;
},
lat_2: function(v2) {
self2.lat2 = v2 * D2R$1;
},
lat_ts: function(v2) {
self2.lat_ts = v2 * D2R$1;
},
lon_0: function(v2) {
self2.long0 = v2 * D2R$1;
},
lon_1: function(v2) {
self2.long1 = v2 * D2R$1;
},
lon_2: function(v2) {
self2.long2 = v2 * D2R$1;
},
alpha: function(v2) {
self2.alpha = parseFloat(v2) * D2R$1;
},
gamma: function(v2) {
self2.rectified_grid_angle = parseFloat(v2) * D2R$1;
},
lonc: function(v2) {
self2.longc = v2 * D2R$1;
},
x_0: function(v2) {
self2.x0 = parseFloat(v2);
},
y_0: function(v2) {
self2.y0 = parseFloat(v2);
},
k_0: function(v2) {
self2.k0 = parseFloat(v2);
},
k: function(v2) {
self2.k0 = parseFloat(v2);
},
a: function(v2) {
self2.a = parseFloat(v2);
},
b: function(v2) {
self2.b = parseFloat(v2);
},
r: function(v2) {
self2.a = self2.b = parseFloat(v2);
},
r_a: function() {
self2.R_A = true;
},
zone: function(v2) {
self2.zone = parseInt(v2, 10);
},
south: function() {
self2.utmSouth = true;
},
towgs84: function(v2) {
self2.datum_params = v2.split(",").map(function(a2) {
return parseFloat(a2);
});
},
to_meter: function(v2) {
self2.to_meter = parseFloat(v2);
},
units: function(v2) {
self2.units = v2;
var unit = match(units, v2);
if (unit) {
self2.to_meter = unit.to_meter;
}
},
from_greenwich: function(v2) {
self2.from_greenwich = v2 * D2R$1;
},
pm: function(v2) {
var pm = match(primeMeridian, v2);
self2.from_greenwich = (pm ? pm : parseFloat(v2)) * D2R$1;
},
nadgrids: function(v2) {
if (v2 === "@null") {
self2.datumCode = "none";
} else {
self2.nadgrids = v2;
}
},
axis: function(v2) {
var legalAxis = "ewnsud";
if (v2.length === 3 && legalAxis.indexOf(v2.substr(0, 1)) !== -1 && legalAxis.indexOf(v2.substr(1, 1)) !== -1 && legalAxis.indexOf(v2.substr(2, 1)) !== -1) {
self2.axis = v2;
}
},
approx: function() {
self2.approx = true;
}
};
for (paramName in paramObj) {
paramVal = paramObj[paramName];
if (paramName in params2) {
paramOutname = params2[paramName];
if (typeof paramOutname === "function") {
paramOutname(paramVal);
} else {
self2[paramOutname] = paramVal;
}
} else {
self2[paramName] = paramVal;
}
}
if (typeof self2.datumCode === "string" && self2.datumCode !== "WGS84") {
self2.datumCode = self2.datumCode.toLowerCase();
}
return self2;
}
class PROJJSONBuilderBase {
static getId(node) {
const idNode = node.find((child) => Array.isArray(child) && child[0] === "ID");
if (idNode && idNode.length >= 3) {
return {
authority: idNode[1],
code: parseInt(idNode[2], 10)
};
}
return null;
}
static convertUnit(node, type = "unit") {
if (!node || node.length < 3) {
return { type, name: "unknown", conversion_factor: null };
}
const name = node[1];
const conversionFactor = parseFloat(node[2]) || null;
const idNode = node.find((child) => Array.isArray(child) && child[0] === "ID");
const id = idNode ? {
authority: idNode[1],
code: parseInt(idNode[2], 10)
} : null;
return {
type,
name,
conversion_factor: conversionFactor,
id
};
}
static convertAxis(node) {
const name = node[1] || "Unknown";
let direction;
const abbreviationMatch = name.match(/^\((.)\)$/);
if (abbreviationMatch) {
const abbreviation = abbreviationMatch[1].toUpperCase();
if (abbreviation === "E") direction = "east";
else if (abbreviation === "N") direction = "north";
else if (abbreviation === "U") direction = "up";
else throw new Error(`Unknown axis abbreviation: ${abbreviation}`);
} else {
direction = node[2] ? node[2].toLowerCase() : "unknown";
}
const orderNode = node.find((child) => Array.isArray(child) && child[0] === "ORDER");
const order = orderNode ? parseInt(orderNode[1], 10) : null;
const unitNode = node.find(
(child) => Array.isArray(child) && (child[0] === "LENGTHUNIT" || child[0] === "ANGLEUNIT" || child[0] === "SCALEUNIT")
);
const unit = this.convertUnit(unitNode);
return {
name,
direction,
// Use the valid PROJJSON direction value
unit,
order
};
}
static extractAxes(node) {
return node.filter((child) => Array.isArray(child) && child[0] === "AXIS").map((axis) => this.convertAxis(axis)).sort((a2, b2) => (a2.order || 0) - (b2.order || 0));
}
static convert(node, result = {}) {
switch (node[0]) {
case "PROJCRS":
result.type = "ProjectedCRS";
result.name = node[1];
result.base_crs = node.find((child) => Array.isArray(child) && child[0] === "BASEGEOGCRS") ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "BASEGEOGCRS")) : null;
result.conversion = node.find((child) => Array.isArray(child) && child[0] === "CONVERSION") ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "CONVERSION")) : null;
const csNode = node.find((child) => Array.isArray(child) && child[0] === "CS");
if (csNode) {
result.coordinate_system = {
type: csNode[1],
axis: this.extractAxes(node)
};
}
const lengthUnitNode = node.find((child) => Array.isArray(child) && child[0] === "LENGTHUNIT");
if (lengthUnitNode) {
const unit2 = this.convertUnit(lengthUnitNode);
result.coordinate_system.unit = unit2;
}
result.id = this.getId(node);
break;
case "BASEGEOGCRS":
case "GEOGCRS":
result.type = "GeographicCRS";
result.name = node[1];
const datumOrEnsembleNode = node.find(
(child) => Array.isArray(child) && (child[0] === "DATUM" || child[0] === "ENSEMBLE")
);
if (datumOrEnsembleNode) {
const datumOrEnsemble = this.convert(datumOrEnsembleNode);
if (datumOrEnsembleNode[0] === "ENSEMBLE") {
result.datum_ensemble = datumOrEnsemble;
} else {
result.datum = datumOrEnsemble;
}
const primem = node.find((child) => Array.isArray(child) && child[0] === "PRIMEM");
if (primem && primem[1] !== "Greenwich") {
datumOrEnsemble.prime_meridian = {
name: primem[1],
longitude: parseFloat(primem[2])
};
}
}
result.coordinate_system = {
type: "ellipsoidal",
axis: this.extractAxes(node)
};
result.id = this.getId(node);
break;
case "DATUM":
result.type = "GeodeticReferenceFrame";
result.name = node[1];
result.ellipsoid = node.find((child) => Array.isArray(child) && child[0] === "ELLIPSOID") ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "ELLIPSOID")) : null;
break;
case "ENSEMBLE":
result.type = "DatumEnsemble";
result.name = node[1];
result.members = node.filter((child) => Array.isArray(child) && child[0] === "MEMBER").map((member) => ({
type: "DatumEnsembleMember",
name: member[1],
id: this.getId(member)
// Extract ID as { authority, code }
}));
const accuracyNode = node.find((child) => Array.isArray(child) && child[0] === "ENSEMBLEACCURACY");
if (accuracyNode) {
result.accuracy = parseFloat(accuracyNode[1]);
}
const ellipsoidNode = node.find((child) => Array.isArray(child) && child[0] === "ELLIPSOID");
if (ellipsoidNode) {
result.ellipsoid = this.convert(ellipsoidNode);
}
result.id = this.getId(node);
break;
case "ELLIPSOID":
result.type = "Ellipsoid";
result.name = node[1];
result.semi_major_axis = parseFloat(node[2]);
result.inverse_flattening = parseFloat(node[3]);
node.find((child) => Array.isArray(child) && child[0] === "LENGTHUNIT") ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "LENGTHUNIT"), result) : null;
break;
case "CONVERSION":
result.type = "Conversion";
result.name = node[1];
result.method = node.find((child) => Array.isArray(child) && child[0] === "METHOD") ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "METHOD")) : null;
result.parameters = node.filter((child) => Array.isArray(child) && child[0] === "PARAMETER").map((param) => this.convert(param));
break;
case "METHOD":
result.type = "Method";
result.name = node[1];
result.id = this.getId(node);
break;
case "PARAMETER":
result.type = "Parameter";
result.name = node[1];
result.value = parseFloat(node[2]);
result.unit = this.convertUnit(
node.find(
(child) => Array.isArray(child) && (child[0] === "LENGTHUNIT" || child[0] === "ANGLEUNIT" || child[0] === "SCALEUNIT")
)
);
result.id = this.getId(node);
break;
case "BOUNDCRS":
result.type = "BoundCRS";
const sourceCrsNode = node.find((child) => Array.isArray(child) && child[0] === "SOURCECRS");
if (sourceCrsNode) {
const sourceCrsContent = sourceCrsNode.find((child) => Array.isArray(child));
result.source_crs = sourceCrsContent ? this.convert(sourceCrsContent) : null;
}
const targetCrsNode = node.find((child) => Array.isArray(child) && child[0] === "TARGETCRS");
if (targetCrsNode) {
const targetCrsContent = targetCrsNode.find((child) => Array.isArray(child));
result.target_crs = targetCrsContent ? this.convert(targetCrsContent) : null;
}
const transformationNode = node.find((child) => Array.isArray(child) && child[0] === "ABRIDGEDTRANSFORMATION");
if (transformationNode) {
result.transformation = this.convert(transformationNode);
} else {
result.transformation = null;
}
break;
case "ABRIDGEDTRANSFORMATION":
result.type = "Transformation";
result.name = node[1];
result.method = node.find((child) => Array.isArray(child) && child[0] === "METHOD") ? this.convert(node.find((child) => Array.isArray(child) && child[0] === "METHOD")) : null;
result.parameters = node.filter((child) => Array.isArray(child) && (child[0] === "PARAMETER" || child[0] === "PARAMETERFILE")).map((param) => {
if (param[0] === "PARAMETER") {
return this.convert(param);
} else if (param[0] === "PARAMETERFILE") {
return {
name: param[1],
value: param[2],
id: {
"authority": "EPSG",
"code": 8656
}
};
}
});
if (result.parameters.length === 7) {
const scaleDifference = result.parameters[6];
if (scaleDifference.name === "Scale difference") {
scaleDifference.value = Math.round((scaleDifference.value - 1) * 1e12) / 1e6;
}
}
result.id = this.getId(node);
break;
case "AXIS":
if (!result.coordinate_system) {
result.coordinate_system = { type: "unspecified", axis: [] };
}
result.coordinate_system.axis.push(this.convertAxis(node));
break;
case "LENGTHUNIT":
const unit = this.convertUnit(node, "LinearUnit");
if (result.coordinate_system && result.coordinate_system.axis) {
result.coordinate_system.axis.forEach((axis) => {
if (!axis.unit) {
axis.unit = unit;
}
});
}
if (unit.conversion_factor && unit.conversion_factor !== 1) {
if (result.semi_major_axis) {
result.semi_major_axis = {
value: result.semi_major_axis,
unit
};
}
}
break;
default:
result.keyword = node[0];
break;
}
return result;
}
}
class PROJJSONBuilder2015 extends PROJJSONBuilderBase {
static convert(node, result = {}) {
super.convert(node, result);
if (result.coordinate_system && result.coordinate_system.subtype === "Cartesian") {
delete result.coordinate_system;
}
if (result.usage) {
delete result.usage;
}
return result;
}
}
class PROJJSONBuilder2019 extends PROJJSONBuilderBase {
static convert(node, result = {}) {
super.convert(node, result);
const csNode = node.find((child) => Array.isArray(child) && child[0] === "CS");
if (csNode) {
result.coordinate_system = {
subtype: csNode[1],
axis: this.extractAxes(node)
};
}
const usageNode = node.find((child) => Array.isArray(child) && child[0] === "USAGE");
if (usageNode) {
const scope = usageNode.find((child) => Array.isArray(child) && child[0] === "SCOPE");
const area = usageNode.find((child) => Array.isArray(child) && child[0] === "AREA");
const bbox = usageNode.find((child) => Array.isArray(child) && child[0] === "BBOX");
result.usage = {};
if (scope) {
result.usage.scope = scope[1];
}
if (area) {
result.usage.area = area[1];
}
if (bbox) {
result.usage.bbox = bbox.slice(1);
}
}
return result;
}
}
function detectWKT2Version(root) {
if (root.find((child) => Array.isArray(child) && child[0] === "USAGE")) {
return "2019";
}
if (root.find((child) => Array.isArray(child) && child[0] === "CS")) {
return "2015";
}
if (root[0] === "BOUNDCRS" || root[0] === "PROJCRS" || root[0] === "GEOGCRS") {
return "2015";
}
return "2015";
}
function buildPROJJSON(root) {
const version = detectWKT2Version(root);
const builder = version === "2019" ? PROJJSONBuilder2019 : PROJJSONBuilder2015;
return builder.convert(root);
}
function detectWKTVersion(wkt2) {
const normalizedWKT = wkt2.toUpperCase();
if (normalizedWKT.includes("PROJCRS") || normalizedWKT.includes("GEOGCRS") || normalizedWKT.includes("BOUNDCRS") || normalizedWKT.includes("VERTCRS") || normalizedWKT.includes("LENGTHUNIT") || normalizedWKT.includes("ANGLEUNIT") || normalizedWKT.includes("SCALEUNIT")) {
return "WKT2";
}
if (normalizedWKT.includes("PROJCS") || normalizedWKT.includes("GEOGCS") || normalizedWKT.includes("LOCAL_CS") || normalizedWKT.includes("VERT_CS") || normalizedWKT.includes("UNIT")) {
return "WKT1";
}
return "WKT1";
}
var NEUTRAL = 1;
var KEYWORD = 2;
var NUMBER = 3;
var QUOTED = 4;
var AFTERQUOTE = 5;
var ENDED = -1;
var whitespace = /\s/;
var latin = /[A-Za-z]/;
var keyword = /[A-Za-z84_]/;
var endThings = /[,\]]/;
var digets = /[\d\.E\-\+]/;
function Parser(text) {
if (typeof text !== "string") {
throw new Error("not a string");
}
this.text = text.trim();
this.level = 0;
this.place = 0;
this.root = null;
this.stack = [];
this.currentObject = null;
this.state = NEUTRAL;
}
Parser.prototype.readCharicter = function() {
var char = this.text[this.place++];
if (this.state !== QUOTED) {
while (whitespace.test(char)) {
if (this.place >= this.text.length) {
return;
}
char = this.text[this.place++];
}
}
switch (this.state) {
case NEUTRAL:
return this.neutral(char);
case KEYWORD:
return this.keyword(char);
case QUOTED:
return this.quoted(char);
case AFTERQUOTE:
return this.afterquote(char);
case NUMBER:
return this.number(char);
case ENDED:
return;
}
};
Parser.prototype.afterquote = function(char) {
if (char === '"') {
this.word += '"';
this.state = QUOTED;
return;
}
if (endThings.test(char)) {
this.word = this.word.trim();
this.afterItem(char);
return;
}
throw new Error(`havn't handled "` + char + '" in afterquote yet, index ' + this.place);
};
Parser.prototype.afterItem = function(char) {
if (char === ",") {
if (this.word !== null) {
this.currentObject.push(this.word);
}
this.word = null;
this.state = NEUTRAL;
return;
}
if (char === "]") {
this.level--;
if (this.word !== null) {
this.currentObject.push(this.word);
this.word = null;
}
this.state = NEUTRAL;
this.currentObject = this.stack.pop();
if (!this.currentObject) {
this.state = ENDED;
}
return;
}
};
Parser.prototype.number = function(char) {
if (digets.test(char)) {
this.word += char;
return;
}
if (endThings.test(char)) {
this.word = parseFloat(this.word);
this.afterItem(char);
return;
}
throw new Error(`havn't handled "` + char + '" in number yet, index ' + this.place);
};
Parser.prototype.quoted = function(char) {
if (char === '"') {
this.state = AFTERQUOTE;
return;
}
this.word += char;
return;
};
Parser.prototype.keyword = function(char) {
if (keyword.test(char)) {
this.word += char;
return;
}
if (char === "[") {
var newObjects = [];
newObjects.push(this.word);
this.level++;
if (this.root === null) {
this.root = newObjects;
} else {
this.currentObject.push(newObjects);
}
this.stack.push(this.currentObject);
this.currentObject = newObjects;
this.state = NEUTRAL;
return;
}
if (endThings.test(char)) {
this.afterItem(char);
return;
}
throw new Error(`havn't handled "` + char + '" in keyword yet, index ' + this.place);
};
Parser.prototype.neutral = function(char) {
if (latin.test(char)) {
this.word = char;
this.state = KEYWORD;
return;
}
if (char === '"') {
this.word = "";
this.state = QUOTED;
return;
}
if (digets.test(char)) {
this.word = char;
this.state = NUMBER;
return;
}
if (endThings.test(char)) {
this.afterItem(char);
return;
}
throw new Error(`havn't handled "` + char + '" in neutral yet, index ' + this.place);
};
Parser.prototype.output = function() {
while (this.place < this.text.length) {
this.readCharicter();
}
if (this.state === ENDED) {
return this.root;
}
throw new Error('unable to parse string "' + this.text + '". State is ' + this.state);
};
function parseString(txt) {
var parser = new Parser(txt);
return parser.output();
}
function mapit(obj, key, value) {
if (Array.isArray(key)) {
value.unshift(key);
key = null;
}
var thing = key ? {} : obj;
var out = value.reduce(function(newObj, item) {
sExpr(item, newObj);
return newObj;
}, thing);
if (key) {
obj[key] = out;
}
}
function sExpr(v2, obj) {
if (!Array.isArray(v2)) {
obj[v2] = true;
return;
}
var key = v2.shift();
if (key === "PARAMETER") {
key = v2.shift();
}
if (v2.length === 1) {
if (Array.isArray(v2[0])) {
obj[key] = {};
sExpr(v2[0], obj[key]);
return;
}
obj[key] = v2[0];
return;
}
if (!v2.length) {
obj[key] = true;
return;
}
if (key === "TOWGS84") {
obj[key] = v2;
return;
}
if (key === "AXIS") {
if (!(key in obj)) {
obj[key] = [];
}
obj[key].push(v2);
return;
}
if (!Array.isArray(key)) {
obj[key] = {};
}
var i2;
switch (key) {
case "UNIT":
case "PRIMEM":
case "VERT_DATUM":
obj[key] = {
name: v2[0].toLowerCase(),
convert: v2[1]
};
if (v2.length === 3) {
sExpr(v2[2], obj[key]);
}
return;
case "SPHEROID":
case "ELLIPSOID":
obj[key] = {
name: v2[0],
a: v2[1],
rf: v2[2]
};
if (v2.length === 4) {
sExpr(v2[3], obj[key]);
}
return;
case "EDATUM":
case "ENGINEERINGDATUM":
case "LOCAL_DATUM":
case "DATUM":
case "VERT_CS":
case "VERTCRS":
case "VERTICALCRS":
v2[0] = ["name", v2[0]];
mapit(obj, key, v2);
return;
case "COMPD_CS":
case "COMPOUNDCRS":
case "FITTED_CS":
// the followings are the crs defined in
// https://github.com/proj4js/proj4js/blob/1da4ed0b865d0fcb51c136090569210cdcc9019e/lib/parseCode.js#L11
case "PROJECTEDCRS":
case "PROJCRS":
case "GEOGCS":
case "GEOCCS":
case "PROJCS":
case "LOCAL_CS":
case "GEODCRS":
case "GEODETICCRS":
case "GEODETICDATUM":
case "ENGCRS":
case "ENGINEERINGCRS":
v2[0] = ["name", v2[0]];
mapit(obj, key, v2);
obj[key].type = key;
return;
default:
i2 = -1;
while (++i2 < v2.length) {
if (!Array.isArray(v2[i2])) {
return sExpr(v2, obj[key]);
}
}
return mapit(obj, key, v2);
}
}
var D2R = 0.017453292519943295;
function d2r(input) {
return input * D2R;
}
function applyProjectionDefaults(wkt2) {
const normalizedProjName = (wkt2.projName || "").toLowerCase().replace(/_/g, " ");
if (!wkt2.long0 && wkt2.longc && (normalizedProjName === "albers conic equal area" || normalizedProjName === "lambert azimuthal equal area")) {
wkt2.long0 = wkt2.longc;
}
if (!wkt2.lat_ts && wkt2.lat1 && (normalizedProjName === "stereographic south pole" || normalizedProjName === "polar stereographic (variant b)")) {
wkt2.lat0 = d2r(wkt2.lat1 > 0 ? 90 : -90);
wkt2.lat_ts = wkt2.lat1;
delete wkt2.lat1;
} else if (!wkt2.lat_ts && wkt2.lat0 && (normalizedProjName === "polar stereographic" || normalizedProjName === "polar stereographic (variant a)")) {
wkt2.lat_ts = wkt2.lat0;
wkt2.lat0 = d2r(wkt2.lat0 > 0 ? 90 : -90);
delete wkt2.lat1;
}
}
function processUnit(unit) {
let result = { units: null, to_meter: void 0 };
if (typeof unit === "string") {
result.units = unit.toLowerCase();
if (result.units === "metre") {
result.units = "meter";
}
if (result.units === "meter") {
result.to_meter = 1;
}
} else if (unit && unit.name) {
result.units = unit.name.toLowerCase();
if (result.units === "metre") {
result.units = "meter";
}
result.to_meter = unit.conversion_factor;
}
return result;
}
function toValue(valueOrObject) {
if (typeof valueOrObject === "object") {
return valueOrObject.value * valueOrObject.unit.conversion_factor;
}
return valueOrObject;
}
function calculateEllipsoid(value, result) {
if (value.ellipsoid.radius) {
result.a = value.ellipsoid.radius;
result.rf = 0;
} else {
result.a = toValue(value.ellipsoid.semi_major_axis);
if (value.ellipsoid.inverse_flattening !== void 0) {
result.rf = value.ellipsoid.inverse_flattening;
} else if (value.ellipsoid.semi_major_axis !== void 0 && value.ellipsoid.semi_minor_axis !== void 0) {
result.rf = result.a / (result.a - toValue(value.ellipsoid.semi_minor_axis));
}
}
}
function transformPROJJSON(projjson, result = {}) {
if (!projjson || typeof projjson !== "object") {
return projjson;
}
if (projjson.type === "BoundCRS") {
transformPROJJSON(projjson.source_crs, result);
if (projjson.transformation) {
if (projjson.transformation.method && projjson.transformation.method.name === "NTv2") {
result.nadgrids = projjson.transformation.parameters[0].value;
} else {
result.datum_params = projjson.transformation.parameters.map((param) => param.value);
}
}
return result;
}
Object.keys(projjson).forEach((key) => {
const value = projjson[key];
if (value === null) {
return;
}
switch (key) {
case "name":
if (result.srsCode) {
break;
}
result.name = value;
result.srsCode = value;
break;
case "type":
if (value === "GeographicCRS") {
result.projName = "longlat";
} else if (value === "ProjectedCRS" && projjson.conversion && projjson.conversion.method) {
result.projName = projjson.conversion.method.name;
}
break;
case "datum":
case "datum_ensemble":
if (value.ellipsoid) {
result.ellps = value.ellipsoid.name;
calculateEllipsoid(value, result);
}
if (value.prime_meridian) {
result.from_greenwich = value.prime_meridian.longitude * Math.PI / 180;
}
break;
case "ellipsoid":
result.ellps = value.name;
calculateEllipsoid(value, result);
break;
case "prime_meridian":
result.long0 = (value.longitude || 0) * Math.PI / 180;
break;
case "coordinate_system":
if (value.axis) {
result.axis = value.axis.map((axis) => {
const direction = axis.direction;
if (direction === "east") return "e";
if (direction === "north") return "n";
if (direction === "west") return "w";
if (direction === "south") return "s";
throw new Error(`Unknown axis direction: ${direction}`);
}).join("") + "u";
if (value.unit) {
const { units: units2, to_meter } = processUnit(value.unit);
result.units = units2;
result.to_meter = to_meter;
} else if (value.axis[0] && value.axis[0].unit) {
const { units: units2, to_meter } = processUnit(value.axis[0].unit);
result.units = units2;
result.to_meter = to_meter;
}
}
break;
case "id":
if (value.authority && value.code) {
result.title = value.authority + ":" + value.code;
}
break;
case "conversion":
if (value.method && value.method.name) {
result.projName = value.method.name;
}
if (value.parameters) {
value.parameters.forEach((param) => {
const paramName = param.name.toLowerCase().replace(/\s+/g, "_");
const paramValue = param.value;
if (param.unit && param.unit.conversion_factor) {
result[paramName] = paramValue * param.unit.conversion_factor;
} else if (param.unit === "degree") {
result[paramName] = paramValue * Math.PI / 180;
} else {
result[paramName] = paramValue;
}
});
}
break;
case "unit":
if (value.name) {
result.units = value.name.toLowerCase();
if (result.units === "metre") {
result.units = "meter";
}
}
if (value.conversion_factor) {
result.to_meter = value.conversion_factor;
}
break;
case "base_crs":
transformPROJJSON(value, result);
result.datumCode = value.id ? value.id.authority + "_" + value.id.code : value.name;
break;
}
});
if (result.latitude_of_false_origin !== void 0) {
result.lat0 = result.latitude_of_false_origin;
}
if (result.longitude_of_false_origin !== void 0) {
result.long0 = result.longitude_of_false_origin;
}
if (result.latitude_of_standard_parallel !== void