2026-03-04 12:59:40 +01:00

2111 lines
67 KiB
JavaScript

import {
ImageCanvas_default,
fromResolutionLike
} from "./chunk-3TN6D4MD.js";
import {
Vector_default as Vector_default2
} from "./chunk-PD2E5XZ4.js";
import {
ARRAY_BUFFER,
AttributeType,
Attributes,
Buffer_default,
DYNAMIC_DRAW,
DefaultUniform,
ELEMENT_ARRAY_BUFFER,
Heatmap_default,
Layer_default as Layer_default2,
PALETTE_TEXTURE_ARRAY,
RenderTarget_default,
TileLayer_default,
Uniforms,
VectorLayer_default as VectorLayer_default2,
VectorTile_default,
WebGLWorkerMessageType,
colorDecodeId,
colorEncodeIdAndPack,
create as create2,
expressionToGlsl,
getStringNumberEquivalent,
getWorldParameters,
newCompilationContext,
parseLiteralStyle,
uniformNameForVariable
} from "./chunk-YUMATXXX.js";
import {
ImageLayer_default,
Image_default
} from "./chunk-E7S7Q7VV.js";
import {
VectorEventType_default
} from "./chunk-V7WRBSQ6.js";
import "./chunk-W7BDJOQY.js";
import {
LineString_default
} from "./chunk-7JXPN73Q.js";
import {
Feature_default
} from "./chunk-E53S5GN6.js";
import {
BaseTile_default,
Tile_default
} from "./chunk-UNDFRJ2M.js";
import {
Immediate_default,
VectorLayer_default,
Vector_default,
getSquaredTolerance
} from "./chunk-T3TT2KJN.js";
import "./chunk-HM3IY3H4.js";
import "./chunk-JFXZSSOM.js";
import "./chunk-ZUI5NXIU.js";
import {
Group_default
} from "./chunk-2C73OZ6M.js";
import {
Collection_default
} from "./chunk-M5TTSD4C.js";
import {
BaseVector_default,
ColorType,
NumberType
} from "./chunk-ZCRXKB7J.js";
import {
RBush
} from "./chunk-RW3V7S4F.js";
import {
Fill_default,
Stroke_default,
Style_default,
Text_default
} from "./chunk-PAB2HIXK.js";
import {
EventType_default as EventType_default2,
Layer_default
} from "./chunk-I6K7MRGV.js";
import "./chunk-PGWX4545.js";
import {
Property_default
} from "./chunk-AYBYZSAV.js";
import {
ViewHint_default
} from "./chunk-YLJGUH5Z.js";
import {
Point_default
} from "./chunk-AZGMK675.js";
import "./chunk-6EWLK2BW.js";
import "./chunk-6Y7C6NBJ.js";
import "./chunk-7XMWB3J4.js";
import "./chunk-5D2XPBR2.js";
import {
ImageState_default
} from "./chunk-SHUBVYN4.js";
import "./chunk-FM44FOIC.js";
import "./chunk-LMC3RO5P.js";
import {
apply,
compose,
create,
makeInverse,
multiply,
translate
} from "./chunk-X52LGBOS.js";
import {
assert
} from "./chunk-QFCIXVZ3.js";
import {
degreesToStringHDMS,
equivalent,
fromUserCoordinate,
get,
getTransform,
getTransformFromProjections,
getUserProjection
} from "./chunk-A3RXLHYB.js";
import "./chunk-ZLPTRF2L.js";
import {
clamp,
squaredSegmentDistance
} from "./chunk-54BTDBAD.js";
import "./chunk-UPTVWZ45.js";
import "./chunk-5XHD7RSF.js";
import {
getUid
} from "./chunk-Q5ZULJHM.js";
import {
listen,
unlistenByKey
} from "./chunk-NGFXCWUF.js";
import {
EventType_default
} from "./chunk-K25ZO44T.js";
import {
applyTransform,
approximatelyEquals,
buffer,
containsCoordinate,
containsExtent,
createEmpty,
equals,
getCenter,
getHeight,
getIntersection,
getWidth,
intersects,
isEmpty,
scaleFromCenter,
wrapX
} from "./chunk-SRXHWJOY.js";
import "./chunk-5RHQVMYD.js";
import "./chunk-DC5AMYBS.js";
// node_modules/ol/geom/flat/geodesic.js
function line(interpolate, transform, squaredTolerance) {
const flatCoordinates = [];
let geoA = interpolate(0);
let geoB = interpolate(1);
let a = transform(geoA);
let b = transform(geoB);
const geoStack = [geoB, geoA];
const stack = [b, a];
const fractionStack = [1, 0];
const fractions = {};
let maxIterations = 1e5;
let geoM, m, fracA, fracB, fracM, key;
while (--maxIterations > 0 && fractionStack.length > 0) {
fracA = fractionStack.pop();
geoA = geoStack.pop();
a = stack.pop();
key = fracA.toString();
if (!(key in fractions)) {
flatCoordinates.push(a[0], a[1]);
fractions[key] = true;
}
fracB = fractionStack.pop();
geoB = geoStack.pop();
b = stack.pop();
fracM = (fracA + fracB) / 2;
geoM = interpolate(fracM);
m = transform(geoM);
if (squaredSegmentDistance(m[0], m[1], a[0], a[1], b[0], b[1]) < squaredTolerance) {
flatCoordinates.push(b[0], b[1]);
key = fracB.toString();
fractions[key] = true;
} else {
fractionStack.push(fracB, fracM, fracM, fracA);
stack.push(b, m, m, a);
geoStack.push(geoB, geoM, geoM, geoA);
}
}
return flatCoordinates;
}
function meridian(lon, lat1, lat2, projection, squaredTolerance) {
const epsg4326Projection = get("EPSG:4326");
return line(
/**
* @param {number} frac Fraction.
* @return {import("../../coordinate.js").Coordinate} Coordinate.
*/
function(frac) {
return [lon, lat1 + (lat2 - lat1) * frac];
},
getTransform(epsg4326Projection, projection),
squaredTolerance
);
}
function parallel(lat, lon1, lon2, projection, squaredTolerance) {
const epsg4326Projection = get("EPSG:4326");
return line(
/**
* @param {number} frac Fraction.
* @return {import("../../coordinate.js").Coordinate} Coordinate.
*/
function(frac) {
return [lon1 + (lon2 - lon1) * frac, lat];
},
getTransform(epsg4326Projection, projection),
squaredTolerance
);
}
// node_modules/ol/render.js
function getVectorContext(event) {
if (!(event.context instanceof CanvasRenderingContext2D)) {
throw new Error("Only works for render events from Canvas 2D layers");
}
const a = event.inversePixelTransform[0];
const b = event.inversePixelTransform[1];
const canvasPixelRatio = Math.sqrt(a * a + b * b);
const frameState = event.frameState;
const transform = multiply(
event.inversePixelTransform.slice(),
frameState.coordinateToPixelTransform
);
const squaredTolerance = getSquaredTolerance(
frameState.viewState.resolution,
canvasPixelRatio
);
let userTransform;
const userProjection = getUserProjection();
if (userProjection) {
userTransform = getTransformFromProjections(
userProjection,
frameState.viewState.projection
);
}
return new Immediate_default(
event.context,
canvasPixelRatio,
frameState.extent,
transform,
frameState.viewState.rotation,
squaredTolerance,
userTransform
);
}
// node_modules/ol/layer/Graticule.js
var DEFAULT_STROKE_STYLE = new Stroke_default({
color: "rgba(0,0,0,0.2)"
});
var INTERVALS = [
90,
45,
30,
20,
10,
5,
2,
1,
30 / 60,
20 / 60,
10 / 60,
5 / 60,
2 / 60,
1 / 60,
30 / 3600,
20 / 3600,
10 / 3600,
5 / 3600,
2 / 3600,
1 / 3600
];
var Graticule = class extends Vector_default {
/**
* @param {Options} [options] Options.
*/
constructor(options) {
options = options ? options : {};
const baseOptions = Object.assign(
{
updateWhileAnimating: true,
updateWhileInteracting: true,
renderBuffer: 0
},
options
);
delete baseOptions.maxLines;
delete baseOptions.strokeStyle;
delete baseOptions.targetSize;
delete baseOptions.showLabels;
delete baseOptions.lonLabelFormatter;
delete baseOptions.latLabelFormatter;
delete baseOptions.lonLabelPosition;
delete baseOptions.latLabelPosition;
delete baseOptions.lonLabelStyle;
delete baseOptions.latLabelStyle;
delete baseOptions.intervals;
super(baseOptions);
this.projection_ = null;
this.maxLat_ = Infinity;
this.maxLon_ = Infinity;
this.minLat_ = -Infinity;
this.minLon_ = -Infinity;
this.maxX_ = Infinity;
this.maxY_ = Infinity;
this.minX_ = -Infinity;
this.minY_ = -Infinity;
this.targetSize_ = options.targetSize !== void 0 ? options.targetSize : 100;
this.maxLines_ = options.maxLines !== void 0 ? options.maxLines : 100;
this.meridians_ = [];
this.parallels_ = [];
this.strokeStyle_ = options.strokeStyle !== void 0 ? options.strokeStyle : DEFAULT_STROKE_STYLE;
this.fromLonLatTransform_ = void 0;
this.toLonLatTransform_ = void 0;
this.projectionCenterLonLat_ = null;
this.bottomLeft_ = null;
this.bottomRight_ = null;
this.topLeft_ = null;
this.topRight_ = null;
this.meridiansLabels_ = null;
this.parallelsLabels_ = null;
if (options.showLabels) {
this.lonLabelFormatter_ = options.lonLabelFormatter == void 0 ? degreesToStringHDMS.bind(this, "EW") : options.lonLabelFormatter;
this.latLabelFormatter_ = options.latLabelFormatter == void 0 ? degreesToStringHDMS.bind(this, "NS") : options.latLabelFormatter;
this.lonLabelPosition_ = options.lonLabelPosition == void 0 ? 0 : options.lonLabelPosition;
this.latLabelPosition_ = options.latLabelPosition == void 0 ? 1 : options.latLabelPosition;
this.lonLabelStyleBase_ = new Style_default({
text: options.lonLabelStyle !== void 0 ? options.lonLabelStyle.clone() : new Text_default({
font: "12px Calibri,sans-serif",
textBaseline: "bottom",
fill: new Fill_default({
color: "rgba(0,0,0,1)"
}),
stroke: new Stroke_default({
color: "rgba(255,255,255,1)",
width: 3
})
})
});
this.lonLabelStyle_ = (feature) => {
const label = feature.get("graticule_label");
this.lonLabelStyleBase_.getText().setText(label);
return this.lonLabelStyleBase_;
};
this.latLabelStyleBase_ = new Style_default({
text: options.latLabelStyle !== void 0 ? options.latLabelStyle.clone() : new Text_default({
font: "12px Calibri,sans-serif",
textAlign: "right",
fill: new Fill_default({
color: "rgba(0,0,0,1)"
}),
stroke: new Stroke_default({
color: "rgba(255,255,255,1)",
width: 3
})
})
});
this.latLabelStyle_ = (feature) => {
const label = feature.get("graticule_label");
this.latLabelStyleBase_.getText().setText(label);
return this.latLabelStyleBase_;
};
this.meridiansLabels_ = [];
this.parallelsLabels_ = [];
this.addEventListener(EventType_default2.POSTRENDER, this.drawLabels_.bind(this));
}
this.intervals_ = options.intervals !== void 0 ? options.intervals : INTERVALS;
this.setSource(
new Vector_default2({
loader: this.loaderFunction.bind(this),
strategy: this.strategyFunction.bind(this),
features: new Collection_default(),
overlaps: false,
useSpatialIndex: false,
wrapX: options.wrapX
})
);
this.featurePool_ = [];
this.lineStyle_ = new Style_default({
stroke: this.strokeStyle_
});
this.loadedExtent_ = null;
this.renderedExtent_ = null;
this.renderedResolution_ = null;
this.setRenderOrder(null);
}
/**
* Strategy function for loading features based on the view's extent and
* resolution.
* @param {import("../extent.js").Extent} extent Extent.
* @param {number} resolution Resolution.
* @return {Array<import("../extent.js").Extent>} Extents.
*/
strategyFunction(extent, resolution) {
let realWorldExtent = extent.slice();
if (this.projection_ && this.getSource().getWrapX()) {
wrapX(realWorldExtent, this.projection_);
}
if (this.loadedExtent_) {
if (approximatelyEquals(this.loadedExtent_, realWorldExtent, resolution)) {
realWorldExtent = this.loadedExtent_.slice();
} else {
this.getSource().removeLoadedExtent(this.loadedExtent_);
}
}
return [realWorldExtent];
}
/**
* Update geometries in the source based on current view
* @param {import("../extent").Extent} extent Extent
* @param {number} resolution Resolution
* @param {import("../proj/Projection.js").default} projection Projection
*/
loaderFunction(extent, resolution, projection) {
this.loadedExtent_ = extent;
const source = this.getSource();
const layerExtent = this.getExtent() || [
-Infinity,
-Infinity,
Infinity,
Infinity
];
const renderExtent = getIntersection(layerExtent, extent);
if (this.renderedExtent_ && equals(this.renderedExtent_, renderExtent) && this.renderedResolution_ === resolution) {
return;
}
this.renderedExtent_ = renderExtent;
this.renderedResolution_ = resolution;
if (isEmpty(renderExtent)) {
return;
}
const center = getCenter(renderExtent);
const squaredTolerance = resolution * resolution / 4;
const updateProjectionInfo = !this.projection_ || !equivalent(this.projection_, projection);
if (updateProjectionInfo) {
this.updateProjectionInfo_(projection);
}
this.createGraticule_(renderExtent, center, resolution, squaredTolerance);
let featureCount = this.meridians_.length + this.parallels_.length;
if (this.meridiansLabels_) {
featureCount += this.meridians_.length;
}
if (this.parallelsLabels_) {
featureCount += this.parallels_.length;
}
let feature;
while (featureCount > this.featurePool_.length) {
feature = new Feature_default();
this.featurePool_.push(feature);
}
const featuresColl = source.getFeaturesCollection();
featuresColl.clear();
let poolIndex = 0;
let i, l;
for (i = 0, l = this.meridians_.length; i < l; ++i) {
feature = this.featurePool_[poolIndex++];
feature.setGeometry(this.meridians_[i]);
feature.setStyle(this.lineStyle_);
featuresColl.push(feature);
}
for (i = 0, l = this.parallels_.length; i < l; ++i) {
feature = this.featurePool_[poolIndex++];
feature.setGeometry(this.parallels_[i]);
feature.setStyle(this.lineStyle_);
featuresColl.push(feature);
}
}
/**
* @param {number} lon Longitude.
* @param {number} minLat Minimal latitude.
* @param {number} maxLat Maximal latitude.
* @param {number} squaredTolerance Squared tolerance.
* @param {import("../extent.js").Extent} extent Extent.
* @param {number} index Index.
* @return {number} Index.
* @private
*/
addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, index) {
const lineString = this.getMeridian_(
lon,
minLat,
maxLat,
squaredTolerance,
index
);
if (intersects(lineString.getExtent(), extent)) {
if (this.meridiansLabels_) {
const text = this.lonLabelFormatter_(lon);
if (index in this.meridiansLabels_) {
this.meridiansLabels_[index].text = text;
} else {
this.meridiansLabels_[index] = {
geom: new Point_default([]),
text
};
}
}
this.meridians_[index++] = lineString;
}
return index;
}
/**
* @param {number} lat Latitude.
* @param {number} minLon Minimal longitude.
* @param {number} maxLon Maximal longitude.
* @param {number} squaredTolerance Squared tolerance.
* @param {import("../extent.js").Extent} extent Extent.
* @param {number} index Index.
* @return {number} Index.
* @private
*/
addParallel_(lat, minLon, maxLon, squaredTolerance, extent, index) {
const lineString = this.getParallel_(
lat,
minLon,
maxLon,
squaredTolerance,
index
);
if (intersects(lineString.getExtent(), extent)) {
if (this.parallelsLabels_) {
const text = this.latLabelFormatter_(lat);
if (index in this.parallelsLabels_) {
this.parallelsLabels_[index].text = text;
} else {
this.parallelsLabels_[index] = {
geom: new Point_default([]),
text
};
}
}
this.parallels_[index++] = lineString;
}
return index;
}
/**
* @param {import("../render/Event.js").default} event Render event.
* @private
*/
drawLabels_(event) {
const rotation = event.frameState.viewState.rotation;
const resolution = event.frameState.viewState.resolution;
const size = event.frameState.size;
const extent = event.frameState.extent;
const rotationCenter = getCenter(extent);
let rotationExtent = extent;
if (rotation) {
const unrotatedWidth = size[0] * resolution;
const unrotatedHeight = size[1] * resolution;
rotationExtent = [
rotationCenter[0] - unrotatedWidth / 2,
rotationCenter[1] - unrotatedHeight / 2,
rotationCenter[0] + unrotatedWidth / 2,
rotationCenter[1] + unrotatedHeight / 2
];
}
let startWorld = 0;
let endWorld = 0;
let labelsAtStart = this.latLabelPosition_ < 0.5;
const projectionExtent = this.projection_.getExtent();
const worldWidth = getWidth(projectionExtent);
if (this.getSource().getWrapX() && this.projection_.canWrapX() && !containsExtent(projectionExtent, extent)) {
startWorld = Math.floor((extent[0] - projectionExtent[0]) / worldWidth);
endWorld = Math.ceil((extent[2] - projectionExtent[2]) / worldWidth);
const inverted = Math.abs(rotation) > Math.PI / 2;
labelsAtStart = labelsAtStart !== inverted;
}
const vectorContext = getVectorContext(event);
for (let world = startWorld; world <= endWorld; ++world) {
let poolIndex = this.meridians_.length + this.parallels_.length;
let feature, index, l, textPoint;
if (this.meridiansLabels_) {
for (index = 0, l = this.meridiansLabels_.length; index < l; ++index) {
const lineString = this.meridians_[index];
if (!rotation && world === 0) {
textPoint = this.getMeridianPoint_(lineString, extent, index);
} else {
const clone = lineString.clone();
clone.translate(world * worldWidth, 0);
clone.rotate(-rotation, rotationCenter);
textPoint = this.getMeridianPoint_(clone, rotationExtent, index);
textPoint.rotate(rotation, rotationCenter);
}
feature = this.featurePool_[poolIndex++];
feature.setGeometry(textPoint);
feature.set("graticule_label", this.meridiansLabels_[index].text);
vectorContext.drawFeature(feature, this.lonLabelStyle_(feature));
}
}
if (this.parallelsLabels_) {
if (world === startWorld && labelsAtStart || world === endWorld && !labelsAtStart) {
for (index = 0, l = this.parallels_.length; index < l; ++index) {
const lineString = this.parallels_[index];
if (!rotation && world === 0) {
textPoint = this.getParallelPoint_(lineString, extent, index);
} else {
const clone = lineString.clone();
clone.translate(world * worldWidth, 0);
clone.rotate(-rotation, rotationCenter);
textPoint = this.getParallelPoint_(clone, rotationExtent, index);
textPoint.rotate(rotation, rotationCenter);
}
feature = this.featurePool_[poolIndex++];
feature.setGeometry(textPoint);
feature.set("graticule_label", this.parallelsLabels_[index].text);
vectorContext.drawFeature(feature, this.latLabelStyle_(feature));
}
}
}
}
}
/**
* @param {import("../extent.js").Extent} extent Extent.
* @param {import("../coordinate.js").Coordinate} center Center.
* @param {number} resolution Resolution.
* @param {number} squaredTolerance Squared tolerance.
* @private
*/
createGraticule_(extent, center, resolution, squaredTolerance) {
const interval = this.getInterval_(resolution);
if (interval == -1) {
this.meridians_.length = 0;
this.parallels_.length = 0;
if (this.meridiansLabels_) {
this.meridiansLabels_.length = 0;
}
if (this.parallelsLabels_) {
this.parallelsLabels_.length = 0;
}
return;
}
let wrapX2 = false;
const projectionExtent = this.projection_.getExtent();
const worldWidth = getWidth(projectionExtent);
if (this.getSource().getWrapX() && this.projection_.canWrapX() && !containsExtent(projectionExtent, extent)) {
if (getWidth(extent) >= worldWidth) {
extent[0] = projectionExtent[0];
extent[2] = projectionExtent[2];
} else {
wrapX2 = true;
}
}
const validCenterP = [
clamp(center[0], this.minX_, this.maxX_),
clamp(center[1], this.minY_, this.maxY_)
];
const centerLonLat = this.toLonLatTransform_(validCenterP);
if (isNaN(centerLonLat[1])) {
centerLonLat[1] = Math.abs(this.maxLat_) >= Math.abs(this.minLat_) ? this.maxLat_ : this.minLat_;
}
let centerLon = clamp(centerLonLat[0], this.minLon_, this.maxLon_);
let centerLat = clamp(centerLonLat[1], this.minLat_, this.maxLat_);
const maxLines = this.maxLines_;
let cnt, idx, lat, lon;
let validExtentP = extent;
if (!wrapX2) {
validExtentP = [
clamp(extent[0], this.minX_, this.maxX_),
clamp(extent[1], this.minY_, this.maxY_),
clamp(extent[2], this.minX_, this.maxX_),
clamp(extent[3], this.minY_, this.maxY_)
];
}
const validExtent = applyTransform(
validExtentP,
this.toLonLatTransform_,
void 0,
8
);
let maxLat = validExtent[3];
let maxLon = validExtent[2];
let minLat = validExtent[1];
let minLon = validExtent[0];
if (!wrapX2) {
if (containsCoordinate(validExtentP, this.bottomLeft_)) {
minLon = this.minLon_;
minLat = this.minLat_;
}
if (containsCoordinate(validExtentP, this.bottomRight_)) {
maxLon = this.maxLon_;
minLat = this.minLat_;
}
if (containsCoordinate(validExtentP, this.topLeft_)) {
minLon = this.minLon_;
maxLat = this.maxLat_;
}
if (containsCoordinate(validExtentP, this.topRight_)) {
maxLon = this.maxLon_;
maxLat = this.maxLat_;
}
maxLat = clamp(maxLat, centerLat, this.maxLat_);
maxLon = clamp(maxLon, centerLon, this.maxLon_);
minLat = clamp(minLat, this.minLat_, centerLat);
minLon = clamp(minLon, this.minLon_, centerLon);
}
centerLon = Math.floor(centerLon / interval) * interval;
lon = clamp(centerLon, this.minLon_, this.maxLon_);
idx = this.addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, 0);
cnt = 0;
if (wrapX2) {
while ((lon -= interval) >= minLon && cnt++ < maxLines) {
idx = this.addMeridian_(
lon,
minLat,
maxLat,
squaredTolerance,
extent,
idx
);
}
} else {
while (lon != this.minLon_ && cnt++ < maxLines) {
lon = Math.max(lon - interval, this.minLon_);
idx = this.addMeridian_(
lon,
minLat,
maxLat,
squaredTolerance,
extent,
idx
);
}
}
lon = clamp(centerLon, this.minLon_, this.maxLon_);
cnt = 0;
if (wrapX2) {
while ((lon += interval) <= maxLon && cnt++ < maxLines) {
idx = this.addMeridian_(
lon,
minLat,
maxLat,
squaredTolerance,
extent,
idx
);
}
} else {
while (lon != this.maxLon_ && cnt++ < maxLines) {
lon = Math.min(lon + interval, this.maxLon_);
idx = this.addMeridian_(
lon,
minLat,
maxLat,
squaredTolerance,
extent,
idx
);
}
}
this.meridians_.length = idx;
if (this.meridiansLabels_) {
this.meridiansLabels_.length = idx;
}
centerLat = Math.floor(centerLat / interval) * interval;
lat = clamp(centerLat, this.minLat_, this.maxLat_);
idx = this.addParallel_(lat, minLon, maxLon, squaredTolerance, extent, 0);
cnt = 0;
while (lat != this.minLat_ && cnt++ < maxLines) {
lat = Math.max(lat - interval, this.minLat_);
idx = this.addParallel_(
lat,
minLon,
maxLon,
squaredTolerance,
extent,
idx
);
}
lat = clamp(centerLat, this.minLat_, this.maxLat_);
cnt = 0;
while (lat != this.maxLat_ && cnt++ < maxLines) {
lat = Math.min(lat + interval, this.maxLat_);
idx = this.addParallel_(
lat,
minLon,
maxLon,
squaredTolerance,
extent,
idx
);
}
this.parallels_.length = idx;
if (this.parallelsLabels_) {
this.parallelsLabels_.length = idx;
}
}
/**
* @param {number} resolution Resolution.
* @return {number} The interval in degrees.
* @private
*/
getInterval_(resolution) {
const centerLon = this.projectionCenterLonLat_[0];
const centerLat = this.projectionCenterLonLat_[1];
let interval = -1;
const target = Math.pow(this.targetSize_ * resolution, 2);
const p1 = [];
const p2 = [];
for (let i = 0, ii = this.intervals_.length; i < ii; ++i) {
const delta = clamp(this.intervals_[i] / 2, 0, 90);
const clampedLat = clamp(centerLat, -90 + delta, 90 - delta);
p1[0] = centerLon - delta;
p1[1] = clampedLat - delta;
p2[0] = centerLon + delta;
p2[1] = clampedLat + delta;
this.fromLonLatTransform_(p1, p1);
this.fromLonLatTransform_(p2, p2);
const dist = Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2);
if (dist <= target) {
break;
}
interval = this.intervals_[i];
}
return interval;
}
/**
* @param {number} lon Longitude.
* @param {number} minLat Minimal latitude.
* @param {number} maxLat Maximal latitude.
* @param {number} squaredTolerance Squared tolerance.
* @return {LineString} The meridian line string.
* @param {number} index Index.
* @private
*/
getMeridian_(lon, minLat, maxLat, squaredTolerance, index) {
const flatCoordinates = meridian(
lon,
minLat,
maxLat,
this.projection_,
squaredTolerance
);
let lineString = this.meridians_[index];
if (!lineString) {
lineString = new LineString_default(flatCoordinates, "XY");
this.meridians_[index] = lineString;
} else {
lineString.setFlatCoordinates("XY", flatCoordinates);
lineString.changed();
}
return lineString;
}
/**
* @param {LineString} lineString Meridian
* @param {import("../extent.js").Extent} extent Extent.
* @param {number} index Index.
* @return {Point} Meridian point.
* @private
*/
getMeridianPoint_(lineString, extent, index) {
const flatCoordinates = lineString.getFlatCoordinates();
let bottom = 1;
let top = flatCoordinates.length - 1;
if (flatCoordinates[bottom] > flatCoordinates[top]) {
bottom = top;
top = 1;
}
const clampedBottom = Math.max(extent[1], flatCoordinates[bottom]);
const clampedTop = Math.min(extent[3], flatCoordinates[top]);
const lat = clamp(
extent[1] + Math.abs(extent[1] - extent[3]) * this.lonLabelPosition_,
clampedBottom,
clampedTop
);
const coordinate0 = flatCoordinates[bottom - 1] + (flatCoordinates[top - 1] - flatCoordinates[bottom - 1]) * (lat - flatCoordinates[bottom]) / (flatCoordinates[top] - flatCoordinates[bottom]);
const coordinate = [coordinate0, lat];
const point = this.meridiansLabels_[index].geom;
point.setCoordinates(coordinate);
return point;
}
/**
* Get the list of meridians. Meridians are lines of equal longitude.
* @return {Array<LineString>} The meridians.
* @api
*/
getMeridians() {
return this.meridians_;
}
/**
* @param {number} lat Latitude.
* @param {number} minLon Minimal longitude.
* @param {number} maxLon Maximal longitude.
* @param {number} squaredTolerance Squared tolerance.
* @return {LineString} The parallel line string.
* @param {number} index Index.
* @private
*/
getParallel_(lat, minLon, maxLon, squaredTolerance, index) {
const flatCoordinates = parallel(
lat,
minLon,
maxLon,
this.projection_,
squaredTolerance
);
let lineString = this.parallels_[index];
if (!lineString) {
lineString = new LineString_default(flatCoordinates, "XY");
} else {
lineString.setFlatCoordinates("XY", flatCoordinates);
lineString.changed();
}
return lineString;
}
/**
* @param {LineString} lineString Parallels.
* @param {import("../extent.js").Extent} extent Extent.
* @param {number} index Index.
* @return {Point} Parallel point.
* @private
*/
getParallelPoint_(lineString, extent, index) {
const flatCoordinates = lineString.getFlatCoordinates();
let left = 0;
let right = flatCoordinates.length - 2;
if (flatCoordinates[left] > flatCoordinates[right]) {
left = right;
right = 0;
}
const clampedLeft = Math.max(extent[0], flatCoordinates[left]);
const clampedRight = Math.min(extent[2], flatCoordinates[right]);
const lon = clamp(
extent[0] + Math.abs(extent[0] - extent[2]) * this.latLabelPosition_,
clampedLeft,
clampedRight
);
const coordinate1 = flatCoordinates[left + 1] + (flatCoordinates[right + 1] - flatCoordinates[left + 1]) * (lon - flatCoordinates[left]) / (flatCoordinates[right] - flatCoordinates[left]);
const coordinate = [lon, coordinate1];
const point = this.parallelsLabels_[index].geom;
point.setCoordinates(coordinate);
return point;
}
/**
* Get the list of parallels. Parallels are lines of equal latitude.
* @return {Array<LineString>} The parallels.
* @api
*/
getParallels() {
return this.parallels_;
}
/**
* @param {import("../proj/Projection.js").default} projection Projection.
* @private
*/
updateProjectionInfo_(projection) {
const epsg4326Projection = get("EPSG:4326");
const worldExtent = projection.getWorldExtent();
this.maxLat_ = worldExtent[3];
this.maxLon_ = worldExtent[2];
this.minLat_ = worldExtent[1];
this.minLon_ = worldExtent[0];
const toLonLatTransform = getTransform(projection, epsg4326Projection);
if (this.minLon_ < this.maxLon_) {
this.toLonLatTransform_ = toLonLatTransform;
} else {
const split = this.minLon_ + this.maxLon_ / 2;
this.maxLon_ += 360;
this.toLonLatTransform_ = function(coordinates, output, dimension) {
dimension = dimension || 2;
const lonLatCoordinates = toLonLatTransform(
coordinates,
output,
dimension
);
for (let i = 0, l = lonLatCoordinates.length; i < l; i += dimension) {
if (lonLatCoordinates[i] < split) {
lonLatCoordinates[i] += 360;
}
}
return lonLatCoordinates;
};
}
this.fromLonLatTransform_ = getTransform(epsg4326Projection, projection);
const worldExtentP = applyTransform(
[this.minLon_, this.minLat_, this.maxLon_, this.maxLat_],
this.fromLonLatTransform_,
void 0,
8
);
this.minX_ = worldExtentP[0];
this.maxX_ = worldExtentP[2];
this.minY_ = worldExtentP[1];
this.maxY_ = worldExtentP[3];
this.bottomLeft_ = this.fromLonLatTransform_([this.minLon_, this.minLat_]);
this.bottomRight_ = this.fromLonLatTransform_([this.maxLon_, this.minLat_]);
this.topLeft_ = this.fromLonLatTransform_([this.minLon_, this.maxLat_]);
this.topRight_ = this.fromLonLatTransform_([this.maxLon_, this.maxLat_]);
this.projectionCenterLonLat_ = this.toLonLatTransform_(
getCenter(projection.getExtent())
);
if (isNaN(this.projectionCenterLonLat_[1])) {
this.projectionCenterLonLat_[1] = Math.abs(this.maxLat_) >= Math.abs(this.minLat_) ? this.maxLat_ : this.minLat_;
}
this.projection_ = projection;
}
};
var Graticule_default = Graticule;
// node_modules/ol/renderer/canvas/VectorImageLayer.js
var CanvasVectorImageLayerRenderer = class extends ImageLayer_default {
/**
* @param {import("../../layer/VectorImage.js").default} layer Vector image layer.
*/
constructor(layer) {
super(layer);
this.vectorRenderer_ = new VectorLayer_default(layer);
this.layerImageRatio_ = layer.getImageRatio();
this.coordinateToVectorPixelTransform_ = create();
this.renderedPixelToCoordinateTransform_ = null;
}
/**
* Clean up.
* @override
*/
disposeInternal() {
this.vectorRenderer_.dispose();
super.disposeInternal();
}
/**
* Asynchronous layer level hit detection.
* @param {import("../../pixel.js").Pixel} pixel Pixel.
* @return {Promise<Array<import("../../Feature").default>>} Promise that resolves with an array of features.
* @override
*/
getFeatures(pixel) {
if (!this.vectorRenderer_) {
return Promise.resolve([]);
}
const vectorPixel = apply(
this.coordinateToVectorPixelTransform_,
apply(this.renderedPixelToCoordinateTransform_, pixel.slice())
);
return this.vectorRenderer_.getFeatures(vectorPixel);
}
/**
* Perform action necessary to get the layer rendered after new fonts have loaded
* @override
*/
handleFontsChanged() {
this.vectorRenderer_.handleFontsChanged();
}
/**
* Determine whether render should be called.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @return {boolean} Layer is ready to be rendered.
* @override
*/
prepareFrame(frameState) {
var _a;
const pixelRatio = frameState.pixelRatio;
const viewState = frameState.viewState;
const viewResolution = viewState.resolution;
const hints = frameState.viewHints;
const vectorRenderer = this.vectorRenderer_;
let renderedExtent = frameState.extent;
if (this.layerImageRatio_ !== 1) {
renderedExtent = renderedExtent.slice(0);
scaleFromCenter(renderedExtent, this.layerImageRatio_);
}
const width = getWidth(renderedExtent) / viewResolution;
const height = getHeight(renderedExtent) / viewResolution;
if (!hints[ViewHint_default.ANIMATING] && !hints[ViewHint_default.INTERACTING] && !isEmpty(renderedExtent)) {
vectorRenderer.useContainer(null, null);
const context = vectorRenderer.context;
const layerState = frameState.layerStatesArray[frameState.layerIndex];
const imageLayerState = Object.assign({}, layerState, { opacity: 1 });
const imageFrameState = (
/** @type {import("../../Map.js").FrameState} */
Object.assign({}, frameState, {
extent: renderedExtent,
size: [width, height],
viewState: (
/** @type {import("../../View.js").State} */
Object.assign({}, frameState.viewState, {
rotation: 0
})
),
layerStatesArray: [imageLayerState],
layerIndex: 0,
declutter: null
})
);
const declutter = this.getLayer().getDeclutter();
if (declutter) {
imageFrameState.declutter = {
[declutter]: new RBush(9)
};
}
const image = new ImageCanvas_default(
renderedExtent,
viewResolution,
pixelRatio,
context.canvas,
function(callback) {
if (vectorRenderer.prepareFrame(imageFrameState) && vectorRenderer.replayGroupChanged) {
vectorRenderer.clipping = false;
vectorRenderer.renderFrame(imageFrameState, null);
vectorRenderer.renderDeclutter(imageFrameState);
vectorRenderer.renderDeferred(imageFrameState);
callback();
}
}
);
image.addEventListener(EventType_default.CHANGE, () => {
if (image.getState() !== ImageState_default.LOADED) {
return;
}
this.image = image;
const imagePixelRatio = image.getPixelRatio();
const renderedResolution = fromResolutionLike(image.getResolution()) * pixelRatio / imagePixelRatio;
this.renderedResolution = renderedResolution;
this.coordinateToVectorPixelTransform_ = compose(
this.coordinateToVectorPixelTransform_,
width / 2,
height / 2,
1 / renderedResolution,
-1 / renderedResolution,
0,
-viewState.center[0],
-viewState.center[1]
);
});
image.load();
}
if (this.image) {
this.renderedPixelToCoordinateTransform_ = frameState.pixelToCoordinateTransform.slice();
}
return !((_a = this.getLayer().getSource()) == null ? void 0 : _a.loading) && !!this.image;
}
/**
* @override
*/
preRender() {
}
/**
* @override
*/
postRender() {
}
/**
*/
renderDeclutter() {
}
/**
* @param {import("../../coordinate.js").Coordinate} coordinate Coordinate.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @param {number} hitTolerance Hit tolerance in pixels.
* @param {import("../vector.js").FeatureCallback<T>} callback Feature callback.
* @param {Array<import("../Map.js").HitMatch<T>>} matches The hit detected matches with tolerance.
* @return {T|undefined} Callback result.
* @template T
* @override
*/
forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, matches) {
if (this.vectorRenderer_) {
return this.vectorRenderer_.forEachFeatureAtCoordinate(
coordinate,
frameState,
hitTolerance,
callback,
matches
);
}
return super.forEachFeatureAtCoordinate(
coordinate,
frameState,
hitTolerance,
callback,
matches
);
}
};
var VectorImageLayer_default = CanvasVectorImageLayerRenderer;
// node_modules/ol/layer/VectorImage.js
var VectorImageLayer = class extends BaseVector_default {
/**
* @param {Options<VectorSourceType, FeatureType>} [options] Options.
*/
constructor(options) {
options = options ? options : {};
const baseOptions = Object.assign({}, options);
delete baseOptions.imageRatio;
super(baseOptions);
this.imageRatio_ = options.imageRatio !== void 0 ? options.imageRatio : 1;
}
/**
* @return {number} Ratio between rendered extent size and viewport extent size.
*/
getImageRatio() {
return this.imageRatio_;
}
/**
* @override
*/
createRenderer() {
return new VectorImageLayer_default(this);
}
};
var VectorImage_default = VectorImageLayer;
// node_modules/ol/renderer/webgl/PointsLayer.js
var WebGLPointsLayerRenderer = class extends Layer_default2 {
/**
* @param {import("../../layer/Layer.js").default} layer Layer.
* @param {Options} options Options.
*/
constructor(layer, options) {
const uniforms = options.uniforms || {};
const projectionMatrixTransform = create();
uniforms[DefaultUniform.PROJECTION_MATRIX] = projectionMatrixTransform;
super(layer, {
uniforms,
postProcesses: options.postProcesses
});
this.sourceRevision_ = -1;
this.verticesBuffer_ = new Buffer_default(ARRAY_BUFFER, DYNAMIC_DRAW);
this.instanceAttributesBuffer_ = new Buffer_default(
ARRAY_BUFFER,
DYNAMIC_DRAW
);
this.indicesBuffer_ = new Buffer_default(
ELEMENT_ARRAY_BUFFER,
DYNAMIC_DRAW
);
this.vertexShader_ = options.vertexShader;
this.fragmentShader_ = options.fragmentShader;
this.program_;
this.hitDetectionEnabled_ = options.hitDetectionEnabled ?? true;
const customAttributes = options.attributes ? options.attributes.map(function(attribute) {
return {
name: "a_" + attribute.name,
size: 1,
type: AttributeType.FLOAT
};
}) : [];
this.attributes = [
{
name: "a_localPosition",
size: 2,
type: AttributeType.FLOAT
}
];
this.instanceAttributes = [
{
name: "a_position",
size: 2,
type: AttributeType.FLOAT
}
];
if (this.hitDetectionEnabled_) {
this.instanceAttributes.push({
name: "a_hitColor",
size: 2,
type: AttributeType.FLOAT
});
this.instanceAttributes.push({
name: "a_featureUid",
size: 1,
type: AttributeType.FLOAT
});
}
this.instanceAttributes.push(...customAttributes);
this.customAttributes = options.attributes ? options.attributes : [];
this.previousExtent_ = createEmpty();
this.currentTransform_ = projectionMatrixTransform;
this.renderTransform_ = create();
this.invertRenderTransform_ = create();
this.renderInstructions_ = new Float32Array(0);
this.hitRenderTarget_;
this.lastSentId = 0;
this.worker_ = create2();
this.worker_.addEventListener(
"message",
/**
* @param {*} event Event.
*/
(event) => {
const received = event.data;
if (received.type === WebGLWorkerMessageType.GENERATE_POINT_BUFFERS) {
const projectionTransform = received.projectionTransform;
this.verticesBuffer_.fromArrayBuffer(received.vertexAttributesBuffer);
this.instanceAttributesBuffer_.fromArrayBuffer(
received.instanceAttributesBuffer
);
this.helper.flushBufferData(this.verticesBuffer_);
this.helper.flushBufferData(this.instanceAttributesBuffer_);
this.indicesBuffer_.fromArrayBuffer(received.indicesBuffer);
this.helper.flushBufferData(this.indicesBuffer_);
this.renderTransform_ = projectionTransform;
makeInverse(
this.invertRenderTransform_,
this.renderTransform_
);
this.renderInstructions_ = new Float32Array(
event.data.renderInstructions
);
if (received.id === this.lastSentId) {
this.ready = true;
}
this.getLayer().changed();
}
}
);
this.featureCache_ = {};
this.featureCount_ = 0;
const source = (
/** @type {import("../../source/Vector.js").default} */
this.getLayer().getSource()
);
this.sourceListenKeys_ = [
listen(
source,
VectorEventType_default.ADDFEATURE,
this.handleSourceFeatureAdded_,
this
),
listen(
source,
VectorEventType_default.CHANGEFEATURE,
this.handleSourceFeatureChanged_,
this
),
listen(
source,
VectorEventType_default.REMOVEFEATURE,
this.handleSourceFeatureDelete_,
this
),
listen(
source,
VectorEventType_default.CLEAR,
this.handleSourceFeatureClear_,
this
)
];
source.forEachFeature((feature) => {
const geometry = feature.getGeometry();
if (geometry && geometry.getType() === "Point") {
this.featureCache_[getUid(feature)] = {
feature: (
/** @type {PointFeature} */
feature
),
properties: feature.getProperties(),
flatCoordinates: (
/** @type {Point} */
geometry.getFlatCoordinates()
)
};
this.featureCount_++;
}
});
}
/**
* @override
*/
afterHelperCreated() {
this.program_ = this.helper.getProgram(
this.fragmentShader_,
this.vertexShader_
);
if (this.hitDetectionEnabled_) {
this.hitRenderTarget_ = new RenderTarget_default(this.helper);
}
if (this.verticesBuffer_.getArray()) {
this.helper.flushBufferData(this.verticesBuffer_);
}
if (this.indicesBuffer_.getArray()) {
this.helper.flushBufferData(this.indicesBuffer_);
}
}
/**
* @param {import("../../source/Vector.js").VectorSourceEvent} event Event.
* @private
*/
handleSourceFeatureAdded_(event) {
const feature = event.feature;
const geometry = feature.getGeometry();
if (geometry && geometry.getType() === "Point") {
this.featureCache_[getUid(feature)] = {
feature: (
/** @type {PointFeature} */
feature
),
properties: feature.getProperties(),
flatCoordinates: (
/** @type {Point} */
geometry.getFlatCoordinates()
)
};
this.featureCount_++;
}
}
/**
* @param {import("../../source/Vector.js").VectorSourceEvent} event Event.
* @private
*/
handleSourceFeatureChanged_(event) {
const feature = event.feature;
const featureUid = getUid(feature);
const item = this.featureCache_[featureUid];
const geometry = feature.getGeometry();
if (item) {
if (geometry && geometry.getType() === "Point") {
item.properties = feature.getProperties();
item.flatCoordinates = /** @type {Point} */
geometry.getFlatCoordinates();
} else {
delete this.featureCache_[featureUid];
this.featureCount_--;
}
} else {
if (geometry && geometry.getType() === "Point") {
this.featureCache_[featureUid] = {
feature: (
/** @type {PointFeature} */
feature
),
properties: feature.getProperties(),
flatCoordinates: (
/** @type {Point} */
geometry.getFlatCoordinates()
)
};
this.featureCount_++;
}
}
}
/**
* @param {import("../../source/Vector.js").VectorSourceEvent} event Event.
* @private
*/
handleSourceFeatureDelete_(event) {
const feature = event.feature;
const featureUid = getUid(feature);
if (featureUid in this.featureCache_) {
delete this.featureCache_[featureUid];
this.featureCount_--;
}
}
/**
* @private
*/
handleSourceFeatureClear_() {
this.featureCache_ = {};
this.featureCount_ = 0;
}
/**
* Render the layer.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @return {HTMLElement} The rendered element.
* @override
*/
renderFrame(frameState) {
const gl = this.helper.getGL();
this.preRender(gl, frameState);
const [startWorld, endWorld, worldWidth] = getWorldParameters(
frameState,
this.getLayer()
);
this.renderWorlds(frameState, false, startWorld, endWorld, worldWidth);
this.helper.finalizeDraw(
frameState,
this.dispatchPreComposeEvent,
this.dispatchPostComposeEvent
);
if (this.hitDetectionEnabled_) {
this.renderWorlds(frameState, true, startWorld, endWorld, worldWidth);
this.hitRenderTarget_.clearCachedData();
}
this.postRender(gl, frameState);
const canvas = this.helper.getCanvas();
return canvas;
}
/**
* Determine whether renderFrame should be called.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @return {boolean} Layer is ready to be rendered.
* @override
*/
prepareFrameInternal(frameState) {
const layer = this.getLayer();
const vectorSource = layer.getSource();
const viewState = frameState.viewState;
const viewNotMoving = !frameState.viewHints[ViewHint_default.ANIMATING] && !frameState.viewHints[ViewHint_default.INTERACTING];
const extentChanged = !equals(this.previousExtent_, frameState.extent);
const sourceChanged = this.sourceRevision_ < vectorSource.getRevision();
if (sourceChanged) {
this.sourceRevision_ = vectorSource.getRevision();
}
if (viewNotMoving && (extentChanged || sourceChanged)) {
const projection = viewState.projection;
const resolution = viewState.resolution;
const renderBuffer = layer instanceof BaseVector_default ? layer.getRenderBuffer() : 0;
const extent = buffer(frameState.extent, renderBuffer * resolution);
vectorSource.loadFeatures(extent, resolution, projection);
this.rebuildBuffers_(frameState);
this.previousExtent_ = frameState.extent.slice();
}
this.helper.useProgram(this.program_, frameState);
this.helper.prepareDraw(frameState);
return true;
}
/**
* Rebuild internal webgl buffers based on current view extent; costly, should not be called too much
* @param {import("../../Map").FrameState} frameState Frame state.
* @private
*/
rebuildBuffers_(frameState) {
const projectionTransform = create();
this.helper.makeProjectionTransform(frameState, projectionTransform);
const userProjection = getUserProjection();
const baseInstructionLength = this.hitDetectionEnabled_ ? 5 : 2;
const singleInstructionLength = baseInstructionLength + this.customAttributes.length;
const totalSize = singleInstructionLength * this.featureCount_;
const renderInstructions = this.renderInstructions_ && this.renderInstructions_.length === totalSize ? this.renderInstructions_ : new Float32Array(totalSize);
this.renderInstructions_ = null;
let tmpCoords = [];
const tmpColor = [];
let idx = -1;
const projection = frameState.viewState.projection;
for (const featureUid in this.featureCache_) {
const featureCache = this.featureCache_[featureUid];
if (userProjection) {
tmpCoords = fromUserCoordinate(
featureCache.flatCoordinates,
projection
);
} else {
tmpCoords[0] = featureCache.flatCoordinates[0];
tmpCoords[1] = featureCache.flatCoordinates[1];
}
apply(projectionTransform, tmpCoords);
renderInstructions[++idx] = tmpCoords[0];
renderInstructions[++idx] = tmpCoords[1];
if (this.hitDetectionEnabled_) {
const hitColor = colorEncodeIdAndPack(idx + 3, tmpColor);
renderInstructions[++idx] = hitColor[0];
renderInstructions[++idx] = hitColor[1];
renderInstructions[++idx] = Number(featureUid);
}
for (let j = 0; j < this.customAttributes.length; j++) {
const value = this.customAttributes[j].callback(
featureCache.feature,
featureCache.properties
);
renderInstructions[++idx] = value;
}
}
const message = {
id: ++this.lastSentId,
type: WebGLWorkerMessageType.GENERATE_POINT_BUFFERS,
renderInstructions: renderInstructions.buffer,
customAttributesSize: singleInstructionLength - 2
};
message["projectionTransform"] = projectionTransform;
this.ready = false;
this.worker_.postMessage(message, [renderInstructions.buffer]);
}
/**
* @param {import("../../coordinate.js").Coordinate} coordinate Coordinate.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @param {number} hitTolerance Hit tolerance in pixels.
* @param {import("../vector.js").FeatureCallback<T>} callback Feature callback.
* @param {Array<import("../Map.js").HitMatch<T>>} matches The hit detected matches with tolerance.
* @return {T|undefined} Callback result.
* @template T
* @override
*/
forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, matches) {
assert(
this.hitDetectionEnabled_,
"`forEachFeatureAtCoordinate` cannot be used on a WebGL layer if the hit detection logic has been disabled using the `disableHitDetection: true` option."
);
if (!this.renderInstructions_ || !this.hitDetectionEnabled_) {
return void 0;
}
const pixel = apply(
frameState.coordinateToPixelTransform,
coordinate.slice()
);
const data = this.hitRenderTarget_.readPixel(pixel[0] / 2, pixel[1] / 2);
const color = [data[0] / 255, data[1] / 255, data[2] / 255, data[3] / 255];
const index = colorDecodeId(color);
const opacity = this.renderInstructions_[index];
const uid = Math.floor(opacity).toString();
const source = this.getLayer().getSource();
const feature = source.getFeatureByUid(uid);
if (feature) {
return callback(feature, this.getLayer(), null);
}
return void 0;
}
/**
* Render the world, either to the main framebuffer or to the hit framebuffer
* @param {import("../../Map.js").FrameState} frameState current frame state
* @param {boolean} forHitDetection whether the rendering is for hit detection
* @param {number} startWorld the world to render in the first iteration
* @param {number} endWorld the last world to render
* @param {number} worldWidth the width of the worlds being rendered
*/
renderWorlds(frameState, forHitDetection, startWorld, endWorld, worldWidth) {
let world = startWorld;
this.helper.useProgram(this.program_, frameState);
if (forHitDetection) {
this.hitRenderTarget_.setSize([
Math.floor(frameState.size[0] / 2),
Math.floor(frameState.size[1] / 2)
]);
this.helper.prepareDrawToRenderTarget(
frameState,
this.hitRenderTarget_,
true
);
}
const instanceAttributesStride = this.instanceAttributes.reduce(
(prev, curr) => prev + (curr.size || 1),
0
);
const instanceCount = this.instanceAttributesBuffer_.getSize() / instanceAttributesStride;
do {
this.helper.bindBuffer(this.indicesBuffer_);
this.helper.bindBuffer(this.verticesBuffer_);
this.helper.enableAttributes(this.attributes);
this.helper.bindBuffer(this.instanceAttributesBuffer_);
this.helper.enableAttributesInstanced(this.instanceAttributes);
this.helper.makeProjectionTransform(frameState, this.currentTransform_);
translate(this.currentTransform_, world * worldWidth, 0);
multiply(this.currentTransform_, this.invertRenderTransform_);
this.helper.applyUniforms(frameState);
this.helper.applyHitDetectionUniform(forHitDetection);
const renderCount = this.indicesBuffer_.getSize();
this.helper.drawElementsInstanced(0, renderCount, instanceCount);
} while (++world < endWorld);
}
/**
* Clean up.
* @override
*/
disposeInternal() {
this.worker_.terminate();
this.sourceListenKeys_.forEach(function(key) {
unlistenByKey(key);
});
this.sourceListenKeys_ = null;
super.disposeInternal();
}
renderDeclutter() {
}
};
var PointsLayer_default = WebGLPointsLayerRenderer;
// node_modules/ol/layer/WebGLPoints.js
var WebGLPointsLayer = class extends Layer_default {
/**
* @param {Options<VectorSourceType>} options Options.
*/
constructor(options) {
const baseOptions = Object.assign({}, options);
super(baseOptions);
this.styleVariables_ = options.variables || {};
this.parseResult_ = parseLiteralStyle(
options.style,
this.styleVariables_,
options.filter
);
this.hitDetectionDisabled_ = !!options.disableHitDetection;
}
/**
* @override
*/
createRenderer() {
const attributes = Object.keys(this.parseResult_.attributes).map(
(name) => ({
name,
...this.parseResult_.attributes[name]
})
);
return new PointsLayer_default(this, {
vertexShader: this.parseResult_.builder.getSymbolVertexShader(),
fragmentShader: this.parseResult_.builder.getSymbolFragmentShader(),
hitDetectionEnabled: !this.hitDetectionDisabled_,
uniforms: this.parseResult_.uniforms,
attributes: (
/** @type {Array<import('../renderer/webgl/PointsLayer.js').CustomAttribute>} */
attributes
)
});
}
/**
* Update any variables used by the layer style and trigger a re-render.
* @param {Object<string, number>} variables Variables to update.
*/
updateStyleVariables(variables) {
Object.assign(this.styleVariables_, variables);
this.changed();
}
};
var WebGLPoints_default = WebGLPointsLayer;
// node_modules/ol/layer/WebGLTile.js
function parseStyle(style, bandCount) {
const vertexShader = `
attribute vec2 ${Attributes.TEXTURE_COORD};
uniform mat4 ${Uniforms.TILE_TRANSFORM};
uniform float ${Uniforms.TEXTURE_PIXEL_WIDTH};
uniform float ${Uniforms.TEXTURE_PIXEL_HEIGHT};
uniform float ${Uniforms.TEXTURE_RESOLUTION};
uniform float ${Uniforms.TEXTURE_ORIGIN_X};
uniform float ${Uniforms.TEXTURE_ORIGIN_Y};
uniform float ${Uniforms.DEPTH};
varying vec2 v_textureCoord;
varying vec2 v_mapCoord;
void main() {
v_textureCoord = ${Attributes.TEXTURE_COORD};
v_mapCoord = vec2(
${Uniforms.TEXTURE_ORIGIN_X} + ${Uniforms.TEXTURE_RESOLUTION} * ${Uniforms.TEXTURE_PIXEL_WIDTH} * v_textureCoord[0],
${Uniforms.TEXTURE_ORIGIN_Y} - ${Uniforms.TEXTURE_RESOLUTION} * ${Uniforms.TEXTURE_PIXEL_HEIGHT} * v_textureCoord[1]
);
gl_Position = ${Uniforms.TILE_TRANSFORM} * vec4(${Attributes.TEXTURE_COORD}, ${Uniforms.DEPTH}, 1.0);
}
`;
const context = {
...newCompilationContext(),
bandCount
};
const pipeline = [];
if (style.color !== void 0) {
const color = expressionToGlsl(context, style.color, ColorType);
pipeline.push(`color = ${color};`);
}
if (style.contrast !== void 0) {
const contrast = expressionToGlsl(context, style.contrast, NumberType);
pipeline.push(
`color.rgb = clamp((${contrast} + 1.0) * color.rgb - (${contrast} / 2.0), vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0));`
);
}
if (style.exposure !== void 0) {
const exposure = expressionToGlsl(context, style.exposure, NumberType);
pipeline.push(
`color.rgb = clamp((${exposure} + 1.0) * color.rgb, vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0));`
);
}
if (style.saturation !== void 0) {
const saturation = expressionToGlsl(context, style.saturation, NumberType);
pipeline.push(`
float saturation = ${saturation} + 1.0;
float sr = (1.0 - saturation) * 0.2126;
float sg = (1.0 - saturation) * 0.7152;
float sb = (1.0 - saturation) * 0.0722;
mat3 saturationMatrix = mat3(
sr + saturation, sr, sr,
sg, sg + saturation, sg,
sb, sb, sb + saturation
);
color.rgb = clamp(saturationMatrix * color.rgb, vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0));
`);
}
if (style.gamma !== void 0) {
const gamma = expressionToGlsl(context, style.gamma, NumberType);
pipeline.push(`color.rgb = pow(color.rgb, vec3(1.0 / ${gamma}));`);
}
if (style.brightness !== void 0) {
const brightness = expressionToGlsl(context, style.brightness, NumberType);
pipeline.push(
`color.rgb = clamp(color.rgb + ${brightness}, vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0));`
);
}
const uniforms = {};
const numVariables = Object.keys(context.variables).length;
if (numVariables > 1 && !style.variables) {
throw new Error(
`Missing variables in style (expected ${context.variables})`
);
}
for (let i = 0; i < numVariables; ++i) {
const variable = context.variables[Object.keys(context.variables)[i]];
if (!(variable.name in style.variables)) {
throw new Error(`Missing '${variable.name}' in style variables`);
}
const uniformName = uniformNameForVariable(variable.name);
uniforms[uniformName] = function() {
let value = style.variables[variable.name];
if (typeof value === "string") {
value = getStringNumberEquivalent(value);
}
return value !== void 0 ? value : -9999999;
};
}
const uniformDeclarations = Object.keys(uniforms).map(function(name) {
return `uniform float ${name};`;
});
const textureCount = Math.ceil(bandCount / 4);
uniformDeclarations.push(
`uniform sampler2D ${Uniforms.TILE_TEXTURE_ARRAY}[${textureCount}];`
);
if (context.paletteTextures) {
uniformDeclarations.push(
`uniform sampler2D ${PALETTE_TEXTURE_ARRAY}[${context.paletteTextures.length}];`
);
}
const functionDefintions = Object.keys(context.functions).map(
function(name) {
return context.functions[name];
}
);
const fragmentShader = `
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
varying vec2 v_textureCoord;
varying vec2 v_mapCoord;
uniform vec4 ${Uniforms.RENDER_EXTENT};
uniform float ${Uniforms.TRANSITION_ALPHA};
uniform float ${Uniforms.TEXTURE_PIXEL_WIDTH};
uniform float ${Uniforms.TEXTURE_PIXEL_HEIGHT};
uniform float ${Uniforms.RESOLUTION};
uniform float ${Uniforms.ZOOM};
${uniformDeclarations.join("\n")}
${functionDefintions.join("\n")}
void main() {
if (
v_mapCoord[0] < ${Uniforms.RENDER_EXTENT}[0] ||
v_mapCoord[1] < ${Uniforms.RENDER_EXTENT}[1] ||
v_mapCoord[0] > ${Uniforms.RENDER_EXTENT}[2] ||
v_mapCoord[1] > ${Uniforms.RENDER_EXTENT}[3]
) {
discard;
}
vec4 color = texture2D(${Uniforms.TILE_TEXTURE_ARRAY}[0], v_textureCoord);
${pipeline.join("\n")}
gl_FragColor = color;
gl_FragColor.rgb *= gl_FragColor.a;
gl_FragColor *= ${Uniforms.TRANSITION_ALPHA};
}`;
return {
vertexShader,
fragmentShader,
uniforms,
paletteTextures: context.paletteTextures
};
}
var WebGLTileLayer = class extends BaseTile_default {
/**
* @param {Options} [options] Tile layer options.
*/
constructor(options) {
options = options ? Object.assign({}, options) : {};
const style = options.style || {};
delete options.style;
super(options);
this.sources_ = options.sources;
this.renderedSource_ = null;
this.renderedResolution_ = NaN;
this.style_ = style;
this.styleVariables_ = this.style_.variables || {};
this.handleSourceUpdate_();
this.addChangeListener(Property_default.SOURCE, this.handleSourceUpdate_);
}
/**
* Gets the sources for this layer, for a given extent and resolution.
* @param {import("../extent.js").Extent} extent Extent.
* @param {number} resolution Resolution.
* @return {Array<SourceType>} Sources.
*/
getSources(extent, resolution) {
const source = this.getSource();
return this.sources_ ? typeof this.sources_ === "function" ? this.sources_(extent, resolution) : this.sources_ : source ? [source] : [];
}
/**
* @return {SourceType} The source being rendered.
* @override
*/
getRenderSource() {
return this.renderedSource_ || this.getSource();
}
/**
* @return {import("../source/Source.js").State} Source state.
* @override
*/
getSourceState() {
const source = this.getRenderSource();
return source ? source.getState() : "undefined";
}
/**
* @private
*/
handleSourceUpdate_() {
if (this.hasRenderer()) {
this.getRenderer().clearCache();
}
const source = this.getSource();
if (source) {
if (source.getState() === "loading") {
const onChange = () => {
if (source.getState() === "ready") {
source.removeEventListener("change", onChange);
this.setStyle(this.style_);
}
};
source.addEventListener("change", onChange);
} else {
this.setStyle(this.style_);
}
}
}
/**
* @private
* @return {number} The number of source bands.
*/
getSourceBandCount_() {
const max = Number.MAX_SAFE_INTEGER;
const sources = this.getSources([-max, -max, max, max], max);
return sources && sources.length && "bandCount" in sources[0] ? sources[0].bandCount : 4;
}
/**
* @override
*/
createRenderer() {
const parsedStyle = parseStyle(this.style_, this.getSourceBandCount_());
return new TileLayer_default(this, {
vertexShader: parsedStyle.vertexShader,
fragmentShader: parsedStyle.fragmentShader,
uniforms: parsedStyle.uniforms,
cacheSize: this.getCacheSize(),
paletteTextures: parsedStyle.paletteTextures
});
}
/**
* @param {import("../Map").FrameState} frameState Frame state.
* @param {Array<SourceType>} sources Sources.
* @return {HTMLElement} Canvas.
*/
renderSources(frameState, sources) {
const layerRenderer = this.getRenderer();
let canvas;
for (let i = 0, ii = sources.length; i < ii; ++i) {
this.renderedSource_ = sources[i];
if (layerRenderer.prepareFrame(frameState)) {
canvas = layerRenderer.renderFrame(frameState);
}
}
return canvas;
}
/**
* @param {?import("../Map.js").FrameState} frameState Frame state.
* @param {HTMLElement} target Target which the renderer may (but need not) use
* for rendering its content.
* @return {HTMLElement} The rendered element.
* @override
*/
render(frameState, target) {
this.rendered = true;
const viewState = frameState.viewState;
const sources = this.getSources(frameState.extent, viewState.resolution);
let ready = true;
for (let i = 0, ii = sources.length; i < ii; ++i) {
const source = sources[i];
const sourceState = source.getState();
if (sourceState == "loading") {
const onChange = () => {
if (source.getState() == "ready") {
source.removeEventListener("change", onChange);
this.changed();
}
};
source.addEventListener("change", onChange);
}
ready = ready && sourceState == "ready";
}
const canvas = this.renderSources(frameState, sources);
if (this.getRenderer().renderComplete && ready) {
this.renderedResolution_ = viewState.resolution;
return canvas;
}
if (this.renderedResolution_ > 0.5 * viewState.resolution) {
const altSources = this.getSources(
frameState.extent,
this.renderedResolution_
).filter((source) => !sources.includes(source));
if (altSources.length > 0) {
return this.renderSources(frameState, altSources);
}
}
return canvas;
}
/**
* Update the layer style. The `updateStyleVariables` function is a more efficient
* way to update layer rendering. In cases where the whole style needs to be updated,
* this method may be called instead. Note that calling this method will also replace
* any previously set variables, so the new style also needs to include new variables,
* if needed.
* @param {Style} style The new style.
*/
setStyle(style) {
this.styleVariables_ = style.variables || {};
this.style_ = style;
if (this.hasRenderer()) {
const parsedStyle = parseStyle(this.style_, this.getSourceBandCount_());
const renderer = this.getRenderer();
renderer.reset({
vertexShader: parsedStyle.vertexShader,
fragmentShader: parsedStyle.fragmentShader,
uniforms: parsedStyle.uniforms,
paletteTextures: parsedStyle.paletteTextures
});
this.changed();
}
}
/**
* Update any variables used by the layer style and trigger a re-render.
* @param {Object<string, number>} variables Variables to update.
* @api
*/
updateStyleVariables(variables) {
Object.assign(this.styleVariables_, variables);
this.changed();
}
};
WebGLTileLayer.prototype.dispose;
var WebGLTile_default = WebGLTileLayer;
// node_modules/ol/layer/WebGLVector.js
var WebGLVectorLayer = class extends Layer_default {
/**
* @param {Options<VectorSourceType, FeatureType>} [options] Options.
*/
constructor(options) {
const baseOptions = Object.assign({}, options);
super(baseOptions);
this.styleVariables_ = options.variables || {};
this.style_ = options.style;
this.hitDetectionDisabled_ = !!options.disableHitDetection;
}
/**
* @override
*/
createRenderer() {
return new VectorLayer_default2(this, {
style: this.style_,
variables: this.styleVariables_,
disableHitDetection: this.hitDetectionDisabled_
});
}
/**
* Update any variables used by the layer style and trigger a re-render.
* @param {import('../style/flat.js').StyleVariables} variables Variables to update.
*/
updateStyleVariables(variables) {
Object.assign(this.styleVariables_, variables);
this.changed();
}
/**
* Set the layer style.
* @param {import('../style/flat.js').FlatStyleLike} style Layer style.
*/
setStyle(style) {
this.style_ = style;
this.clearRenderer();
this.changed();
}
};
var WebGLVector_default = WebGLVectorLayer;
export {
Graticule_default as Graticule,
Group_default as Group,
Heatmap_default as Heatmap,
Image_default as Image,
Layer_default as Layer,
Tile_default as Tile,
Vector_default as Vector,
VectorImage_default as VectorImage,
VectorTile_default as VectorTile,
WebGLPoints_default as WebGLPoints,
WebGLTile_default as WebGLTile,
WebGLVector_default as WebGLVector
};
//# sourceMappingURL=ol_layer.js.map