2111 lines
67 KiB
JavaScript
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
|