SourceTermAnalysisSystem_vue/node_modules/.vite/deps/chunk-2RRPH7ER.js
2026-05-15 10:22:44 +08:00

5339 lines
178 KiB
JavaScript

import {
Layer_default,
ZIndexContext_default,
canvasPool
} from "./chunk-JOOKRY6I.js";
import {
BaseVector_default
} from "./chunk-OVJRLVXU.js";
import {
Icon_default,
asColorLike,
defaultFillStyle,
defaultFont,
defaultLineCap,
defaultLineDash,
defaultLineDashOffset,
defaultLineJoin,
defaultLineWidth,
defaultMiterLimit,
defaultPadding,
defaultStrokeStyle,
defaultTextAlign,
defaultTextBaseline,
drawImageOrLabel,
getTextDimensions,
measureAndCacheTextWidth,
registerFont
} from "./chunk-EMRMEHGR.js";
import {
EventType_default,
ViewHint_default
} from "./chunk-S5OMZ56B.js";
import {
createCanvasContext2D,
releaseCanvas
} from "./chunk-YWIWRQT2.js";
import {
ImageState_default
} from "./chunk-5TDNKDLD.js";
import {
lineStringLength
} from "./chunk-JFXZSSOM.js";
import {
inflateCoordinates,
inflateCoordinatesArray,
inflateMultiCoordinatesArray,
snap
} from "./chunk-NLIGXLAR.js";
import {
rotate,
transform2D,
transformGeom2D
} from "./chunk-YUTQGDGI.js";
import {
apply,
compose,
create,
setFromArray
} from "./chunk-JFONEOYG.js";
import {
fromUserExtent,
getTransformFromProjections,
getUserProjection,
toUserExtent,
toUserResolution
} from "./chunk-XZU4LSFD.js";
import {
wrapX as wrapX2
} from "./chunk-3JZANJYE.js";
import {
clamp,
lerp,
toFixed
} from "./chunk-54BTDBAD.js";
import {
Relationship_default,
buffer,
clone,
containsCoordinate,
containsExtent,
coordinateRelationship,
createEmpty,
createOrUpdate,
extendCoordinate,
getHeight,
getWidth,
intersects,
wrapX
} from "./chunk-CKDBVGKM.js";
import {
getUid
} from "./chunk-H47PV7W6.js";
import {
ascending,
descending,
equals,
reverseSubArray
} from "./chunk-FQY6EMA7.js";
import {
isEmpty
} from "./chunk-5RHQVMYD.js";
// node_modules/ol/render/VectorContext.js
var VectorContext = class {
/**
* Render a geometry with a custom renderer.
*
* @param {import("../geom/SimpleGeometry.js").default} geometry Geometry.
* @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {Function} renderer Renderer.
* @param {Function} hitDetectionRenderer Renderer.
* @param {number} [index] Render order index.
*/
drawCustom(geometry, feature, renderer, hitDetectionRenderer, index) {
}
/**
* Render a geometry.
*
* @param {import("../geom/Geometry.js").default} geometry The geometry to render.
*/
drawGeometry(geometry) {
}
/**
* Set the rendering style.
*
* @param {import("../style/Style.js").default} style The rendering style.
*/
setStyle(style) {
}
/**
* @param {import("../geom/Circle.js").default} circleGeometry Circle geometry.
* @param {import("../Feature.js").default} feature Feature.
* @param {number} [index] Render order index.
*/
drawCircle(circleGeometry, feature, index) {
}
/**
* @param {import("../Feature.js").default} feature Feature.
* @param {import("../style/Style.js").default} style Style.
* @param {number} [index] Render order index.
*/
drawFeature(feature, style, index) {
}
/**
* @param {import("../geom/GeometryCollection.js").default} geometryCollectionGeometry Geometry collection.
* @param {import("../Feature.js").default} feature Feature.
* @param {number} [index] Render order index.
*/
drawGeometryCollection(geometryCollectionGeometry, feature, index) {
}
/**
* @param {import("../geom/LineString.js").default|import("./Feature.js").default} lineStringGeometry Line string geometry.
* @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
*/
drawLineString(lineStringGeometry, feature, index) {
}
/**
* @param {import("../geom/MultiLineString.js").default|import("./Feature.js").default} multiLineStringGeometry MultiLineString geometry.
* @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
*/
drawMultiLineString(multiLineStringGeometry, feature, index) {
}
/**
* @param {import("../geom/MultiPoint.js").default|import("./Feature.js").default} multiPointGeometry MultiPoint geometry.
* @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
*/
drawMultiPoint(multiPointGeometry, feature, index) {
}
/**
* @param {import("../geom/MultiPolygon.js").default} multiPolygonGeometry MultiPolygon geometry.
* @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
*/
drawMultiPolygon(multiPolygonGeometry, feature, index) {
}
/**
* @param {import("../geom/Point.js").default|import("./Feature.js").default} pointGeometry Point geometry.
* @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
*/
drawPoint(pointGeometry, feature, index) {
}
/**
* @param {import("../geom/Polygon.js").default|import("./Feature.js").default} polygonGeometry Polygon geometry.
* @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
*/
drawPolygon(polygonGeometry, feature, index) {
}
/**
* @param {import("../geom/SimpleGeometry.js").default|import("./Feature.js").default} geometry Geometry.
* @param {import("../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
*/
drawText(geometry, feature, index) {
}
/**
* @param {import("../style/Fill.js").default} fillStyle Fill style.
* @param {import("../style/Stroke.js").default} strokeStyle Stroke style.
*/
setFillStrokeStyle(fillStyle, strokeStyle) {
}
/**
* @param {import("../style/Image.js").default} imageStyle Image style.
* @param {import("../render/canvas.js").DeclutterImageWithText} [declutterImageWithText] Shared data for combined decluttering with a text style.
*/
setImageStyle(imageStyle, declutterImageWithText) {
}
/**
* @param {import("../style/Text.js").default} textStyle Text style.
* @param {import("../render/canvas.js").DeclutterImageWithText} [declutterImageWithText] Shared data for combined decluttering with an image style.
*/
setTextStyle(textStyle, declutterImageWithText) {
}
};
var VectorContext_default = VectorContext;
// node_modules/ol/render/canvas/Instruction.js
var Instruction = {
BEGIN_GEOMETRY: 0,
BEGIN_PATH: 1,
CIRCLE: 2,
CLOSE_PATH: 3,
CUSTOM: 4,
DRAW_CHARS: 5,
DRAW_IMAGE: 6,
END_GEOMETRY: 7,
FILL: 8,
MOVE_TO_LINE_TO: 9,
SET_FILL_STYLE: 10,
SET_STROKE_STYLE: 11,
STROKE: 12
};
var fillInstruction = [Instruction.FILL];
var strokeInstruction = [Instruction.STROKE];
var beginPathInstruction = [Instruction.BEGIN_PATH];
var closePathInstruction = [Instruction.CLOSE_PATH];
var Instruction_default = Instruction;
// node_modules/ol/render/canvas/Builder.js
var CanvasBuilder = class extends VectorContext_default {
/**
* @param {number} tolerance Tolerance.
* @param {import("../../extent.js").Extent} maxExtent Maximum extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
*/
constructor(tolerance, maxExtent, resolution, pixelRatio) {
super();
this.tolerance = tolerance;
this.maxExtent = maxExtent;
this.pixelRatio = pixelRatio;
this.maxLineWidth = 0;
this.resolution = resolution;
this.beginGeometryInstruction1_ = null;
this.beginGeometryInstruction2_ = null;
this.bufferedMaxExtent_ = null;
this.instructions = [];
this.coordinates = [];
this.tmpCoordinate_ = [];
this.hitDetectionInstructions = [];
this.state = /** @type {import("../canvas.js").FillStrokeState} */
{};
}
/**
* @protected
* @param {Array<number>} dashArray Dash array.
* @return {Array<number>} Dash array with pixel ratio applied
*/
applyPixelRatio(dashArray) {
const pixelRatio = this.pixelRatio;
return pixelRatio == 1 ? dashArray : dashArray.map(function(dash) {
return dash * pixelRatio;
});
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} stride Stride.
* @protected
* @return {number} My end
*/
appendFlatPointCoordinates(flatCoordinates, stride) {
const extent = this.getBufferedMaxExtent();
const tmpCoord = this.tmpCoordinate_;
const coordinates = this.coordinates;
let myEnd = coordinates.length;
for (let i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
tmpCoord[0] = flatCoordinates[i];
tmpCoord[1] = flatCoordinates[i + 1];
if (containsCoordinate(extent, tmpCoord)) {
coordinates[myEnd++] = tmpCoord[0];
coordinates[myEnd++] = tmpCoord[1];
}
}
return myEnd;
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {number} end End.
* @param {number} stride Stride.
* @param {boolean} closed Last input coordinate equals first.
* @param {boolean} skipFirst Skip first coordinate.
* @protected
* @return {number} My end.
*/
appendFlatLineCoordinates(flatCoordinates, offset, end, stride, closed, skipFirst) {
const coordinates = this.coordinates;
let myEnd = coordinates.length;
const extent = this.getBufferedMaxExtent();
if (skipFirst) {
offset += stride;
}
let lastXCoord = flatCoordinates[offset];
let lastYCoord = flatCoordinates[offset + 1];
const nextCoord = this.tmpCoordinate_;
let skipped = true;
let i, lastRel, nextRel;
for (i = offset + stride; i < end; i += stride) {
nextCoord[0] = flatCoordinates[i];
nextCoord[1] = flatCoordinates[i + 1];
nextRel = coordinateRelationship(extent, nextCoord);
if (nextRel !== lastRel) {
if (skipped) {
coordinates[myEnd++] = lastXCoord;
coordinates[myEnd++] = lastYCoord;
skipped = false;
}
coordinates[myEnd++] = nextCoord[0];
coordinates[myEnd++] = nextCoord[1];
} else if (nextRel === Relationship_default.INTERSECTING) {
coordinates[myEnd++] = nextCoord[0];
coordinates[myEnd++] = nextCoord[1];
skipped = false;
} else {
skipped = true;
}
lastXCoord = nextCoord[0];
lastYCoord = nextCoord[1];
lastRel = nextRel;
}
if (closed && skipped || i === offset + stride) {
coordinates[myEnd++] = lastXCoord;
coordinates[myEnd++] = lastYCoord;
}
return myEnd;
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {Array<number>} ends Ends.
* @param {number} stride Stride.
* @param {Array<number>} builderEnds Builder ends.
* @return {number} Offset.
*/
drawCustomCoordinates_(flatCoordinates, offset, ends, stride, builderEnds) {
for (let i = 0, ii = ends.length; i < ii; ++i) {
const end = ends[i];
const builderEnd = this.appendFlatLineCoordinates(
flatCoordinates,
offset,
end,
stride,
false,
false
);
builderEnds.push(builderEnd);
offset = end;
}
return offset;
}
/**
* @param {import("../../geom/SimpleGeometry.js").default} geometry Geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {Function} renderer Renderer.
* @param {Function} hitDetectionRenderer Renderer.
* @param {number} [index] Render order index.
* @override
*/
drawCustom(geometry, feature, renderer, hitDetectionRenderer, index) {
this.beginGeometry(geometry, feature, index);
const type = geometry.getType();
const stride = geometry.getStride();
const builderBegin = this.coordinates.length;
let flatCoordinates, builderEnd, builderEnds, builderEndss;
let offset;
switch (type) {
case "MultiPolygon":
flatCoordinates = /** @type {import("../../geom/MultiPolygon.js").default} */
geometry.getOrientedFlatCoordinates();
builderEndss = [];
const endss = (
/** @type {import("../../geom/MultiPolygon.js").default} */
geometry.getEndss()
);
offset = 0;
for (let i = 0, ii = endss.length; i < ii; ++i) {
const myEnds = [];
offset = this.drawCustomCoordinates_(
flatCoordinates,
offset,
endss[i],
stride,
myEnds
);
builderEndss.push(myEnds);
}
this.instructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEndss,
geometry,
renderer,
inflateMultiCoordinatesArray,
index
]);
this.hitDetectionInstructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEndss,
geometry,
hitDetectionRenderer || renderer,
inflateMultiCoordinatesArray,
index
]);
break;
case "Polygon":
case "MultiLineString":
builderEnds = [];
flatCoordinates = type == "Polygon" ? (
/** @type {import("../../geom/Polygon.js").default} */
geometry.getOrientedFlatCoordinates()
) : geometry.getFlatCoordinates();
offset = this.drawCustomCoordinates_(
flatCoordinates,
0,
/** @type {import("../../geom/Polygon.js").default|import("../../geom/MultiLineString.js").default} */
geometry.getEnds(),
stride,
builderEnds
);
this.instructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEnds,
geometry,
renderer,
inflateCoordinatesArray,
index
]);
this.hitDetectionInstructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEnds,
geometry,
hitDetectionRenderer || renderer,
inflateCoordinatesArray,
index
]);
break;
case "LineString":
case "Circle":
flatCoordinates = geometry.getFlatCoordinates();
builderEnd = this.appendFlatLineCoordinates(
flatCoordinates,
0,
flatCoordinates.length,
stride,
false,
false
);
this.instructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEnd,
geometry,
renderer,
inflateCoordinates,
index
]);
this.hitDetectionInstructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEnd,
geometry,
hitDetectionRenderer || renderer,
inflateCoordinates,
index
]);
break;
case "MultiPoint":
flatCoordinates = geometry.getFlatCoordinates();
builderEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);
if (builderEnd > builderBegin) {
this.instructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEnd,
geometry,
renderer,
inflateCoordinates,
index
]);
this.hitDetectionInstructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEnd,
geometry,
hitDetectionRenderer || renderer,
inflateCoordinates,
index
]);
}
break;
case "Point":
flatCoordinates = geometry.getFlatCoordinates();
this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
builderEnd = this.coordinates.length;
this.instructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEnd,
geometry,
renderer,
void 0,
index
]);
this.hitDetectionInstructions.push([
Instruction_default.CUSTOM,
builderBegin,
builderEnd,
geometry,
hitDetectionRenderer || renderer,
void 0,
index
]);
break;
default:
}
this.endGeometry(feature);
}
/**
* @protected
* @param {import("../../geom/Geometry").default|import("../Feature.js").default} geometry The geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} index Render order index
*/
beginGeometry(geometry, feature, index) {
this.beginGeometryInstruction1_ = [
Instruction_default.BEGIN_GEOMETRY,
feature,
0,
geometry,
index
];
this.instructions.push(this.beginGeometryInstruction1_);
this.beginGeometryInstruction2_ = [
Instruction_default.BEGIN_GEOMETRY,
feature,
0,
geometry,
index
];
this.hitDetectionInstructions.push(this.beginGeometryInstruction2_);
}
/**
* @return {import("../canvas.js").SerializableInstructions} the serializable instructions.
*/
finish() {
return {
instructions: this.instructions,
hitDetectionInstructions: this.hitDetectionInstructions,
coordinates: this.coordinates
};
}
/**
* Reverse the hit detection instructions.
*/
reverseHitDetectionInstructions() {
const hitDetectionInstructions = this.hitDetectionInstructions;
hitDetectionInstructions.reverse();
let i;
const n = hitDetectionInstructions.length;
let instruction;
let type;
let begin = -1;
for (i = 0; i < n; ++i) {
instruction = hitDetectionInstructions[i];
type = /** @type {import("./Instruction.js").default} */
instruction[0];
if (type == Instruction_default.END_GEOMETRY) {
begin = i;
} else if (type == Instruction_default.BEGIN_GEOMETRY) {
instruction[2] = i;
reverseSubArray(this.hitDetectionInstructions, begin, i);
begin = -1;
}
}
}
/**
* @param {import("../../style/Fill.js").default} fillStyle Fill style.
* @param {import('../canvas.js').FillStrokeState} [state] State.
* @return {import('../canvas.js').FillStrokeState} State.
*/
fillStyleToState(fillStyle, state = (
/** @type {import('../canvas.js').FillStrokeState} */
{}
)) {
if (fillStyle) {
const fillStyleColor = fillStyle.getColor();
state.fillPatternScale = fillStyleColor && typeof fillStyleColor === "object" && "src" in fillStyleColor ? this.pixelRatio : 1;
state.fillStyle = asColorLike(
fillStyleColor ? fillStyleColor : defaultFillStyle
);
} else {
state.fillStyle = void 0;
}
return state;
}
/**
* @param {import("../../style/Stroke.js").default} strokeStyle Stroke style.
* @param {import("../canvas.js").FillStrokeState} state State.
* @return {import("../canvas.js").FillStrokeState} State.
*/
strokeStyleToState(strokeStyle, state = (
/** @type {import('../canvas.js').FillStrokeState} */
{}
)) {
if (strokeStyle) {
const strokeStyleColor = strokeStyle.getColor();
state.strokeStyle = asColorLike(
strokeStyleColor ? strokeStyleColor : defaultStrokeStyle
);
const strokeStyleLineCap = strokeStyle.getLineCap();
state.lineCap = strokeStyleLineCap !== void 0 ? strokeStyleLineCap : defaultLineCap;
const strokeStyleLineDash = strokeStyle.getLineDash();
state.lineDash = strokeStyleLineDash ? strokeStyleLineDash.slice() : defaultLineDash;
const strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
state.lineDashOffset = strokeStyleLineDashOffset ? strokeStyleLineDashOffset : defaultLineDashOffset;
const strokeStyleLineJoin = strokeStyle.getLineJoin();
state.lineJoin = strokeStyleLineJoin !== void 0 ? strokeStyleLineJoin : defaultLineJoin;
const strokeStyleWidth = strokeStyle.getWidth();
state.lineWidth = strokeStyleWidth !== void 0 ? strokeStyleWidth : defaultLineWidth;
const strokeStyleMiterLimit = strokeStyle.getMiterLimit();
state.miterLimit = strokeStyleMiterLimit !== void 0 ? strokeStyleMiterLimit : defaultMiterLimit;
if (state.lineWidth > this.maxLineWidth) {
this.maxLineWidth = state.lineWidth;
this.bufferedMaxExtent_ = null;
}
} else {
state.strokeStyle = void 0;
state.lineCap = void 0;
state.lineDash = null;
state.lineDashOffset = void 0;
state.lineJoin = void 0;
state.lineWidth = void 0;
state.miterLimit = void 0;
}
return state;
}
/**
* @param {import("../../style/Fill.js").default} fillStyle Fill style.
* @param {import("../../style/Stroke.js").default} strokeStyle Stroke style.
* @override
*/
setFillStrokeStyle(fillStyle, strokeStyle) {
const state = this.state;
this.fillStyleToState(fillStyle, state);
this.strokeStyleToState(strokeStyle, state);
}
/**
* @param {import("../canvas.js").FillStrokeState} state State.
* @return {Array<*>} Fill instruction.
*/
createFill(state) {
const fillStyle = state.fillStyle;
const fillInstruction2 = [Instruction_default.SET_FILL_STYLE, fillStyle];
if (typeof fillStyle !== "string") {
fillInstruction2.push(state.fillPatternScale);
}
return fillInstruction2;
}
/**
* @param {import("../canvas.js").FillStrokeState} state State.
*/
applyStroke(state) {
this.instructions.push(this.createStroke(state));
}
/**
* @param {import("../canvas.js").FillStrokeState} state State.
* @return {Array<*>} Stroke instruction.
*/
createStroke(state) {
return [
Instruction_default.SET_STROKE_STYLE,
state.strokeStyle,
state.lineWidth * this.pixelRatio,
state.lineCap,
state.lineJoin,
state.miterLimit,
state.lineDash ? this.applyPixelRatio(state.lineDash) : null,
state.lineDashOffset * this.pixelRatio
];
}
/**
* @param {import("../canvas.js").FillStrokeState} state State.
* @param {function(this:CanvasBuilder, import("../canvas.js").FillStrokeState):Array<*>} createFill Create fill.
*/
updateFillStyle(state, createFill) {
const fillStyle = state.fillStyle;
if (typeof fillStyle !== "string" || state.currentFillStyle != fillStyle) {
this.instructions.push(createFill.call(this, state));
state.currentFillStyle = fillStyle;
}
}
/**
* @param {import("../canvas.js").FillStrokeState} state State.
* @param {function(this:CanvasBuilder, import("../canvas.js").FillStrokeState): void} applyStroke Apply stroke.
*/
updateStrokeStyle(state, applyStroke) {
const strokeStyle = state.strokeStyle;
const lineCap = state.lineCap;
const lineDash = state.lineDash;
const lineDashOffset = state.lineDashOffset;
const lineJoin = state.lineJoin;
const lineWidth = state.lineWidth;
const miterLimit = state.miterLimit;
if (state.currentStrokeStyle != strokeStyle || state.currentLineCap != lineCap || lineDash != state.currentLineDash && !equals(state.currentLineDash, lineDash) || state.currentLineDashOffset != lineDashOffset || state.currentLineJoin != lineJoin || state.currentLineWidth != lineWidth || state.currentMiterLimit != miterLimit) {
applyStroke.call(this, state);
state.currentStrokeStyle = strokeStyle;
state.currentLineCap = lineCap;
state.currentLineDash = lineDash;
state.currentLineDashOffset = lineDashOffset;
state.currentLineJoin = lineJoin;
state.currentLineWidth = lineWidth;
state.currentMiterLimit = miterLimit;
}
}
/**
* @param {import("../../Feature.js").FeatureLike} feature Feature.
*/
endGeometry(feature) {
this.beginGeometryInstruction1_[2] = this.instructions.length;
this.beginGeometryInstruction1_ = null;
this.beginGeometryInstruction2_[2] = this.hitDetectionInstructions.length;
this.beginGeometryInstruction2_ = null;
const endGeometryInstruction = [Instruction_default.END_GEOMETRY, feature];
this.instructions.push(endGeometryInstruction);
this.hitDetectionInstructions.push(endGeometryInstruction);
}
/**
* Get the buffered rendering extent. Rendering will be clipped to the extent
* provided to the constructor. To account for symbolizers that may intersect
* this extent, we calculate a buffered extent (e.g. based on stroke width).
* @return {import("../../extent.js").Extent} The buffered rendering extent.
* @protected
*/
getBufferedMaxExtent() {
if (!this.bufferedMaxExtent_) {
this.bufferedMaxExtent_ = clone(this.maxExtent);
if (this.maxLineWidth > 0) {
const width = this.resolution * (this.maxLineWidth + 1) / 2;
buffer(this.bufferedMaxExtent_, width, this.bufferedMaxExtent_);
}
}
return this.bufferedMaxExtent_;
}
};
var Builder_default = CanvasBuilder;
// node_modules/ol/render/canvas/ImageBuilder.js
var CanvasImageBuilder = class extends Builder_default {
/**
* @param {number} tolerance Tolerance.
* @param {import("../../extent.js").Extent} maxExtent Maximum extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
*/
constructor(tolerance, maxExtent, resolution, pixelRatio) {
super(tolerance, maxExtent, resolution, pixelRatio);
this.hitDetectionImage_ = null;
this.image_ = null;
this.imagePixelRatio_ = void 0;
this.anchorX_ = void 0;
this.anchorY_ = void 0;
this.height_ = void 0;
this.opacity_ = void 0;
this.originX_ = void 0;
this.originY_ = void 0;
this.rotateWithView_ = void 0;
this.rotation_ = void 0;
this.scale_ = void 0;
this.width_ = void 0;
this.declutterMode_ = void 0;
this.declutterImageWithText_ = void 0;
}
/**
* @param {import("../../geom/Point.js").default|import("../Feature.js").default} pointGeometry Point geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
* @override
*/
drawPoint(pointGeometry, feature, index) {
if (!this.image_ || this.maxExtent && !containsCoordinate(this.maxExtent, pointGeometry.getFlatCoordinates())) {
return;
}
this.beginGeometry(pointGeometry, feature, index);
const flatCoordinates = pointGeometry.getFlatCoordinates();
const stride = pointGeometry.getStride();
const myBegin = this.coordinates.length;
const myEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);
this.instructions.push([
Instruction_default.DRAW_IMAGE,
myBegin,
myEnd,
this.image_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_ * this.imagePixelRatio_,
this.anchorY_ * this.imagePixelRatio_,
Math.ceil(this.height_ * this.imagePixelRatio_),
this.opacity_,
this.originX_ * this.imagePixelRatio_,
this.originY_ * this.imagePixelRatio_,
this.rotateWithView_,
this.rotation_,
[
this.scale_[0] * this.pixelRatio / this.imagePixelRatio_,
this.scale_[1] * this.pixelRatio / this.imagePixelRatio_
],
Math.ceil(this.width_ * this.imagePixelRatio_),
this.declutterMode_,
this.declutterImageWithText_
]);
this.hitDetectionInstructions.push([
Instruction_default.DRAW_IMAGE,
myBegin,
myEnd,
this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_,
this.anchorY_,
this.height_,
1,
this.originX_,
this.originY_,
this.rotateWithView_,
this.rotation_,
this.scale_,
this.width_,
this.declutterMode_,
this.declutterImageWithText_
]);
this.endGeometry(feature);
}
/**
* @param {import("../../geom/MultiPoint.js").default|import("../Feature.js").default} multiPointGeometry MultiPoint geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
* @override
*/
drawMultiPoint(multiPointGeometry, feature, index) {
if (!this.image_) {
return;
}
this.beginGeometry(multiPointGeometry, feature, index);
const flatCoordinates = multiPointGeometry.getFlatCoordinates();
const filteredFlatCoordinates = [];
for (let i = 0, ii = flatCoordinates.length; i < ii; i += multiPointGeometry.getStride()) {
if (!this.maxExtent || containsCoordinate(this.maxExtent, flatCoordinates.slice(i, i + 2))) {
filteredFlatCoordinates.push(
flatCoordinates[i],
flatCoordinates[i + 1]
);
}
}
const myBegin = this.coordinates.length;
const myEnd = this.appendFlatPointCoordinates(filteredFlatCoordinates, 2);
this.instructions.push([
Instruction_default.DRAW_IMAGE,
myBegin,
myEnd,
this.image_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_ * this.imagePixelRatio_,
this.anchorY_ * this.imagePixelRatio_,
Math.ceil(this.height_ * this.imagePixelRatio_),
this.opacity_,
this.originX_ * this.imagePixelRatio_,
this.originY_ * this.imagePixelRatio_,
this.rotateWithView_,
this.rotation_,
[
this.scale_[0] * this.pixelRatio / this.imagePixelRatio_,
this.scale_[1] * this.pixelRatio / this.imagePixelRatio_
],
Math.ceil(this.width_ * this.imagePixelRatio_),
this.declutterMode_,
this.declutterImageWithText_
]);
this.hitDetectionInstructions.push([
Instruction_default.DRAW_IMAGE,
myBegin,
myEnd,
this.hitDetectionImage_,
// Remaining arguments to DRAW_IMAGE are in alphabetical order
this.anchorX_,
this.anchorY_,
this.height_,
1,
this.originX_,
this.originY_,
this.rotateWithView_,
this.rotation_,
this.scale_,
this.width_,
this.declutterMode_,
this.declutterImageWithText_
]);
this.endGeometry(feature);
}
/**
* @return {import("../canvas.js").SerializableInstructions} the serializable instructions.
* @override
*/
finish() {
this.reverseHitDetectionInstructions();
this.anchorX_ = void 0;
this.anchorY_ = void 0;
this.hitDetectionImage_ = null;
this.image_ = null;
this.imagePixelRatio_ = void 0;
this.height_ = void 0;
this.scale_ = void 0;
this.opacity_ = void 0;
this.originX_ = void 0;
this.originY_ = void 0;
this.rotateWithView_ = void 0;
this.rotation_ = void 0;
this.width_ = void 0;
return super.finish();
}
/**
* @param {import("../../style/Image.js").default} imageStyle Image style.
* @param {Object} [sharedData] Shared data.
* @override
*/
setImageStyle(imageStyle, sharedData) {
const anchor = imageStyle.getAnchor();
const size = imageStyle.getSize();
const origin = imageStyle.getOrigin();
this.imagePixelRatio_ = imageStyle.getPixelRatio(this.pixelRatio);
this.anchorX_ = anchor[0];
this.anchorY_ = anchor[1];
this.hitDetectionImage_ = imageStyle.getHitDetectionImage();
this.image_ = imageStyle.getImage(this.pixelRatio);
this.height_ = size[1];
this.opacity_ = imageStyle.getOpacity();
this.originX_ = origin[0];
this.originY_ = origin[1];
this.rotateWithView_ = imageStyle.getRotateWithView();
this.rotation_ = imageStyle.getRotation();
this.scale_ = imageStyle.getScaleArray();
this.width_ = size[0];
this.declutterMode_ = imageStyle.getDeclutterMode();
this.declutterImageWithText_ = sharedData;
}
};
var ImageBuilder_default = CanvasImageBuilder;
// node_modules/ol/render/canvas/LineStringBuilder.js
var CanvasLineStringBuilder = class extends Builder_default {
/**
* @param {number} tolerance Tolerance.
* @param {import("../../extent.js").Extent} maxExtent Maximum extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
*/
constructor(tolerance, maxExtent, resolution, pixelRatio) {
super(tolerance, maxExtent, resolution, pixelRatio);
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {number} end End.
* @param {number} stride Stride.
* @private
* @return {number} end.
*/
drawFlatCoordinates_(flatCoordinates, offset, end, stride) {
const myBegin = this.coordinates.length;
const myEnd = this.appendFlatLineCoordinates(
flatCoordinates,
offset,
end,
stride,
false,
false
);
const moveToLineToInstruction = [
Instruction_default.MOVE_TO_LINE_TO,
myBegin,
myEnd
];
this.instructions.push(moveToLineToInstruction);
this.hitDetectionInstructions.push(moveToLineToInstruction);
return end;
}
/**
* @param {import("../../geom/LineString.js").default|import("../Feature.js").default} lineStringGeometry Line string geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
* @override
*/
drawLineString(lineStringGeometry, feature, index) {
const state = this.state;
const strokeStyle = state.strokeStyle;
const lineWidth = state.lineWidth;
if (strokeStyle === void 0 || lineWidth === void 0) {
return;
}
this.updateStrokeStyle(state, this.applyStroke);
this.beginGeometry(lineStringGeometry, feature, index);
this.hitDetectionInstructions.push(
[
Instruction_default.SET_STROKE_STYLE,
state.strokeStyle,
state.lineWidth,
state.lineCap,
state.lineJoin,
state.miterLimit,
defaultLineDash,
defaultLineDashOffset
],
beginPathInstruction
);
const flatCoordinates = lineStringGeometry.getFlatCoordinates();
const stride = lineStringGeometry.getStride();
this.drawFlatCoordinates_(
flatCoordinates,
0,
flatCoordinates.length,
stride
);
this.hitDetectionInstructions.push(strokeInstruction);
this.endGeometry(feature);
}
/**
* @param {import("../../geom/MultiLineString.js").default|import("../Feature.js").default} multiLineStringGeometry MultiLineString geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
* @override
*/
drawMultiLineString(multiLineStringGeometry, feature, index) {
const state = this.state;
const strokeStyle = state.strokeStyle;
const lineWidth = state.lineWidth;
if (strokeStyle === void 0 || lineWidth === void 0) {
return;
}
this.updateStrokeStyle(state, this.applyStroke);
this.beginGeometry(multiLineStringGeometry, feature, index);
this.hitDetectionInstructions.push(
[
Instruction_default.SET_STROKE_STYLE,
state.strokeStyle,
state.lineWidth,
state.lineCap,
state.lineJoin,
state.miterLimit,
defaultLineDash,
defaultLineDashOffset
],
beginPathInstruction
);
const ends = multiLineStringGeometry.getEnds();
const flatCoordinates = multiLineStringGeometry.getFlatCoordinates();
const stride = multiLineStringGeometry.getStride();
let offset = 0;
for (let i = 0, ii = ends.length; i < ii; ++i) {
offset = this.drawFlatCoordinates_(
flatCoordinates,
offset,
/** @type {number} */
ends[i],
stride
);
}
this.hitDetectionInstructions.push(strokeInstruction);
this.endGeometry(feature);
}
/**
* @return {import("../canvas.js").SerializableInstructions} the serializable instructions.
* @override
*/
finish() {
const state = this.state;
if (state.lastStroke != void 0 && state.lastStroke != this.coordinates.length) {
this.instructions.push(strokeInstruction);
}
this.reverseHitDetectionInstructions();
this.state = null;
return super.finish();
}
/**
* @param {import("../canvas.js").FillStrokeState} state State.
* @override
*/
applyStroke(state) {
if (state.lastStroke != void 0 && state.lastStroke != this.coordinates.length) {
this.instructions.push(strokeInstruction);
state.lastStroke = this.coordinates.length;
}
state.lastStroke = 0;
super.applyStroke(state);
this.instructions.push(beginPathInstruction);
}
};
var LineStringBuilder_default = CanvasLineStringBuilder;
// node_modules/ol/render/canvas/PolygonBuilder.js
var CanvasPolygonBuilder = class extends Builder_default {
/**
* @param {number} tolerance Tolerance.
* @param {import("../../extent.js").Extent} maxExtent Maximum extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
*/
constructor(tolerance, maxExtent, resolution, pixelRatio) {
super(tolerance, maxExtent, resolution, pixelRatio);
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {Array<number>} ends Ends.
* @param {number} stride Stride.
* @private
* @return {number} End.
*/
drawFlatCoordinatess_(flatCoordinates, offset, ends, stride) {
const state = this.state;
const fill = state.fillStyle !== void 0;
const stroke = state.strokeStyle !== void 0;
const numEnds = ends.length;
this.instructions.push(beginPathInstruction);
this.hitDetectionInstructions.push(beginPathInstruction);
for (let i = 0; i < numEnds; ++i) {
const end = ends[i];
const myBegin = this.coordinates.length;
const myEnd = this.appendFlatLineCoordinates(
flatCoordinates,
offset,
end,
stride,
true,
!stroke
);
const moveToLineToInstruction = [
Instruction_default.MOVE_TO_LINE_TO,
myBegin,
myEnd
];
this.instructions.push(moveToLineToInstruction);
this.hitDetectionInstructions.push(moveToLineToInstruction);
if (stroke) {
this.instructions.push(closePathInstruction);
this.hitDetectionInstructions.push(closePathInstruction);
}
offset = end;
}
if (fill) {
this.instructions.push(fillInstruction);
this.hitDetectionInstructions.push(fillInstruction);
}
if (stroke) {
this.instructions.push(strokeInstruction);
this.hitDetectionInstructions.push(strokeInstruction);
}
return offset;
}
/**
* @param {import("../../geom/Circle.js").default} circleGeometry Circle geometry.
* @param {import("../../Feature.js").default} feature Feature.
* @param {number} [index] Render order index.
* @override
*/
drawCircle(circleGeometry, feature, index) {
const state = this.state;
const fillStyle = state.fillStyle;
const strokeStyle = state.strokeStyle;
if (fillStyle === void 0 && strokeStyle === void 0) {
return;
}
this.setFillStrokeStyles_();
this.beginGeometry(circleGeometry, feature, index);
if (state.fillStyle !== void 0) {
this.hitDetectionInstructions.push([
Instruction_default.SET_FILL_STYLE,
defaultFillStyle
]);
}
if (state.strokeStyle !== void 0) {
this.hitDetectionInstructions.push([
Instruction_default.SET_STROKE_STYLE,
state.strokeStyle,
state.lineWidth,
state.lineCap,
state.lineJoin,
state.miterLimit,
defaultLineDash,
defaultLineDashOffset
]);
}
const flatCoordinates = circleGeometry.getFlatCoordinates();
const stride = circleGeometry.getStride();
const myBegin = this.coordinates.length;
this.appendFlatLineCoordinates(
flatCoordinates,
0,
flatCoordinates.length,
stride,
false,
false
);
const circleInstruction = [Instruction_default.CIRCLE, myBegin];
this.instructions.push(beginPathInstruction, circleInstruction);
this.hitDetectionInstructions.push(beginPathInstruction, circleInstruction);
if (state.fillStyle !== void 0) {
this.instructions.push(fillInstruction);
this.hitDetectionInstructions.push(fillInstruction);
}
if (state.strokeStyle !== void 0) {
this.instructions.push(strokeInstruction);
this.hitDetectionInstructions.push(strokeInstruction);
}
this.endGeometry(feature);
}
/**
* @param {import("../../geom/Polygon.js").default|import("../Feature.js").default} polygonGeometry Polygon geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
* @override
*/
drawPolygon(polygonGeometry, feature, index) {
const state = this.state;
const fillStyle = state.fillStyle;
const strokeStyle = state.strokeStyle;
if (fillStyle === void 0 && strokeStyle === void 0) {
return;
}
this.setFillStrokeStyles_();
this.beginGeometry(polygonGeometry, feature, index);
if (state.fillStyle !== void 0) {
this.hitDetectionInstructions.push([
Instruction_default.SET_FILL_STYLE,
defaultFillStyle
]);
}
if (state.strokeStyle !== void 0) {
this.hitDetectionInstructions.push([
Instruction_default.SET_STROKE_STYLE,
state.strokeStyle,
state.lineWidth,
state.lineCap,
state.lineJoin,
state.miterLimit,
defaultLineDash,
defaultLineDashOffset
]);
}
const ends = polygonGeometry.getEnds();
const flatCoordinates = polygonGeometry.getOrientedFlatCoordinates();
const stride = polygonGeometry.getStride();
this.drawFlatCoordinatess_(
flatCoordinates,
0,
/** @type {Array<number>} */
ends,
stride
);
this.endGeometry(feature);
}
/**
* @param {import("../../geom/MultiPolygon.js").default} multiPolygonGeometry MultiPolygon geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
* @override
*/
drawMultiPolygon(multiPolygonGeometry, feature, index) {
const state = this.state;
const fillStyle = state.fillStyle;
const strokeStyle = state.strokeStyle;
if (fillStyle === void 0 && strokeStyle === void 0) {
return;
}
this.setFillStrokeStyles_();
this.beginGeometry(multiPolygonGeometry, feature, index);
if (state.fillStyle !== void 0) {
this.hitDetectionInstructions.push([
Instruction_default.SET_FILL_STYLE,
defaultFillStyle
]);
}
if (state.strokeStyle !== void 0) {
this.hitDetectionInstructions.push([
Instruction_default.SET_STROKE_STYLE,
state.strokeStyle,
state.lineWidth,
state.lineCap,
state.lineJoin,
state.miterLimit,
defaultLineDash,
defaultLineDashOffset
]);
}
const endss = multiPolygonGeometry.getEndss();
const flatCoordinates = multiPolygonGeometry.getOrientedFlatCoordinates();
const stride = multiPolygonGeometry.getStride();
let offset = 0;
for (let i = 0, ii = endss.length; i < ii; ++i) {
offset = this.drawFlatCoordinatess_(
flatCoordinates,
offset,
endss[i],
stride
);
}
this.endGeometry(feature);
}
/**
* @return {import("../canvas.js").SerializableInstructions} the serializable instructions.
* @override
*/
finish() {
this.reverseHitDetectionInstructions();
this.state = null;
const tolerance = this.tolerance;
if (tolerance !== 0) {
const coordinates = this.coordinates;
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
coordinates[i] = snap(coordinates[i], tolerance);
}
}
return super.finish();
}
/**
* @private
*/
setFillStrokeStyles_() {
const state = this.state;
this.updateFillStyle(state, this.createFill);
this.updateStrokeStyle(state, this.applyStroke);
}
};
var PolygonBuilder_default = CanvasPolygonBuilder;
// node_modules/ol/geom/flat/linechunk.js
function lineChunk(chunkLength, flatCoordinates, offset, end, stride) {
const chunks = [];
let cursor = offset;
let chunkM = 0;
let currentChunk = flatCoordinates.slice(offset, 2);
while (chunkM < chunkLength && cursor + stride < end) {
const [x1, y1] = currentChunk.slice(-2);
const x2 = flatCoordinates[cursor + stride];
const y2 = flatCoordinates[cursor + stride + 1];
const segmentLength = Math.sqrt(
(x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)
);
chunkM += segmentLength;
if (chunkM >= chunkLength) {
const m = (chunkLength - chunkM + segmentLength) / segmentLength;
const x = lerp(x1, x2, m);
const y = lerp(y1, y2, m);
currentChunk.push(x, y);
chunks.push(currentChunk);
currentChunk = [x, y];
if (chunkM == chunkLength) {
cursor += stride;
}
chunkM = 0;
} else if (chunkM < chunkLength) {
currentChunk.push(
flatCoordinates[cursor + stride],
flatCoordinates[cursor + stride + 1]
);
cursor += stride;
} else {
const missing = segmentLength - chunkM;
const x = lerp(x1, x2, missing / segmentLength);
const y = lerp(y1, y2, missing / segmentLength);
currentChunk.push(x, y);
chunks.push(currentChunk);
currentChunk = [x, y];
chunkM = 0;
cursor += stride;
}
}
if (chunkM > 0) {
chunks.push(currentChunk);
}
return chunks;
}
// node_modules/ol/geom/flat/straightchunk.js
function matchingChunk(maxAngle, flatCoordinates, offset, end, stride) {
let chunkStart = offset;
let chunkEnd = offset;
let chunkM = 0;
let m = 0;
let start = offset;
let acos, i, m12, m23, x1, y1, x12, y12, x23, y23;
for (i = offset; i < end; i += stride) {
const x2 = flatCoordinates[i];
const y2 = flatCoordinates[i + 1];
if (x1 !== void 0) {
x23 = x2 - x1;
y23 = y2 - y1;
m23 = Math.sqrt(x23 * x23 + y23 * y23);
if (x12 !== void 0) {
m += m12;
acos = Math.acos((x12 * x23 + y12 * y23) / (m12 * m23));
if (acos > maxAngle) {
if (m > chunkM) {
chunkM = m;
chunkStart = start;
chunkEnd = i;
}
m = 0;
start = i - stride;
}
}
m12 = m23;
x12 = x23;
y12 = y23;
}
x1 = x2;
y1 = y2;
}
m += m23;
return m > chunkM ? [start, i] : [chunkStart, chunkEnd];
}
// node_modules/ol/render/canvas/TextBuilder.js
var TEXT_ALIGN = {
"left": 0,
"center": 0.5,
"right": 1,
"top": 0,
"middle": 0.5,
"hanging": 0.2,
"alphabetic": 0.8,
"ideographic": 0.8,
"bottom": 1
};
var CanvasTextBuilder = class extends Builder_default {
/**
* @param {number} tolerance Tolerance.
* @param {import("../../extent.js").Extent} maxExtent Maximum extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
*/
constructor(tolerance, maxExtent, resolution, pixelRatio) {
super(tolerance, maxExtent, resolution, pixelRatio);
this.labels_ = null;
this.text_ = "";
this.textOffsetX_ = 0;
this.textOffsetY_ = 0;
this.textRotateWithView_ = void 0;
this.textKeepUpright_ = void 0;
this.textRotation_ = 0;
this.textFillState_ = null;
this.fillStates = {};
this.fillStates[defaultFillStyle] = { fillStyle: defaultFillStyle };
this.textStrokeState_ = null;
this.strokeStates = {};
this.textState_ = /** @type {import("../canvas.js").TextState} */
{};
this.textStates = {};
this.textKey_ = "";
this.fillKey_ = "";
this.strokeKey_ = "";
this.declutterMode_ = void 0;
this.declutterImageWithText_ = void 0;
}
/**
* @return {import("../canvas.js").SerializableInstructions} the serializable instructions.
* @override
*/
finish() {
const instructions = super.finish();
instructions.textStates = this.textStates;
instructions.fillStates = this.fillStates;
instructions.strokeStates = this.strokeStates;
return instructions;
}
/**
* @param {import("../../geom/SimpleGeometry.js").default|import("../Feature.js").default} geometry Geometry.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {number} [index] Render order index.
* @override
*/
drawText(geometry, feature, index) {
const fillState = this.textFillState_;
const strokeState = this.textStrokeState_;
const textState = this.textState_;
if (this.text_ === "" || !textState || !fillState && !strokeState) {
return;
}
const coordinates = this.coordinates;
let begin = coordinates.length;
const geometryType = geometry.getType();
let flatCoordinates = null;
let stride = geometry.getStride();
if (textState.placement === "line" && (geometryType == "LineString" || geometryType == "MultiLineString" || geometryType == "Polygon" || geometryType == "MultiPolygon")) {
if (!intersects(this.maxExtent, geometry.getExtent())) {
return;
}
let ends;
flatCoordinates = geometry.getFlatCoordinates();
if (geometryType == "LineString") {
ends = [flatCoordinates.length];
} else if (geometryType == "MultiLineString") {
ends = /** @type {import("../../geom/MultiLineString.js").default} */
geometry.getEnds();
} else if (geometryType == "Polygon") {
ends = /** @type {import("../../geom/Polygon.js").default} */
geometry.getEnds().slice(0, 1);
} else if (geometryType == "MultiPolygon") {
const endss = (
/** @type {import("../../geom/MultiPolygon.js").default} */
geometry.getEndss()
);
ends = [];
for (let i = 0, ii = endss.length; i < ii; ++i) {
ends.push(endss[i][0]);
}
}
this.beginGeometry(geometry, feature, index);
const repeat = textState.repeat;
const textAlign = repeat ? void 0 : textState.textAlign;
let flatOffset = 0;
for (let o = 0, oo = ends.length; o < oo; ++o) {
let chunks;
if (repeat) {
chunks = lineChunk(
repeat * this.resolution,
flatCoordinates,
flatOffset,
ends[o],
stride
);
} else {
chunks = [flatCoordinates.slice(flatOffset, ends[o])];
}
for (let c = 0, cc = chunks.length; c < cc; ++c) {
const chunk = chunks[c];
let chunkBegin = 0;
let chunkEnd = chunk.length;
if (textAlign == void 0) {
const range = matchingChunk(
textState.maxAngle,
chunk,
0,
chunk.length,
2
);
chunkBegin = range[0];
chunkEnd = range[1];
}
for (let i = chunkBegin; i < chunkEnd; i += stride) {
coordinates.push(chunk[i], chunk[i + 1]);
}
const end = coordinates.length;
flatOffset = ends[o];
this.drawChars_(begin, end);
begin = end;
}
}
this.endGeometry(feature);
} else {
let geometryWidths = textState.overflow ? null : [];
switch (geometryType) {
case "Point":
case "MultiPoint":
flatCoordinates = /** @type {import("../../geom/MultiPoint.js").default} */
geometry.getFlatCoordinates();
break;
case "LineString":
flatCoordinates = /** @type {import("../../geom/LineString.js").default} */
geometry.getFlatMidpoint();
break;
case "Circle":
flatCoordinates = /** @type {import("../../geom/Circle.js").default} */
geometry.getCenter();
break;
case "MultiLineString":
flatCoordinates = /** @type {import("../../geom/MultiLineString.js").default} */
geometry.getFlatMidpoints();
stride = 2;
break;
case "Polygon":
flatCoordinates = /** @type {import("../../geom/Polygon.js").default} */
geometry.getFlatInteriorPoint();
if (!textState.overflow) {
geometryWidths.push(flatCoordinates[2] / this.resolution);
}
stride = 3;
break;
case "MultiPolygon":
const interiorPoints = (
/** @type {import("../../geom/MultiPolygon.js").default} */
geometry.getFlatInteriorPoints()
);
flatCoordinates = [];
for (let i = 0, ii = interiorPoints.length; i < ii; i += 3) {
if (!textState.overflow) {
geometryWidths.push(interiorPoints[i + 2] / this.resolution);
}
flatCoordinates.push(interiorPoints[i], interiorPoints[i + 1]);
}
if (flatCoordinates.length === 0) {
return;
}
stride = 2;
break;
default:
}
const end = this.appendFlatPointCoordinates(flatCoordinates, stride);
if (end === begin) {
return;
}
if (geometryWidths && (end - begin) / 2 !== flatCoordinates.length / stride) {
let beg = begin / 2;
geometryWidths = geometryWidths.filter((w, i) => {
const keep = coordinates[(beg + i) * 2] === flatCoordinates[i * stride] && coordinates[(beg + i) * 2 + 1] === flatCoordinates[i * stride + 1];
if (!keep) {
--beg;
}
return keep;
});
}
this.saveTextStates_();
const backgroundFill = textState.backgroundFill ? this.createFill(this.fillStyleToState(textState.backgroundFill)) : null;
const backgroundStroke = textState.backgroundStroke ? this.createStroke(this.strokeStyleToState(textState.backgroundStroke)) : null;
this.beginGeometry(geometry, feature, index);
let padding = textState.padding;
if (padding != defaultPadding && (textState.scale[0] < 0 || textState.scale[1] < 0)) {
let p0 = textState.padding[0];
let p12 = textState.padding[1];
let p22 = textState.padding[2];
let p32 = textState.padding[3];
if (textState.scale[0] < 0) {
p12 = -p12;
p32 = -p32;
}
if (textState.scale[1] < 0) {
p0 = -p0;
p22 = -p22;
}
padding = [p0, p12, p22, p32];
}
const pixelRatio = this.pixelRatio;
this.instructions.push([
Instruction_default.DRAW_IMAGE,
begin,
end,
null,
NaN,
NaN,
NaN,
1,
0,
0,
this.textRotateWithView_,
this.textRotation_,
[1, 1],
NaN,
this.declutterMode_,
this.declutterImageWithText_,
padding == defaultPadding ? defaultPadding : padding.map(function(p) {
return p * pixelRatio;
}),
backgroundFill,
backgroundStroke,
this.text_,
this.textKey_,
this.strokeKey_,
this.fillKey_,
this.textOffsetX_,
this.textOffsetY_,
geometryWidths
]);
const scale = 1 / pixelRatio;
const hitDetectionBackgroundFill = backgroundFill ? backgroundFill.slice(0) : null;
if (hitDetectionBackgroundFill) {
hitDetectionBackgroundFill[1] = defaultFillStyle;
}
this.hitDetectionInstructions.push([
Instruction_default.DRAW_IMAGE,
begin,
end,
null,
NaN,
NaN,
NaN,
1,
0,
0,
this.textRotateWithView_,
this.textRotation_,
[scale, scale],
NaN,
this.declutterMode_,
this.declutterImageWithText_,
padding,
hitDetectionBackgroundFill,
backgroundStroke,
this.text_,
this.textKey_,
this.strokeKey_,
this.fillKey_ ? defaultFillStyle : this.fillKey_,
this.textOffsetX_,
this.textOffsetY_,
geometryWidths
]);
this.endGeometry(feature);
}
}
/**
* @private
*/
saveTextStates_() {
const strokeState = this.textStrokeState_;
const textState = this.textState_;
const fillState = this.textFillState_;
const strokeKey = this.strokeKey_;
if (strokeState) {
if (!(strokeKey in this.strokeStates)) {
this.strokeStates[strokeKey] = {
strokeStyle: strokeState.strokeStyle,
lineCap: strokeState.lineCap,
lineDashOffset: strokeState.lineDashOffset,
lineWidth: strokeState.lineWidth,
lineJoin: strokeState.lineJoin,
miterLimit: strokeState.miterLimit,
lineDash: strokeState.lineDash
};
}
}
const textKey = this.textKey_;
if (!(textKey in this.textStates)) {
this.textStates[textKey] = {
font: textState.font,
textAlign: textState.textAlign || defaultTextAlign,
justify: textState.justify,
textBaseline: textState.textBaseline || defaultTextBaseline,
scale: textState.scale
};
}
const fillKey = this.fillKey_;
if (fillState) {
if (!(fillKey in this.fillStates)) {
this.fillStates[fillKey] = {
fillStyle: fillState.fillStyle
};
}
}
}
/**
* @private
* @param {number} begin Begin.
* @param {number} end End.
*/
drawChars_(begin, end) {
const strokeState = this.textStrokeState_;
const textState = this.textState_;
const strokeKey = this.strokeKey_;
const textKey = this.textKey_;
const fillKey = this.fillKey_;
this.saveTextStates_();
const pixelRatio = this.pixelRatio;
const baseline = TEXT_ALIGN[textState.textBaseline];
const offsetY = this.textOffsetY_ * pixelRatio;
const text = this.text_;
const strokeWidth = strokeState ? strokeState.lineWidth * Math.abs(textState.scale[0]) / 2 : 0;
this.instructions.push([
Instruction_default.DRAW_CHARS,
begin,
end,
baseline,
textState.overflow,
fillKey,
textState.maxAngle,
pixelRatio,
offsetY,
strokeKey,
strokeWidth * pixelRatio,
text,
textKey,
1,
this.declutterMode_,
this.textKeepUpright_
]);
this.hitDetectionInstructions.push([
Instruction_default.DRAW_CHARS,
begin,
end,
baseline,
textState.overflow,
fillKey ? defaultFillStyle : fillKey,
textState.maxAngle,
pixelRatio,
offsetY,
strokeKey,
strokeWidth * pixelRatio,
text,
textKey,
1 / pixelRatio,
this.declutterMode_,
this.textKeepUpright_
]);
}
/**
* @param {import("../../style/Text.js").default} textStyle Text style.
* @param {Object} [sharedData] Shared data.
* @override
*/
setTextStyle(textStyle, sharedData) {
let textState, fillState, strokeState;
if (!textStyle) {
this.text_ = "";
} else {
const textFillStyle = textStyle.getFill();
if (!textFillStyle) {
fillState = null;
this.textFillState_ = fillState;
} else {
fillState = this.textFillState_;
if (!fillState) {
fillState = /** @type {import("../canvas.js").FillState} */
{};
this.textFillState_ = fillState;
}
fillState.fillStyle = asColorLike(
textFillStyle.getColor() || defaultFillStyle
);
}
const textStrokeStyle = textStyle.getStroke();
if (!textStrokeStyle) {
strokeState = null;
this.textStrokeState_ = strokeState;
} else {
strokeState = this.textStrokeState_;
if (!strokeState) {
strokeState = /** @type {import("../canvas.js").StrokeState} */
{};
this.textStrokeState_ = strokeState;
}
const lineDash = textStrokeStyle.getLineDash();
const lineDashOffset = textStrokeStyle.getLineDashOffset();
const lineWidth = textStrokeStyle.getWidth();
const miterLimit = textStrokeStyle.getMiterLimit();
strokeState.lineCap = textStrokeStyle.getLineCap() || defaultLineCap;
strokeState.lineDash = lineDash ? lineDash.slice() : defaultLineDash;
strokeState.lineDashOffset = lineDashOffset === void 0 ? defaultLineDashOffset : lineDashOffset;
strokeState.lineJoin = textStrokeStyle.getLineJoin() || defaultLineJoin;
strokeState.lineWidth = lineWidth === void 0 ? defaultLineWidth : lineWidth;
strokeState.miterLimit = miterLimit === void 0 ? defaultMiterLimit : miterLimit;
strokeState.strokeStyle = asColorLike(
textStrokeStyle.getColor() || defaultStrokeStyle
);
}
textState = this.textState_;
const font = textStyle.getFont() || defaultFont;
registerFont(font);
const textScale = textStyle.getScaleArray();
textState.overflow = textStyle.getOverflow();
textState.font = font;
textState.maxAngle = textStyle.getMaxAngle();
textState.placement = textStyle.getPlacement();
textState.textAlign = textStyle.getTextAlign();
textState.repeat = textStyle.getRepeat();
textState.justify = textStyle.getJustify();
textState.textBaseline = textStyle.getTextBaseline() || defaultTextBaseline;
textState.backgroundFill = textStyle.getBackgroundFill();
textState.backgroundStroke = textStyle.getBackgroundStroke();
textState.padding = textStyle.getPadding() || defaultPadding;
textState.scale = textScale === void 0 ? [1, 1] : textScale;
const textOffsetX = textStyle.getOffsetX();
const textOffsetY = textStyle.getOffsetY();
const textRotateWithView = textStyle.getRotateWithView();
const textKeepUpright = textStyle.getKeepUpright();
const textRotation = textStyle.getRotation();
this.text_ = textStyle.getText() || "";
this.textOffsetX_ = textOffsetX === void 0 ? 0 : textOffsetX;
this.textOffsetY_ = textOffsetY === void 0 ? 0 : textOffsetY;
this.textRotateWithView_ = textRotateWithView === void 0 ? false : textRotateWithView;
this.textKeepUpright_ = textKeepUpright === void 0 ? true : textKeepUpright;
this.textRotation_ = textRotation === void 0 ? 0 : textRotation;
this.strokeKey_ = strokeState ? (typeof strokeState.strokeStyle == "string" ? strokeState.strokeStyle : getUid(strokeState.strokeStyle)) + strokeState.lineCap + strokeState.lineDashOffset + "|" + strokeState.lineWidth + strokeState.lineJoin + strokeState.miterLimit + "[" + strokeState.lineDash.join() + "]" : "";
this.textKey_ = textState.font + textState.scale + (textState.textAlign || "?") + (textState.repeat || "?") + (textState.justify || "?") + (textState.textBaseline || "?");
this.fillKey_ = fillState && fillState.fillStyle ? typeof fillState.fillStyle == "string" ? fillState.fillStyle : "|" + getUid(fillState.fillStyle) : "";
}
this.declutterMode_ = textStyle.getDeclutterMode();
this.declutterImageWithText_ = sharedData;
}
};
var TextBuilder_default = CanvasTextBuilder;
// node_modules/ol/render/canvas/BuilderGroup.js
var BATCH_CONSTRUCTORS = {
"Circle": PolygonBuilder_default,
"Default": Builder_default,
"Image": ImageBuilder_default,
"LineString": LineStringBuilder_default,
"Polygon": PolygonBuilder_default,
"Text": TextBuilder_default
};
var BuilderGroup = class {
/**
* @param {number} tolerance Tolerance.
* @param {import("../../extent.js").Extent} maxExtent Max extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
*/
constructor(tolerance, maxExtent, resolution, pixelRatio) {
this.tolerance_ = tolerance;
this.maxExtent_ = maxExtent;
this.pixelRatio_ = pixelRatio;
this.resolution_ = resolution;
this.buildersByZIndex_ = {};
}
/**
* @return {!Object<string, !Object<import("../canvas.js").BuilderType, import("./Builder.js").SerializableInstructions>>} The serializable instructions
*/
finish() {
const builderInstructions = {};
for (const zKey in this.buildersByZIndex_) {
builderInstructions[zKey] = builderInstructions[zKey] || {};
const builders = this.buildersByZIndex_[zKey];
for (const builderKey in builders) {
const builderInstruction = builders[builderKey].finish();
builderInstructions[zKey][builderKey] = builderInstruction;
}
}
return builderInstructions;
}
/**
* @param {number|undefined} zIndex Z index.
* @param {import("../canvas.js").BuilderType} builderType Replay type.
* @return {import("../VectorContext.js").default} Replay.
*/
getBuilder(zIndex, builderType) {
const zIndexKey = zIndex !== void 0 ? zIndex.toString() : "0";
let replays = this.buildersByZIndex_[zIndexKey];
if (replays === void 0) {
replays = {};
this.buildersByZIndex_[zIndexKey] = replays;
}
let replay = replays[builderType];
if (replay === void 0) {
const Constructor = BATCH_CONSTRUCTORS[builderType];
replay = new Constructor(
this.tolerance_,
this.maxExtent_,
this.resolution_,
this.pixelRatio_
);
replays[builderType] = replay;
}
return replay;
}
};
var BuilderGroup_default = BuilderGroup;
// node_modules/ol/geom/flat/textpath.js
function drawTextOnPath(flatCoordinates, offset, end, stride, text, startM, maxAngle, scale, measureAndCacheTextWidth2, font, cache, rotation, keepUpright = true) {
let x2 = flatCoordinates[offset];
let y2 = flatCoordinates[offset + 1];
let x1 = 0;
let y1 = 0;
let segmentLength = 0;
let segmentM = 0;
function advance() {
x1 = x2;
y1 = y2;
offset += stride;
x2 = flatCoordinates[offset];
y2 = flatCoordinates[offset + 1];
segmentM += segmentLength;
segmentLength = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
do {
advance();
} while (offset < end - stride && segmentM + segmentLength < startM);
let interpolate = segmentLength === 0 ? 0 : (startM - segmentM) / segmentLength;
const beginX = lerp(x1, x2, interpolate);
const beginY = lerp(y1, y2, interpolate);
const startOffset = offset - stride;
const startLength = segmentM;
const endM = startM + scale * measureAndCacheTextWidth2(font, text, cache);
while (offset < end - stride && segmentM + segmentLength < endM) {
advance();
}
interpolate = segmentLength === 0 ? 0 : (endM - segmentM) / segmentLength;
const endX = lerp(x1, x2, interpolate);
const endY = lerp(y1, y2, interpolate);
let reverse = false;
if (keepUpright) {
if (rotation) {
const flat = [beginX, beginY, endX, endY];
rotate(flat, 0, 4, 2, rotation, flat, flat);
reverse = flat[0] > flat[2];
} else {
reverse = beginX > endX;
}
}
const PI = Math.PI;
const result = [];
const singleSegment = startOffset + stride === offset;
offset = startOffset;
segmentLength = 0;
segmentM = startLength;
x2 = flatCoordinates[offset];
y2 = flatCoordinates[offset + 1];
let previousAngle;
if (singleSegment) {
advance();
previousAngle = Math.atan2(y2 - y1, x2 - x1);
if (reverse) {
previousAngle += previousAngle > 0 ? -PI : PI;
}
const x = (endX + beginX) / 2;
const y = (endY + beginY) / 2;
result[0] = [x, y, (endM - startM) / 2, previousAngle, text];
return result;
}
text = text.replace(/\n/g, " ");
for (let i = 0, ii = text.length; i < ii; ) {
advance();
let angle = Math.atan2(y2 - y1, x2 - x1);
if (reverse) {
angle += angle > 0 ? -PI : PI;
}
if (previousAngle !== void 0) {
let delta = angle - previousAngle;
delta += delta > PI ? -2 * PI : delta < -PI ? 2 * PI : 0;
if (Math.abs(delta) > maxAngle) {
return null;
}
}
previousAngle = angle;
const iStart = i;
let charLength = 0;
for (; i < ii; ++i) {
const index = reverse ? ii - i - 1 : i;
const len = scale * measureAndCacheTextWidth2(font, text[index], cache);
if (offset + stride < end && segmentM + segmentLength < startM + charLength + len / 2) {
break;
}
charLength += len;
}
if (i === iStart) {
continue;
}
const chars = reverse ? text.substring(ii - iStart, ii - i) : text.substring(iStart, i);
interpolate = segmentLength === 0 ? 0 : (startM + charLength / 2 - segmentM) / segmentLength;
const x = lerp(x1, x2, interpolate);
const y = lerp(y1, y2, interpolate);
result.push([x, y, charLength / 2, angle, chars]);
startM += charLength;
}
return result;
}
// node_modules/ol/render/canvas/Executor.js
var tmpExtent = createEmpty();
var p1 = [];
var p2 = [];
var p3 = [];
var p4 = [];
function getDeclutterBox(replayImageOrLabelArgs) {
return replayImageOrLabelArgs[3].declutterBox;
}
var rtlRegEx = new RegExp(
/* eslint-disable prettier/prettier */
"[" + String.fromCharCode(1425) + "-" + String.fromCharCode(2303) + String.fromCharCode(64285) + "-" + String.fromCharCode(65023) + String.fromCharCode(65136) + "-" + String.fromCharCode(65276) + String.fromCharCode(67584) + "-" + String.fromCharCode(69631) + String.fromCharCode(124928) + "-" + String.fromCharCode(126975) + "]"
/* eslint-enable prettier/prettier */
);
function horizontalTextAlign(text, align) {
if (align === "start") {
align = rtlRegEx.test(text) ? "right" : "left";
} else if (align === "end") {
align = rtlRegEx.test(text) ? "left" : "right";
}
return TEXT_ALIGN[align];
}
function createTextChunks(acc, line, i) {
if (i > 0) {
acc.push("\n", "");
}
acc.push(line, "");
return acc;
}
function richTextToPlainText(result, part, index) {
if (index % 2 === 0) {
result += part;
}
return result;
}
var Executor = class {
/**
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {boolean} overlaps The replay can have overlapping geometries.
* @param {import("../canvas.js").SerializableInstructions} instructions The serializable instructions.
* @param {boolean} [deferredRendering] Enable deferred rendering.
*/
constructor(resolution, pixelRatio, overlaps, instructions, deferredRendering) {
this.overlaps = overlaps;
this.pixelRatio = pixelRatio;
this.resolution = resolution;
this.alignAndScaleFill_;
this.instructions = instructions.instructions;
this.coordinates = instructions.coordinates;
this.coordinateCache_ = {};
this.renderedTransform_ = create();
this.hitDetectionInstructions = instructions.hitDetectionInstructions;
this.pixelCoordinates_ = null;
this.viewRotation_ = 0;
this.fillStates = instructions.fillStates || {};
this.strokeStates = instructions.strokeStates || {};
this.textStates = instructions.textStates || {};
this.widths_ = {};
this.labels_ = {};
this.zIndexContext_ = deferredRendering ? new ZIndexContext_default() : null;
}
/**
* @return {ZIndexContext} ZIndex context.
*/
getZIndexContext() {
return this.zIndexContext_;
}
/**
* @param {string|Array<string>} text Text.
* @param {string} textKey Text style key.
* @param {string} fillKey Fill style key.
* @param {string} strokeKey Stroke style key.
* @return {import("../canvas.js").Label} Label.
*/
createLabel(text, textKey, fillKey, strokeKey) {
const key = text + textKey + fillKey + strokeKey;
if (this.labels_[key]) {
return this.labels_[key];
}
const strokeState = strokeKey ? this.strokeStates[strokeKey] : null;
const fillState = fillKey ? this.fillStates[fillKey] : null;
const textState = this.textStates[textKey];
const pixelRatio = this.pixelRatio;
const scale = [
textState.scale[0] * pixelRatio,
textState.scale[1] * pixelRatio
];
const align = textState.justify ? TEXT_ALIGN[textState.justify] : horizontalTextAlign(
Array.isArray(text) ? text[0] : text,
textState.textAlign || defaultTextAlign
);
const strokeWidth = strokeKey && strokeState.lineWidth ? strokeState.lineWidth : 0;
const chunks = Array.isArray(text) ? text : String(text).split("\n").reduce(createTextChunks, []);
const { width, height, widths, heights, lineWidths } = getTextDimensions(
textState,
chunks
);
const renderWidth = width + strokeWidth;
const contextInstructions = [];
const w = (renderWidth + 2) * scale[0];
const h = (height + strokeWidth) * scale[1];
const label = {
width: w < 0 ? Math.floor(w) : Math.ceil(w),
height: h < 0 ? Math.floor(h) : Math.ceil(h),
contextInstructions
};
if (scale[0] != 1 || scale[1] != 1) {
contextInstructions.push("scale", scale);
}
if (strokeKey) {
contextInstructions.push("strokeStyle", strokeState.strokeStyle);
contextInstructions.push("lineWidth", strokeWidth);
contextInstructions.push("lineCap", strokeState.lineCap);
contextInstructions.push("lineJoin", strokeState.lineJoin);
contextInstructions.push("miterLimit", strokeState.miterLimit);
contextInstructions.push("setLineDash", [strokeState.lineDash]);
contextInstructions.push("lineDashOffset", strokeState.lineDashOffset);
}
if (fillKey) {
contextInstructions.push("fillStyle", fillState.fillStyle);
}
contextInstructions.push("textBaseline", "middle");
contextInstructions.push("textAlign", "center");
const leftRight = 0.5 - align;
let x = align * renderWidth + leftRight * strokeWidth;
const strokeInstructions = [];
const fillInstructions = [];
let lineHeight = 0;
let lineOffset = 0;
let widthHeightIndex = 0;
let lineWidthIndex = 0;
let previousFont;
for (let i = 0, ii = chunks.length; i < ii; i += 2) {
const text2 = chunks[i];
if (text2 === "\n") {
lineOffset += lineHeight;
lineHeight = 0;
x = align * renderWidth + leftRight * strokeWidth;
++lineWidthIndex;
continue;
}
const font = chunks[i + 1] || textState.font;
if (font !== previousFont) {
if (strokeKey) {
strokeInstructions.push("font", font);
}
if (fillKey) {
fillInstructions.push("font", font);
}
previousFont = font;
}
lineHeight = Math.max(lineHeight, heights[widthHeightIndex]);
const fillStrokeArgs = [
text2,
x + leftRight * widths[widthHeightIndex] + align * (widths[widthHeightIndex] - lineWidths[lineWidthIndex]),
0.5 * (strokeWidth + lineHeight) + lineOffset
];
x += widths[widthHeightIndex];
if (strokeKey) {
strokeInstructions.push("strokeText", fillStrokeArgs);
}
if (fillKey) {
fillInstructions.push("fillText", fillStrokeArgs);
}
++widthHeightIndex;
}
Array.prototype.push.apply(contextInstructions, strokeInstructions);
Array.prototype.push.apply(contextInstructions, fillInstructions);
this.labels_[key] = label;
return label;
}
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {import("../../coordinate.js").Coordinate} p1 1st point of the background box.
* @param {import("../../coordinate.js").Coordinate} p2 2nd point of the background box.
* @param {import("../../coordinate.js").Coordinate} p3 3rd point of the background box.
* @param {import("../../coordinate.js").Coordinate} p4 4th point of the background box.
* @param {Array<*>} fillInstruction Fill instruction.
* @param {Array<*>} strokeInstruction Stroke instruction.
*/
replayTextBackground_(context, p12, p22, p32, p42, fillInstruction2, strokeInstruction2) {
context.beginPath();
context.moveTo.apply(context, p12);
context.lineTo.apply(context, p22);
context.lineTo.apply(context, p32);
context.lineTo.apply(context, p42);
context.lineTo.apply(context, p12);
if (fillInstruction2) {
this.alignAndScaleFill_ = /** @type {number} */
fillInstruction2[2];
context.fillStyle = /** @type {string} */
fillInstruction2[1];
this.fill_(context);
}
if (strokeInstruction2) {
this.setStrokeStyle_(
context,
/** @type {Array<*>} */
strokeInstruction2
);
context.stroke();
}
}
/**
* @private
* @param {number} sheetWidth Width of the sprite sheet.
* @param {number} sheetHeight Height of the sprite sheet.
* @param {number} centerX X.
* @param {number} centerY Y.
* @param {number} width Width.
* @param {number} height Height.
* @param {number} anchorX Anchor X.
* @param {number} anchorY Anchor Y.
* @param {number} originX Origin X.
* @param {number} originY Origin Y.
* @param {number} rotation Rotation.
* @param {import("../../size.js").Size} scale Scale.
* @param {boolean} snapToPixel Snap to pixel.
* @param {Array<number>} padding Padding.
* @param {boolean} fillStroke Background fill or stroke.
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @return {ImageOrLabelDimensions} Dimensions for positioning and decluttering the image or label.
*/
calculateImageOrLabelDimensions_(sheetWidth, sheetHeight, centerX, centerY, width, height, anchorX, anchorY, originX, originY, rotation, scale, snapToPixel, padding, fillStroke, feature) {
anchorX *= scale[0];
anchorY *= scale[1];
let x = centerX - anchorX;
let y = centerY - anchorY;
const w = width + originX > sheetWidth ? sheetWidth - originX : width;
const h = height + originY > sheetHeight ? sheetHeight - originY : height;
const boxW = padding[3] + w * scale[0] + padding[1];
const boxH = padding[0] + h * scale[1] + padding[2];
const boxX = x - padding[3];
const boxY = y - padding[0];
if (fillStroke || rotation !== 0) {
p1[0] = boxX;
p4[0] = boxX;
p1[1] = boxY;
p2[1] = boxY;
p2[0] = boxX + boxW;
p3[0] = p2[0];
p3[1] = boxY + boxH;
p4[1] = p3[1];
}
let transform;
if (rotation !== 0) {
transform = compose(
create(),
centerX,
centerY,
1,
1,
rotation,
-centerX,
-centerY
);
apply(transform, p1);
apply(transform, p2);
apply(transform, p3);
apply(transform, p4);
createOrUpdate(
Math.min(p1[0], p2[0], p3[0], p4[0]),
Math.min(p1[1], p2[1], p3[1], p4[1]),
Math.max(p1[0], p2[0], p3[0], p4[0]),
Math.max(p1[1], p2[1], p3[1], p4[1]),
tmpExtent
);
} else {
createOrUpdate(
Math.min(boxX, boxX + boxW),
Math.min(boxY, boxY + boxH),
Math.max(boxX, boxX + boxW),
Math.max(boxY, boxY + boxH),
tmpExtent
);
}
if (snapToPixel) {
x = Math.round(x);
y = Math.round(y);
}
return {
drawImageX: x,
drawImageY: y,
drawImageW: w,
drawImageH: h,
originX,
originY,
declutterBox: {
minX: tmpExtent[0],
minY: tmpExtent[1],
maxX: tmpExtent[2],
maxY: tmpExtent[3],
value: feature
},
canvasTransform: transform,
scale
};
}
/**
* @private
* @param {CanvasRenderingContext2D} context Context.
* @param {import('../../size.js').Size} scaledCanvasSize Scaled canvas size.
* @param {import("../canvas.js").Label|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} imageOrLabel Image.
* @param {ImageOrLabelDimensions} dimensions Dimensions.
* @param {number} opacity Opacity.
* @param {Array<*>} fillInstruction Fill instruction.
* @param {Array<*>} strokeInstruction Stroke instruction.
* @return {boolean} The image or label was rendered.
*/
replayImageOrLabel_(context, scaledCanvasSize, imageOrLabel, dimensions, opacity, fillInstruction2, strokeInstruction2) {
const fillStroke = !!(fillInstruction2 || strokeInstruction2);
const box = dimensions.declutterBox;
const strokePadding = strokeInstruction2 ? strokeInstruction2[2] * dimensions.scale[0] / 2 : 0;
const intersects2 = box.minX - strokePadding <= scaledCanvasSize[0] && box.maxX + strokePadding >= 0 && box.minY - strokePadding <= scaledCanvasSize[1] && box.maxY + strokePadding >= 0;
if (intersects2) {
if (fillStroke) {
this.replayTextBackground_(
context,
p1,
p2,
p3,
p4,
/** @type {Array<*>} */
fillInstruction2,
/** @type {Array<*>} */
strokeInstruction2
);
}
drawImageOrLabel(
context,
dimensions.canvasTransform,
opacity,
imageOrLabel,
dimensions.originX,
dimensions.originY,
dimensions.drawImageW,
dimensions.drawImageH,
dimensions.drawImageX,
dimensions.drawImageY,
dimensions.scale
);
}
return true;
}
/**
* @private
* @param {CanvasRenderingContext2D} context Context.
*/
fill_(context) {
const alignAndScale = this.alignAndScaleFill_;
if (alignAndScale) {
const origin = apply(this.renderedTransform_, [0, 0]);
const repeatSize = 512 * this.pixelRatio;
context.save();
context.translate(origin[0] % repeatSize, origin[1] % repeatSize);
if (alignAndScale !== 1) {
context.scale(alignAndScale, alignAndScale);
}
context.rotate(this.viewRotation_);
}
context.fill();
if (alignAndScale) {
context.restore();
}
}
/**
* @private
* @param {CanvasRenderingContext2D} context Context.
* @param {Array<*>} instruction Instruction.
*/
setStrokeStyle_(context, instruction) {
context.strokeStyle = /** @type {import("../../colorlike.js").ColorLike} */
instruction[1];
if (!instruction[1]) {
return;
}
context.lineWidth = /** @type {number} */
instruction[2];
context.lineCap = /** @type {CanvasLineCap} */
instruction[3];
context.lineJoin = /** @type {CanvasLineJoin} */
instruction[4];
context.miterLimit = /** @type {number} */
instruction[5];
context.lineDashOffset = /** @type {number} */
instruction[7];
context.setLineDash(
/** @type {Array<number>} */
instruction[6]
);
}
/**
* @private
* @param {string|Array<string>} text The text to draw.
* @param {string} textKey The key of the text state.
* @param {string} strokeKey The key for the stroke state.
* @param {string} fillKey The key for the fill state.
* @return {{label: import("../canvas.js").Label, anchorX: number, anchorY: number}} The text image and its anchor.
*/
drawLabelWithPointPlacement_(text, textKey, strokeKey, fillKey) {
const textState = this.textStates[textKey];
const label = this.createLabel(text, textKey, fillKey, strokeKey);
const strokeState = this.strokeStates[strokeKey];
const pixelRatio = this.pixelRatio;
const align = horizontalTextAlign(
Array.isArray(text) ? text[0] : text,
textState.textAlign || defaultTextAlign
);
const baseline = TEXT_ALIGN[textState.textBaseline || defaultTextBaseline];
const strokeWidth = strokeState && strokeState.lineWidth ? strokeState.lineWidth : 0;
const width = label.width / pixelRatio - 2 * textState.scale[0];
const anchorX = align * width + 2 * (0.5 - align) * strokeWidth;
const anchorY = baseline * label.height / pixelRatio + 2 * (0.5 - baseline) * strokeWidth;
return {
label,
anchorX,
anchorY
};
}
/**
* @private
* @param {CanvasRenderingContext2D} context Context.
* @param {import('../../size.js').Size} scaledCanvasSize Scaled canvas size
* @param {import("../../transform.js").Transform} transform Transform.
* @param {Array<*>} instructions Instructions array.
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
* @param {FeatureCallback<T>} [featureCallback] Feature callback.
* @param {import("../../extent.js").Extent} [hitExtent] Only check
* features that intersect this extent.
* @param {import("rbush").default<DeclutterEntry>} [declutterTree] Declutter tree.
* @return {T|undefined} Callback result.
* @template T
*/
execute_(context, scaledCanvasSize, transform, instructions, snapToPixel, featureCallback, hitExtent, declutterTree) {
const zIndexContext = this.zIndexContext_;
let pixelCoordinates;
if (this.pixelCoordinates_ && equals(transform, this.renderedTransform_)) {
pixelCoordinates = this.pixelCoordinates_;
} else {
if (!this.pixelCoordinates_) {
this.pixelCoordinates_ = [];
}
pixelCoordinates = transform2D(
this.coordinates,
0,
this.coordinates.length,
2,
transform,
this.pixelCoordinates_
);
setFromArray(this.renderedTransform_, transform);
}
let i = 0;
const ii = instructions.length;
let d = 0;
let dd;
let anchorX, anchorY, declutterMode, prevX, prevY, roundX, roundY, image, text, textKey, strokeKey, fillKey;
let pendingFill = 0;
let pendingStroke = 0;
const coordinateCache = this.coordinateCache_;
const viewRotation = this.viewRotation_;
const viewRotationFromTransform = Math.round(Math.atan2(-transform[1], transform[0]) * 1e12) / 1e12;
const state = (
/** @type {import("../../render.js").State} */
{
context,
pixelRatio: this.pixelRatio,
resolution: this.resolution,
rotation: viewRotation
}
);
const batchSize = this.instructions != instructions || this.overlaps ? 0 : 200;
let feature;
let x, y, currentGeometry;
while (i < ii) {
const instruction = instructions[i];
const type = (
/** @type {import("./Instruction.js").default} */
instruction[0]
);
switch (type) {
case Instruction_default.BEGIN_GEOMETRY:
feature = /** @type {import("../../Feature.js").FeatureLike} */
instruction[1];
currentGeometry = instruction[3];
if (!feature.getGeometry()) {
i = /** @type {number} */
instruction[2];
} else if (hitExtent !== void 0 && !intersects(hitExtent, currentGeometry.getExtent())) {
i = /** @type {number} */
instruction[2] + 1;
} else {
++i;
}
if (zIndexContext) {
zIndexContext.zIndex = instruction[4];
}
break;
case Instruction_default.BEGIN_PATH:
if (pendingFill > batchSize) {
this.fill_(context);
pendingFill = 0;
}
if (pendingStroke > batchSize) {
context.stroke();
pendingStroke = 0;
}
if (!pendingFill && !pendingStroke) {
context.beginPath();
prevX = NaN;
prevY = NaN;
}
++i;
break;
case Instruction_default.CIRCLE:
d = /** @type {number} */
instruction[1];
const x1 = pixelCoordinates[d];
const y1 = pixelCoordinates[d + 1];
const x2 = pixelCoordinates[d + 2];
const y2 = pixelCoordinates[d + 3];
const dx = x2 - x1;
const dy = y2 - y1;
const r = Math.sqrt(dx * dx + dy * dy);
context.moveTo(x1 + r, y1);
context.arc(x1, y1, r, 0, 2 * Math.PI, true);
++i;
break;
case Instruction_default.CLOSE_PATH:
context.closePath();
++i;
break;
case Instruction_default.CUSTOM:
d = /** @type {number} */
instruction[1];
dd = instruction[2];
const geometry = (
/** @type {import("../../geom/SimpleGeometry.js").default} */
instruction[3]
);
const renderer = instruction[4];
const fn = instruction[5];
state.geometry = geometry;
state.feature = feature;
if (!(i in coordinateCache)) {
coordinateCache[i] = [];
}
const coords = coordinateCache[i];
if (fn) {
fn(pixelCoordinates, d, dd, 2, coords);
} else {
coords[0] = pixelCoordinates[d];
coords[1] = pixelCoordinates[d + 1];
coords.length = 2;
}
if (zIndexContext) {
zIndexContext.zIndex = instruction[6];
}
renderer(coords, state);
++i;
break;
case Instruction_default.DRAW_IMAGE:
d = /** @type {number} */
instruction[1];
dd = /** @type {number} */
instruction[2];
image = /** @type {HTMLCanvasElement|HTMLVideoElement|HTMLImageElement} */
instruction[3];
anchorX = /** @type {number} */
instruction[4];
anchorY = /** @type {number} */
instruction[5];
let height = (
/** @type {number} */
instruction[6]
);
const opacity = (
/** @type {number} */
instruction[7]
);
const originX = (
/** @type {number} */
instruction[8]
);
const originY = (
/** @type {number} */
instruction[9]
);
const rotateWithView = (
/** @type {boolean} */
instruction[10]
);
let rotation = (
/** @type {number} */
instruction[11]
);
const scale = (
/** @type {import("../../size.js").Size} */
instruction[12]
);
let width = (
/** @type {number} */
instruction[13]
);
declutterMode = instruction[14] || "declutter";
const declutterImageWithText = (
/** @type {{args: import("../canvas.js").DeclutterImageWithText, declutterMode: import('../../style/Style.js').DeclutterMode}} */
instruction[15]
);
if (!image && instruction.length >= 20) {
text = /** @type {string} */
instruction[19];
textKey = /** @type {string} */
instruction[20];
strokeKey = /** @type {string} */
instruction[21];
fillKey = /** @type {string} */
instruction[22];
const labelWithAnchor = this.drawLabelWithPointPlacement_(
text,
textKey,
strokeKey,
fillKey
);
image = labelWithAnchor.label;
instruction[3] = image;
const textOffsetX = (
/** @type {number} */
instruction[23]
);
anchorX = (labelWithAnchor.anchorX - textOffsetX) * this.pixelRatio;
instruction[4] = anchorX;
const textOffsetY = (
/** @type {number} */
instruction[24]
);
anchorY = (labelWithAnchor.anchorY - textOffsetY) * this.pixelRatio;
instruction[5] = anchorY;
height = image.height;
instruction[6] = height;
width = image.width;
instruction[13] = width;
}
let geometryWidths;
if (instruction.length > 25) {
geometryWidths = /** @type {number} */
instruction[25];
}
let padding, backgroundFillInstruction, backgroundStrokeInstruction;
if (instruction.length > 17) {
padding = /** @type {Array<number>} */
instruction[16];
backgroundFillInstruction = /** @type {Array<*>} */
instruction[17];
backgroundStrokeInstruction = /** @type {Array<*>} */
instruction[18];
} else {
padding = defaultPadding;
backgroundFillInstruction = null;
backgroundStrokeInstruction = null;
}
if (rotateWithView && viewRotationFromTransform) {
rotation += viewRotation;
} else if (!rotateWithView && !viewRotationFromTransform) {
rotation -= viewRotation;
}
let widthIndex = 0;
for (; d < dd; d += 2) {
if (geometryWidths && geometryWidths[widthIndex++] < width / this.pixelRatio) {
continue;
}
const dimensions = this.calculateImageOrLabelDimensions_(
image.width,
image.height,
pixelCoordinates[d],
pixelCoordinates[d + 1],
width,
height,
anchorX,
anchorY,
originX,
originY,
rotation,
scale,
snapToPixel,
padding,
!!backgroundFillInstruction || !!backgroundStrokeInstruction,
feature
);
const args = [
context,
scaledCanvasSize,
image,
dimensions,
opacity,
backgroundFillInstruction,
backgroundStrokeInstruction
];
if (declutterTree) {
let imageArgs, imageDeclutterMode, imageDeclutterBox;
if (declutterImageWithText) {
const index = dd - d;
if (!declutterImageWithText[index]) {
declutterImageWithText[index] = { args, declutterMode };
continue;
}
const imageDeclutter = declutterImageWithText[index];
imageArgs = imageDeclutter.args;
imageDeclutterMode = imageDeclutter.declutterMode;
delete declutterImageWithText[index];
imageDeclutterBox = getDeclutterBox(imageArgs);
}
let renderImage, renderText;
if (imageArgs && (imageDeclutterMode !== "declutter" || !declutterTree.collides(imageDeclutterBox))) {
renderImage = true;
}
if (declutterMode !== "declutter" || !declutterTree.collides(dimensions.declutterBox)) {
renderText = true;
}
if (imageDeclutterMode === "declutter" && declutterMode === "declutter") {
const render = renderImage && renderText;
renderImage = render;
renderText = render;
}
if (renderImage) {
if (imageDeclutterMode !== "none") {
declutterTree.insert(imageDeclutterBox);
}
this.replayImageOrLabel_.apply(this, imageArgs);
}
if (renderText) {
if (declutterMode !== "none") {
declutterTree.insert(dimensions.declutterBox);
}
this.replayImageOrLabel_.apply(this, args);
}
} else {
this.replayImageOrLabel_.apply(this, args);
}
}
++i;
break;
case Instruction_default.DRAW_CHARS:
const begin = (
/** @type {number} */
instruction[1]
);
const end = (
/** @type {number} */
instruction[2]
);
const baseline = (
/** @type {number} */
instruction[3]
);
const overflow = (
/** @type {number} */
instruction[4]
);
fillKey = /** @type {string} */
instruction[5];
const maxAngle = (
/** @type {number} */
instruction[6]
);
const measurePixelRatio = (
/** @type {number} */
instruction[7]
);
const offsetY = (
/** @type {number} */
instruction[8]
);
strokeKey = /** @type {string} */
instruction[9];
const strokeWidth = (
/** @type {number} */
instruction[10]
);
text = /** @type {string|Array<string>} */
instruction[11];
if (Array.isArray(text)) {
text = text.reduce(richTextToPlainText, "");
}
textKey = /** @type {string} */
instruction[12];
const pixelRatioScale = [
/** @type {number} */
instruction[13],
/** @type {number} */
instruction[13]
];
declutterMode = instruction[14] || "declutter";
const textKeepUpright = (
/** @type {boolean} */
instruction[15]
);
const textState = this.textStates[textKey];
const font = textState.font;
const textScale = [
textState.scale[0] * measurePixelRatio,
textState.scale[1] * measurePixelRatio
];
let cachedWidths;
if (font in this.widths_) {
cachedWidths = this.widths_[font];
} else {
cachedWidths = {};
this.widths_[font] = cachedWidths;
}
const pathLength = lineStringLength(pixelCoordinates, begin, end, 2);
const textLength = Math.abs(textScale[0]) * measureAndCacheTextWidth(font, text, cachedWidths);
if (overflow || textLength <= pathLength) {
const textAlign = this.textStates[textKey].textAlign;
const startM = (pathLength - textLength) * horizontalTextAlign(text, textAlign);
const parts = drawTextOnPath(
pixelCoordinates,
begin,
end,
2,
text,
startM,
maxAngle,
Math.abs(textScale[0]),
measureAndCacheTextWidth,
font,
cachedWidths,
viewRotationFromTransform ? 0 : this.viewRotation_,
textKeepUpright
);
drawChars: if (parts) {
const replayImageOrLabelArgs = [];
let c, cc, chars, label, part;
if (strokeKey) {
for (c = 0, cc = parts.length; c < cc; ++c) {
part = parts[c];
chars = /** @type {string} */
part[4];
label = this.createLabel(chars, textKey, "", strokeKey);
anchorX = /** @type {number} */
part[2] + (textScale[0] < 0 ? -strokeWidth : strokeWidth);
anchorY = baseline * label.height + (0.5 - baseline) * 2 * strokeWidth * textScale[1] / textScale[0] - offsetY;
const dimensions = this.calculateImageOrLabelDimensions_(
label.width,
label.height,
part[0],
part[1],
label.width,
label.height,
anchorX,
anchorY,
0,
0,
part[3],
pixelRatioScale,
false,
defaultPadding,
false,
feature
);
if (declutterTree && declutterMode === "declutter" && declutterTree.collides(dimensions.declutterBox)) {
break drawChars;
}
replayImageOrLabelArgs.push([
context,
scaledCanvasSize,
label,
dimensions,
1,
null,
null
]);
}
}
if (fillKey) {
for (c = 0, cc = parts.length; c < cc; ++c) {
part = parts[c];
chars = /** @type {string} */
part[4];
label = this.createLabel(chars, textKey, fillKey, "");
anchorX = /** @type {number} */
part[2];
anchorY = baseline * label.height - offsetY;
const dimensions = this.calculateImageOrLabelDimensions_(
label.width,
label.height,
part[0],
part[1],
label.width,
label.height,
anchorX,
anchorY,
0,
0,
part[3],
pixelRatioScale,
false,
defaultPadding,
false,
feature
);
if (declutterTree && declutterMode === "declutter" && declutterTree.collides(dimensions.declutterBox)) {
break drawChars;
}
replayImageOrLabelArgs.push([
context,
scaledCanvasSize,
label,
dimensions,
1,
null,
null
]);
}
}
if (declutterTree && declutterMode !== "none") {
declutterTree.load(replayImageOrLabelArgs.map(getDeclutterBox));
}
for (let i2 = 0, ii2 = replayImageOrLabelArgs.length; i2 < ii2; ++i2) {
this.replayImageOrLabel_.apply(this, replayImageOrLabelArgs[i2]);
}
}
}
++i;
break;
case Instruction_default.END_GEOMETRY:
if (featureCallback !== void 0) {
feature = /** @type {import("../../Feature.js").FeatureLike} */
instruction[1];
const result = featureCallback(
feature,
currentGeometry,
declutterMode
);
if (result) {
return result;
}
}
++i;
break;
case Instruction_default.FILL:
if (batchSize) {
pendingFill++;
} else {
this.fill_(context);
}
++i;
break;
case Instruction_default.MOVE_TO_LINE_TO:
d = /** @type {number} */
instruction[1];
dd = /** @type {number} */
instruction[2];
x = pixelCoordinates[d];
y = pixelCoordinates[d + 1];
context.moveTo(x, y);
prevX = x + 0.5 | 0;
prevY = y + 0.5 | 0;
for (d += 2; d < dd; d += 2) {
x = pixelCoordinates[d];
y = pixelCoordinates[d + 1];
roundX = x + 0.5 | 0;
roundY = y + 0.5 | 0;
if (d == dd - 2 || roundX !== prevX || roundY !== prevY) {
context.lineTo(x, y);
prevX = roundX;
prevY = roundY;
}
}
++i;
break;
case Instruction_default.SET_FILL_STYLE:
this.alignAndScaleFill_ = instruction[2];
if (pendingFill) {
this.fill_(context);
pendingFill = 0;
if (pendingStroke) {
context.stroke();
pendingStroke = 0;
}
}
context.fillStyle = instruction[1];
++i;
break;
case Instruction_default.SET_STROKE_STYLE:
if (pendingStroke) {
context.stroke();
pendingStroke = 0;
}
this.setStrokeStyle_(
context,
/** @type {Array<*>} */
instruction
);
++i;
break;
case Instruction_default.STROKE:
if (batchSize) {
pendingStroke++;
} else {
context.stroke();
}
++i;
break;
default:
++i;
break;
}
}
if (pendingFill) {
this.fill_(context);
}
if (pendingStroke) {
context.stroke();
}
return void 0;
}
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {import('../../size.js').Size} scaledCanvasSize Scaled canvas size.
* @param {import("../../transform.js").Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
* @param {import("rbush").default<DeclutterEntry>} [declutterTree] Declutter tree.
*/
execute(context, scaledCanvasSize, transform, viewRotation, snapToPixel, declutterTree) {
this.viewRotation_ = viewRotation;
this.execute_(
context,
scaledCanvasSize,
transform,
this.instructions,
snapToPixel,
void 0,
void 0,
declutterTree
);
}
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {import("../../transform.js").Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {FeatureCallback<T>} [featureCallback] Feature callback.
* @param {import("../../extent.js").Extent} [hitExtent] Only check
* features that intersect this extent.
* @return {T|undefined} Callback result.
* @template T
*/
executeHitDetection(context, transform, viewRotation, featureCallback, hitExtent) {
this.viewRotation_ = viewRotation;
return this.execute_(
context,
[context.canvas.width, context.canvas.height],
transform,
this.hitDetectionInstructions,
true,
featureCallback,
hitExtent
);
}
};
var Executor_default = Executor;
// node_modules/ol/render/canvas/ExecutorGroup.js
var ALL = [
"Polygon",
"Circle",
"LineString",
"Image",
"Text",
"Default"
];
var DECLUTTER = ["Image", "Text"];
var NON_DECLUTTER = ALL.filter(
(builderType) => !DECLUTTER.includes(builderType)
);
var ExecutorGroup = class {
/**
* @param {import("../../extent.js").Extent} maxExtent Max extent for clipping. When a
* `maxExtent` was set on the Builder for this executor group, the same `maxExtent`
* should be set here, unless the target context does not exceed that extent (which
* can be the case when rendering to tiles).
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {boolean} overlaps The executor group can have overlapping geometries.
* @param {!Object<string, !Object<import("../canvas.js").BuilderType, import("../canvas.js").SerializableInstructions>>} allInstructions
* The serializable instructions.
* @param {number} [renderBuffer] Optional rendering buffer.
* @param {boolean} [deferredRendering] Enable deferred rendering with renderDeferred().
*/
constructor(maxExtent, resolution, pixelRatio, overlaps, allInstructions, renderBuffer, deferredRendering) {
this.maxExtent_ = maxExtent;
this.overlaps_ = overlaps;
this.pixelRatio_ = pixelRatio;
this.resolution_ = resolution;
this.renderBuffer_ = renderBuffer;
this.executorsByZIndex_ = {};
this.hitDetectionContext_ = null;
this.hitDetectionTransform_ = create();
this.renderedContext_ = null;
this.deferredZIndexContexts_ = {};
this.createExecutors_(allInstructions, deferredRendering);
}
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {import("../../transform.js").Transform} transform Transform.
*/
clip(context, transform) {
const flatClipCoords = this.getClipCoords(transform);
context.beginPath();
context.moveTo(flatClipCoords[0], flatClipCoords[1]);
context.lineTo(flatClipCoords[2], flatClipCoords[3]);
context.lineTo(flatClipCoords[4], flatClipCoords[5]);
context.lineTo(flatClipCoords[6], flatClipCoords[7]);
context.clip();
}
/**
* Create executors and populate them using the provided instructions.
* @private
* @param {!Object<string, !Object<string, import("../canvas.js").SerializableInstructions>>} allInstructions The serializable instructions
* @param {boolean} deferredRendering Enable deferred rendering.
*/
createExecutors_(allInstructions, deferredRendering) {
for (const zIndex in allInstructions) {
let executors = this.executorsByZIndex_[zIndex];
if (executors === void 0) {
executors = {};
this.executorsByZIndex_[zIndex] = executors;
}
const instructionByZindex = allInstructions[zIndex];
for (const builderType in instructionByZindex) {
const instructions = instructionByZindex[builderType];
executors[builderType] = new Executor_default(
this.resolution_,
this.pixelRatio_,
this.overlaps_,
instructions,
deferredRendering
);
}
}
}
/**
* @param {Array<import("../canvas.js").BuilderType>} executors Executors.
* @return {boolean} Has executors of the provided types.
*/
hasExecutors(executors) {
for (const zIndex in this.executorsByZIndex_) {
const candidates = this.executorsByZIndex_[zIndex];
for (let i = 0, ii = executors.length; i < ii; ++i) {
if (executors[i] in candidates) {
return true;
}
}
}
return false;
}
/**
* @param {import("../../coordinate.js").Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
* @param {number} rotation Rotation.
* @param {number} hitTolerance Hit tolerance in pixels.
* @param {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default, number): T} callback Feature callback.
* @param {Array<import("../../Feature.js").FeatureLike>} declutteredFeatures Decluttered features.
* @return {T|undefined} Callback result.
* @template T
*/
forEachFeatureAtCoordinate(coordinate, resolution, rotation, hitTolerance, callback, declutteredFeatures) {
hitTolerance = Math.round(hitTolerance);
const contextSize = hitTolerance * 2 + 1;
const transform = compose(
this.hitDetectionTransform_,
hitTolerance + 0.5,
hitTolerance + 0.5,
1 / resolution,
-1 / resolution,
-rotation,
-coordinate[0],
-coordinate[1]
);
const newContext = !this.hitDetectionContext_;
if (newContext) {
this.hitDetectionContext_ = createCanvasContext2D(
contextSize,
contextSize
);
}
const context = this.hitDetectionContext_;
if (context.canvas.width !== contextSize || context.canvas.height !== contextSize) {
context.canvas.width = contextSize;
context.canvas.height = contextSize;
} else if (!newContext) {
context.clearRect(0, 0, contextSize, contextSize);
}
let hitExtent;
if (this.renderBuffer_ !== void 0) {
hitExtent = createEmpty();
extendCoordinate(hitExtent, coordinate);
buffer(
hitExtent,
resolution * (this.renderBuffer_ + hitTolerance),
hitExtent
);
}
const indexes = getPixelIndexArray(hitTolerance);
let builderType;
function featureCallback(feature, geometry, declutterMode) {
const imageData = context.getImageData(
0,
0,
contextSize,
contextSize
).data;
for (let i2 = 0, ii = indexes.length; i2 < ii; i2++) {
if (imageData[indexes[i2]] > 0) {
if (!declutteredFeatures || declutterMode === "none" || builderType !== "Image" && builderType !== "Text" || declutteredFeatures.includes(feature)) {
const idx = (indexes[i2] - 3) / 4;
const x = hitTolerance - idx % contextSize;
const y = hitTolerance - (idx / contextSize | 0);
const result2 = callback(feature, geometry, x * x + y * y);
if (result2) {
return result2;
}
}
context.clearRect(0, 0, contextSize, contextSize);
break;
}
}
return void 0;
}
const zs = Object.keys(this.executorsByZIndex_).map(Number);
zs.sort(ascending);
let i, j, executors, executor, result;
for (i = zs.length - 1; i >= 0; --i) {
const zIndexKey = zs[i].toString();
executors = this.executorsByZIndex_[zIndexKey];
for (j = ALL.length - 1; j >= 0; --j) {
builderType = ALL[j];
executor = executors[builderType];
if (executor !== void 0) {
result = executor.executeHitDetection(
context,
transform,
rotation,
featureCallback,
hitExtent
);
if (result) {
return result;
}
}
}
}
return void 0;
}
/**
* @param {import("../../transform.js").Transform} transform Transform.
* @return {Array<number>|null} Clip coordinates.
*/
getClipCoords(transform) {
const maxExtent = this.maxExtent_;
if (!maxExtent) {
return null;
}
const minX = maxExtent[0];
const minY = maxExtent[1];
const maxX = maxExtent[2];
const maxY = maxExtent[3];
const flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
transform2D(flatClipCoords, 0, 8, 2, transform, flatClipCoords);
return flatClipCoords;
}
/**
* @return {boolean} Is empty.
*/
isEmpty() {
return isEmpty(this.executorsByZIndex_);
}
/**
* @param {CanvasRenderingContext2D} targetContext Context.
* @param {import('../../size.js').Size} scaledCanvasSize Scale of the context.
* @param {import("../../transform.js").Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {boolean} snapToPixel Snap point symbols and test to integer pixel.
* @param {Array<import("../canvas.js").BuilderType>} [builderTypes] Ordered replay types to replay.
* Default is {@link module:ol/render/replay~ALL}
* @param {import("rbush").default<import('./Executor.js').DeclutterEntry>|null} [declutterTree] Declutter tree.
* When set to null, no decluttering is done, even when the executor group has a `ZIndexContext`.
*/
execute(targetContext, scaledCanvasSize, transform, viewRotation, snapToPixel, builderTypes, declutterTree) {
const zs = Object.keys(this.executorsByZIndex_).map(Number);
zs.sort(declutterTree ? descending : ascending);
builderTypes = builderTypes ? builderTypes : ALL;
const maxBuilderTypes = ALL.length;
for (let i = 0, ii = zs.length; i < ii; ++i) {
const zIndexKey = zs[i].toString();
const replays = this.executorsByZIndex_[zIndexKey];
for (let j = 0, jj = builderTypes.length; j < jj; ++j) {
const builderType = builderTypes[j];
const replay = replays[builderType];
if (replay !== void 0) {
const zIndexContext = declutterTree === null ? void 0 : replay.getZIndexContext();
const context = zIndexContext ? zIndexContext.getContext() : targetContext;
const requireClip = this.maxExtent_ && builderType !== "Image" && builderType !== "Text";
if (requireClip) {
context.save();
this.clip(context, transform);
}
if (!zIndexContext || builderType === "Text" || builderType === "Image") {
replay.execute(
context,
scaledCanvasSize,
transform,
viewRotation,
snapToPixel,
declutterTree
);
} else {
zIndexContext.pushFunction(
(context2) => replay.execute(
context2,
scaledCanvasSize,
transform,
viewRotation,
snapToPixel,
declutterTree
)
);
}
if (requireClip) {
context.restore();
}
if (zIndexContext) {
zIndexContext.offset();
const index = zs[i] * maxBuilderTypes + ALL.indexOf(builderType);
if (!this.deferredZIndexContexts_[index]) {
this.deferredZIndexContexts_[index] = [];
}
this.deferredZIndexContexts_[index].push(zIndexContext);
}
}
}
}
this.renderedContext_ = targetContext;
}
getDeferredZIndexContexts() {
return this.deferredZIndexContexts_;
}
getRenderedContext() {
return this.renderedContext_;
}
renderDeferred() {
const deferredZIndexContexts = this.deferredZIndexContexts_;
const zs = Object.keys(deferredZIndexContexts).map(Number).sort(ascending);
for (let i = 0, ii = zs.length; i < ii; ++i) {
deferredZIndexContexts[zs[i]].forEach((zIndexContext) => {
zIndexContext.draw(this.renderedContext_);
zIndexContext.clear();
});
deferredZIndexContexts[zs[i]].length = 0;
}
}
};
var circlePixelIndexArrayCache = {};
function getPixelIndexArray(radius) {
if (circlePixelIndexArrayCache[radius] !== void 0) {
return circlePixelIndexArrayCache[radius];
}
const size = radius * 2 + 1;
const maxDistanceSq = radius * radius;
const distances = new Array(maxDistanceSq + 1);
for (let i = 0; i <= radius; ++i) {
for (let j = 0; j <= radius; ++j) {
const distanceSq = i * i + j * j;
if (distanceSq > maxDistanceSq) {
break;
}
let distance = distances[distanceSq];
if (!distance) {
distance = [];
distances[distanceSq] = distance;
}
distance.push(((radius + i) * size + (radius + j)) * 4 + 3);
if (i > 0) {
distance.push(((radius - i) * size + (radius + j)) * 4 + 3);
}
if (j > 0) {
distance.push(((radius + i) * size + (radius - j)) * 4 + 3);
if (i > 0) {
distance.push(((radius - i) * size + (radius - j)) * 4 + 3);
}
}
}
}
const pixelIndex = [];
for (let i = 0, ii = distances.length; i < ii; ++i) {
if (distances[i]) {
pixelIndex.push(...distances[i]);
}
}
circlePixelIndexArrayCache[radius] = pixelIndex;
return pixelIndex;
}
var ExecutorGroup_default = ExecutorGroup;
// node_modules/ol/render/canvas/Immediate.js
var CanvasImmediateRenderer = class extends VectorContext_default {
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {number} pixelRatio Pixel ratio.
* @param {import("../../extent.js").Extent} extent Extent.
* @param {import("../../transform.js").Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {number} [squaredTolerance] Optional squared tolerance for simplification.
* @param {import("../../proj.js").TransformFunction} [userTransform] Transform from user to view projection.
*/
constructor(context, pixelRatio, extent, transform, viewRotation, squaredTolerance, userTransform) {
super();
this.context_ = context;
this.pixelRatio_ = pixelRatio;
this.extent_ = extent;
this.transform_ = transform;
this.transformRotation_ = transform ? toFixed(Math.atan2(transform[1], transform[0]), 10) : 0;
this.viewRotation_ = viewRotation;
this.squaredTolerance_ = squaredTolerance;
this.userTransform_ = userTransform;
this.contextFillState_ = null;
this.contextStrokeState_ = null;
this.contextTextState_ = null;
this.fillState_ = null;
this.strokeState_ = null;
this.image_ = null;
this.imageAnchorX_ = 0;
this.imageAnchorY_ = 0;
this.imageHeight_ = 0;
this.imageOpacity_ = 0;
this.imageOriginX_ = 0;
this.imageOriginY_ = 0;
this.imageRotateWithView_ = false;
this.imageRotation_ = 0;
this.imageScale_ = [0, 0];
this.imageWidth_ = 0;
this.text_ = "";
this.textOffsetX_ = 0;
this.textOffsetY_ = 0;
this.textRotateWithView_ = false;
this.textRotation_ = 0;
this.textScale_ = [0, 0];
this.textFillState_ = null;
this.textStrokeState_ = null;
this.textState_ = null;
this.pixelCoordinates_ = [];
this.tmpLocalTransform_ = create();
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {number} end End.
* @param {number} stride Stride.
* @private
*/
drawImages_(flatCoordinates, offset, end, stride) {
if (!this.image_) {
return;
}
const pixelCoordinates = transform2D(
flatCoordinates,
offset,
end,
stride,
this.transform_,
this.pixelCoordinates_
);
const context = this.context_;
const localTransform = this.tmpLocalTransform_;
const alpha = context.globalAlpha;
if (this.imageOpacity_ != 1) {
context.globalAlpha = alpha * this.imageOpacity_;
}
let rotation = this.imageRotation_;
if (this.transformRotation_ === 0) {
rotation -= this.viewRotation_;
}
if (this.imageRotateWithView_) {
rotation += this.viewRotation_;
}
for (let i = 0, ii = pixelCoordinates.length; i < ii; i += 2) {
const x = pixelCoordinates[i] - this.imageAnchorX_;
const y = pixelCoordinates[i + 1] - this.imageAnchorY_;
if (rotation !== 0 || this.imageScale_[0] != 1 || this.imageScale_[1] != 1) {
const centerX = x + this.imageAnchorX_;
const centerY = y + this.imageAnchorY_;
compose(
localTransform,
centerX,
centerY,
1,
1,
rotation,
-centerX,
-centerY
);
context.save();
context.transform.apply(context, localTransform);
context.translate(centerX, centerY);
context.scale(this.imageScale_[0], this.imageScale_[1]);
context.drawImage(
this.image_,
this.imageOriginX_,
this.imageOriginY_,
this.imageWidth_,
this.imageHeight_,
-this.imageAnchorX_,
-this.imageAnchorY_,
this.imageWidth_,
this.imageHeight_
);
context.restore();
} else {
context.drawImage(
this.image_,
this.imageOriginX_,
this.imageOriginY_,
this.imageWidth_,
this.imageHeight_,
x,
y,
this.imageWidth_,
this.imageHeight_
);
}
}
if (this.imageOpacity_ != 1) {
context.globalAlpha = alpha;
}
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {number} end End.
* @param {number} stride Stride.
* @private
*/
drawText_(flatCoordinates, offset, end, stride) {
if (!this.textState_ || this.text_ === "") {
return;
}
if (this.textFillState_) {
this.setContextFillState_(this.textFillState_);
}
if (this.textStrokeState_) {
this.setContextStrokeState_(this.textStrokeState_);
}
this.setContextTextState_(this.textState_);
const pixelCoordinates = transform2D(
flatCoordinates,
offset,
end,
stride,
this.transform_,
this.pixelCoordinates_
);
const context = this.context_;
let rotation = this.textRotation_;
if (this.transformRotation_ === 0) {
rotation -= this.viewRotation_;
}
if (this.textRotateWithView_) {
rotation += this.viewRotation_;
}
for (; offset < end; offset += stride) {
const x = pixelCoordinates[offset] + this.textOffsetX_;
const y = pixelCoordinates[offset + 1] + this.textOffsetY_;
if (rotation !== 0 || this.textScale_[0] != 1 || this.textScale_[1] != 1) {
context.save();
context.translate(x - this.textOffsetX_, y - this.textOffsetY_);
context.rotate(rotation);
context.translate(this.textOffsetX_, this.textOffsetY_);
context.scale(this.textScale_[0], this.textScale_[1]);
if (this.textStrokeState_) {
context.strokeText(this.text_, 0, 0);
}
if (this.textFillState_) {
context.fillText(this.text_, 0, 0);
}
context.restore();
} else {
if (this.textStrokeState_) {
context.strokeText(this.text_, x, y);
}
if (this.textFillState_) {
context.fillText(this.text_, x, y);
}
}
}
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {number} end End.
* @param {number} stride Stride.
* @param {boolean} close Close.
* @private
* @return {number} end End.
*/
moveToLineTo_(flatCoordinates, offset, end, stride, close) {
const context = this.context_;
const pixelCoordinates = transform2D(
flatCoordinates,
offset,
end,
stride,
this.transform_,
this.pixelCoordinates_
);
context.moveTo(pixelCoordinates[0], pixelCoordinates[1]);
let length = pixelCoordinates.length;
if (close) {
length -= 2;
}
for (let i = 2; i < length; i += 2) {
context.lineTo(pixelCoordinates[i], pixelCoordinates[i + 1]);
}
if (close) {
context.closePath();
}
return end;
}
/**
* @param {Array<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {Array<number>} ends Ends.
* @param {number} stride Stride.
* @private
* @return {number} End.
*/
drawRings_(flatCoordinates, offset, ends, stride) {
for (let i = 0, ii = ends.length; i < ii; ++i) {
offset = this.moveToLineTo_(
flatCoordinates,
offset,
ends[i],
stride,
true
);
}
return offset;
}
/**
* Render a circle geometry into the canvas. Rendering is immediate and uses
* the current fill and stroke styles.
*
* @param {import("../../geom/Circle.js").default} geometry Circle geometry.
* @api
* @override
*/
drawCircle(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/Circle.js").default} */
geometry.simplifyTransformed(
this.squaredTolerance_,
this.userTransform_
);
}
if (!intersects(this.extent_, geometry.getExtent())) {
return;
}
if (this.fillState_ || this.strokeState_) {
if (this.fillState_) {
this.setContextFillState_(this.fillState_);
}
if (this.strokeState_) {
this.setContextStrokeState_(this.strokeState_);
}
const pixelCoordinates = transformGeom2D(
geometry,
this.transform_,
this.pixelCoordinates_
);
const dx = pixelCoordinates[2] - pixelCoordinates[0];
const dy = pixelCoordinates[3] - pixelCoordinates[1];
const radius = Math.sqrt(dx * dx + dy * dy);
const context = this.context_;
context.beginPath();
context.arc(
pixelCoordinates[0],
pixelCoordinates[1],
radius,
0,
2 * Math.PI
);
if (this.fillState_) {
context.fill();
}
if (this.strokeState_) {
context.stroke();
}
}
if (this.text_ !== "") {
this.drawText_(geometry.getCenter(), 0, 2, 2);
}
}
/**
* Set the rendering style. Note that since this is an immediate rendering API,
* any `zIndex` on the provided style will be ignored.
*
* @param {import("../../style/Style.js").default} style The rendering style.
* @api
* @override
*/
setStyle(style) {
this.setFillStrokeStyle(style.getFill(), style.getStroke());
this.setImageStyle(style.getImage());
this.setTextStyle(style.getText());
}
/**
* @param {import("../../transform.js").Transform} transform Transform.
*/
setTransform(transform) {
this.transform_ = transform;
}
/**
* Render a geometry into the canvas. Call
* {@link module:ol/render/canvas/Immediate~CanvasImmediateRenderer#setStyle renderer.setStyle()} first to set the rendering style.
*
* @param {import("../../geom/Geometry.js").default|import("../Feature.js").default} geometry The geometry to render.
* @api
* @override
*/
drawGeometry(geometry) {
const type = geometry.getType();
switch (type) {
case "Point":
this.drawPoint(
/** @type {import("../../geom/Point.js").default} */
geometry
);
break;
case "LineString":
this.drawLineString(
/** @type {import("../../geom/LineString.js").default} */
geometry
);
break;
case "Polygon":
this.drawPolygon(
/** @type {import("../../geom/Polygon.js").default} */
geometry
);
break;
case "MultiPoint":
this.drawMultiPoint(
/** @type {import("../../geom/MultiPoint.js").default} */
geometry
);
break;
case "MultiLineString":
this.drawMultiLineString(
/** @type {import("../../geom/MultiLineString.js").default} */
geometry
);
break;
case "MultiPolygon":
this.drawMultiPolygon(
/** @type {import("../../geom/MultiPolygon.js").default} */
geometry
);
break;
case "GeometryCollection":
this.drawGeometryCollection(
/** @type {import("../../geom/GeometryCollection.js").default} */
geometry
);
break;
case "Circle":
this.drawCircle(
/** @type {import("../../geom/Circle.js").default} */
geometry
);
break;
default:
}
}
/**
* Render a feature into the canvas. Note that any `zIndex` on the provided
* style will be ignored - features are rendered immediately in the order that
* this method is called. If you need `zIndex` support, you should be using an
* {@link module:ol/layer/Vector~VectorLayer} instead.
*
* @param {import("../../Feature.js").default} feature Feature.
* @param {import("../../style/Style.js").default} style Style.
* @api
* @override
*/
drawFeature(feature, style) {
const geometry = style.getGeometryFunction()(feature);
if (!geometry) {
return;
}
this.setStyle(style);
this.drawGeometry(geometry);
}
/**
* Render a GeometryCollection to the canvas. Rendering is immediate and
* uses the current styles appropriate for each geometry in the collection.
*
* @param {import("../../geom/GeometryCollection.js").default} geometry Geometry collection.
* @override
*/
drawGeometryCollection(geometry) {
const geometries = geometry.getGeometriesArray();
for (let i = 0, ii = geometries.length; i < ii; ++i) {
this.drawGeometry(geometries[i]);
}
}
/**
* Render a Point geometry into the canvas. Rendering is immediate and uses
* the current style.
*
* @param {import("../../geom/Point.js").default|import("../Feature.js").default} geometry Point geometry.
* @override
*/
drawPoint(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/Point.js").default} */
geometry.simplifyTransformed(
this.squaredTolerance_,
this.userTransform_
);
}
const flatCoordinates = geometry.getFlatCoordinates();
const stride = geometry.getStride();
if (this.image_) {
this.drawImages_(flatCoordinates, 0, flatCoordinates.length, stride);
}
if (this.text_ !== "") {
this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride);
}
}
/**
* Render a MultiPoint geometry into the canvas. Rendering is immediate and
* uses the current style.
*
* @param {import("../../geom/MultiPoint.js").default|import("../Feature.js").default} geometry MultiPoint geometry.
* @override
*/
drawMultiPoint(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/MultiPoint.js").default} */
geometry.simplifyTransformed(
this.squaredTolerance_,
this.userTransform_
);
}
const flatCoordinates = geometry.getFlatCoordinates();
const stride = geometry.getStride();
if (this.image_) {
this.drawImages_(flatCoordinates, 0, flatCoordinates.length, stride);
}
if (this.text_ !== "") {
this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride);
}
}
/**
* Render a LineString into the canvas. Rendering is immediate and uses
* the current style.
*
* @param {import("../../geom/LineString.js").default|import("../Feature.js").default} geometry LineString geometry.
* @override
*/
drawLineString(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/LineString.js").default} */
geometry.simplifyTransformed(
this.squaredTolerance_,
this.userTransform_
);
}
if (!intersects(this.extent_, geometry.getExtent())) {
return;
}
if (this.strokeState_) {
this.setContextStrokeState_(this.strokeState_);
const context = this.context_;
const flatCoordinates = geometry.getFlatCoordinates();
context.beginPath();
this.moveToLineTo_(
flatCoordinates,
0,
flatCoordinates.length,
geometry.getStride(),
false
);
context.stroke();
}
if (this.text_ !== "") {
const flatMidpoint = geometry.getFlatMidpoint();
this.drawText_(flatMidpoint, 0, 2, 2);
}
}
/**
* Render a MultiLineString geometry into the canvas. Rendering is immediate
* and uses the current style.
*
* @param {import("../../geom/MultiLineString.js").default|import("../Feature.js").default} geometry MultiLineString geometry.
* @override
*/
drawMultiLineString(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/MultiLineString.js").default} */
geometry.simplifyTransformed(
this.squaredTolerance_,
this.userTransform_
);
}
const geometryExtent = geometry.getExtent();
if (!intersects(this.extent_, geometryExtent)) {
return;
}
if (this.strokeState_) {
this.setContextStrokeState_(this.strokeState_);
const context = this.context_;
const flatCoordinates = geometry.getFlatCoordinates();
let offset = 0;
const ends = (
/** @type {Array<number>} */
geometry.getEnds()
);
const stride = geometry.getStride();
context.beginPath();
for (let i = 0, ii = ends.length; i < ii; ++i) {
offset = this.moveToLineTo_(
flatCoordinates,
offset,
ends[i],
stride,
false
);
}
context.stroke();
}
if (this.text_ !== "") {
const flatMidpoints = geometry.getFlatMidpoints();
this.drawText_(flatMidpoints, 0, flatMidpoints.length, 2);
}
}
/**
* Render a Polygon geometry into the canvas. Rendering is immediate and uses
* the current style.
*
* @param {import("../../geom/Polygon.js").default|import("../Feature.js").default} geometry Polygon geometry.
* @override
*/
drawPolygon(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/Polygon.js").default} */
geometry.simplifyTransformed(
this.squaredTolerance_,
this.userTransform_
);
}
if (!intersects(this.extent_, geometry.getExtent())) {
return;
}
if (this.strokeState_ || this.fillState_) {
if (this.fillState_) {
this.setContextFillState_(this.fillState_);
}
if (this.strokeState_) {
this.setContextStrokeState_(this.strokeState_);
}
const context = this.context_;
context.beginPath();
this.drawRings_(
geometry.getOrientedFlatCoordinates(),
0,
/** @type {Array<number>} */
geometry.getEnds(),
geometry.getStride()
);
if (this.fillState_) {
context.fill();
}
if (this.strokeState_) {
context.stroke();
}
}
if (this.text_ !== "") {
const flatInteriorPoint = geometry.getFlatInteriorPoint();
this.drawText_(flatInteriorPoint, 0, 2, 2);
}
}
/**
* Render MultiPolygon geometry into the canvas. Rendering is immediate and
* uses the current style.
* @param {import("../../geom/MultiPolygon.js").default} geometry MultiPolygon geometry.
* @override
*/
drawMultiPolygon(geometry) {
if (this.squaredTolerance_) {
geometry = /** @type {import("../../geom/MultiPolygon.js").default} */
geometry.simplifyTransformed(
this.squaredTolerance_,
this.userTransform_
);
}
if (!intersects(this.extent_, geometry.getExtent())) {
return;
}
if (this.strokeState_ || this.fillState_) {
if (this.fillState_) {
this.setContextFillState_(this.fillState_);
}
if (this.strokeState_) {
this.setContextStrokeState_(this.strokeState_);
}
const context = this.context_;
const flatCoordinates = geometry.getOrientedFlatCoordinates();
let offset = 0;
const endss = geometry.getEndss();
const stride = geometry.getStride();
context.beginPath();
for (let i = 0, ii = endss.length; i < ii; ++i) {
const ends = endss[i];
offset = this.drawRings_(flatCoordinates, offset, ends, stride);
}
if (this.fillState_) {
context.fill();
}
if (this.strokeState_) {
context.stroke();
}
}
if (this.text_ !== "") {
const flatInteriorPoints = geometry.getFlatInteriorPoints();
this.drawText_(flatInteriorPoints, 0, flatInteriorPoints.length, 2);
}
}
/**
* @param {import("../canvas.js").FillState} fillState Fill state.
* @private
*/
setContextFillState_(fillState) {
const context = this.context_;
const contextFillState = this.contextFillState_;
if (!contextFillState) {
context.fillStyle = fillState.fillStyle;
this.contextFillState_ = {
fillStyle: fillState.fillStyle
};
} else {
if (contextFillState.fillStyle != fillState.fillStyle) {
contextFillState.fillStyle = fillState.fillStyle;
context.fillStyle = fillState.fillStyle;
}
}
}
/**
* @param {import("../canvas.js").StrokeState} strokeState Stroke state.
* @private
*/
setContextStrokeState_(strokeState) {
const context = this.context_;
const contextStrokeState = this.contextStrokeState_;
if (!contextStrokeState) {
context.lineCap = strokeState.lineCap;
context.setLineDash(strokeState.lineDash);
context.lineDashOffset = strokeState.lineDashOffset;
context.lineJoin = strokeState.lineJoin;
context.lineWidth = strokeState.lineWidth;
context.miterLimit = strokeState.miterLimit;
context.strokeStyle = strokeState.strokeStyle;
this.contextStrokeState_ = {
lineCap: strokeState.lineCap,
lineDash: strokeState.lineDash,
lineDashOffset: strokeState.lineDashOffset,
lineJoin: strokeState.lineJoin,
lineWidth: strokeState.lineWidth,
miterLimit: strokeState.miterLimit,
strokeStyle: strokeState.strokeStyle
};
} else {
if (contextStrokeState.lineCap != strokeState.lineCap) {
contextStrokeState.lineCap = strokeState.lineCap;
context.lineCap = strokeState.lineCap;
}
if (!equals(contextStrokeState.lineDash, strokeState.lineDash)) {
context.setLineDash(
contextStrokeState.lineDash = strokeState.lineDash
);
}
if (contextStrokeState.lineDashOffset != strokeState.lineDashOffset) {
contextStrokeState.lineDashOffset = strokeState.lineDashOffset;
context.lineDashOffset = strokeState.lineDashOffset;
}
if (contextStrokeState.lineJoin != strokeState.lineJoin) {
contextStrokeState.lineJoin = strokeState.lineJoin;
context.lineJoin = strokeState.lineJoin;
}
if (contextStrokeState.lineWidth != strokeState.lineWidth) {
contextStrokeState.lineWidth = strokeState.lineWidth;
context.lineWidth = strokeState.lineWidth;
}
if (contextStrokeState.miterLimit != strokeState.miterLimit) {
contextStrokeState.miterLimit = strokeState.miterLimit;
context.miterLimit = strokeState.miterLimit;
}
if (contextStrokeState.strokeStyle != strokeState.strokeStyle) {
contextStrokeState.strokeStyle = strokeState.strokeStyle;
context.strokeStyle = strokeState.strokeStyle;
}
}
}
/**
* @param {import("../canvas.js").TextState} textState Text state.
* @private
*/
setContextTextState_(textState) {
const context = this.context_;
const contextTextState = this.contextTextState_;
const textAlign = textState.textAlign ? textState.textAlign : defaultTextAlign;
if (!contextTextState) {
context.font = textState.font;
context.textAlign = textAlign;
context.textBaseline = textState.textBaseline;
this.contextTextState_ = {
font: textState.font,
textAlign,
textBaseline: textState.textBaseline
};
} else {
if (contextTextState.font != textState.font) {
contextTextState.font = textState.font;
context.font = textState.font;
}
if (contextTextState.textAlign != textAlign) {
contextTextState.textAlign = textAlign;
context.textAlign = textAlign;
}
if (contextTextState.textBaseline != textState.textBaseline) {
contextTextState.textBaseline = textState.textBaseline;
context.textBaseline = textState.textBaseline;
}
}
}
/**
* Set the fill and stroke style for subsequent draw operations. To clear
* either fill or stroke styles, pass null for the appropriate parameter.
*
* @param {import("../../style/Fill.js").default} fillStyle Fill style.
* @param {import("../../style/Stroke.js").default} strokeStyle Stroke style.
* @override
*/
setFillStrokeStyle(fillStyle, strokeStyle) {
if (!fillStyle) {
this.fillState_ = null;
} else {
const fillStyleColor = fillStyle.getColor();
this.fillState_ = {
fillStyle: asColorLike(
fillStyleColor ? fillStyleColor : defaultFillStyle
)
};
}
if (!strokeStyle) {
this.strokeState_ = null;
} else {
const strokeStyleColor = strokeStyle.getColor();
const strokeStyleLineCap = strokeStyle.getLineCap();
const strokeStyleLineDash = strokeStyle.getLineDash();
const strokeStyleLineDashOffset = strokeStyle.getLineDashOffset();
const strokeStyleLineJoin = strokeStyle.getLineJoin();
const strokeStyleWidth = strokeStyle.getWidth();
const strokeStyleMiterLimit = strokeStyle.getMiterLimit();
const lineDash = strokeStyleLineDash ? strokeStyleLineDash : defaultLineDash;
this.strokeState_ = {
lineCap: strokeStyleLineCap !== void 0 ? strokeStyleLineCap : defaultLineCap,
lineDash: this.pixelRatio_ === 1 ? lineDash : lineDash.map((n) => n * this.pixelRatio_),
lineDashOffset: (strokeStyleLineDashOffset ? strokeStyleLineDashOffset : defaultLineDashOffset) * this.pixelRatio_,
lineJoin: strokeStyleLineJoin !== void 0 ? strokeStyleLineJoin : defaultLineJoin,
lineWidth: (strokeStyleWidth !== void 0 ? strokeStyleWidth : defaultLineWidth) * this.pixelRatio_,
miterLimit: strokeStyleMiterLimit !== void 0 ? strokeStyleMiterLimit : defaultMiterLimit,
strokeStyle: asColorLike(
strokeStyleColor ? strokeStyleColor : defaultStrokeStyle
)
};
}
}
/**
* Set the image style for subsequent draw operations. Pass null to remove
* the image style.
*
* @param {import("../../style/Image.js").default} imageStyle Image style.
* @override
*/
setImageStyle(imageStyle) {
let imageSize;
if (!imageStyle || !(imageSize = imageStyle.getSize())) {
this.image_ = null;
return;
}
const imagePixelRatio = imageStyle.getPixelRatio(this.pixelRatio_);
const imageAnchor = imageStyle.getAnchor();
const imageOrigin = imageStyle.getOrigin();
this.image_ = imageStyle.getImage(this.pixelRatio_);
this.imageAnchorX_ = imageAnchor[0] * imagePixelRatio;
this.imageAnchorY_ = imageAnchor[1] * imagePixelRatio;
this.imageHeight_ = imageSize[1] * imagePixelRatio;
this.imageOpacity_ = imageStyle.getOpacity();
this.imageOriginX_ = imageOrigin[0];
this.imageOriginY_ = imageOrigin[1];
this.imageRotateWithView_ = imageStyle.getRotateWithView();
this.imageRotation_ = imageStyle.getRotation();
const imageScale = imageStyle.getScaleArray();
this.imageScale_ = [
imageScale[0] * this.pixelRatio_ / imagePixelRatio,
imageScale[1] * this.pixelRatio_ / imagePixelRatio
];
this.imageWidth_ = imageSize[0] * imagePixelRatio;
}
/**
* Set the text style for subsequent draw operations. Pass null to
* remove the text style.
*
* @param {import("../../style/Text.js").default} textStyle Text style.
* @override
*/
setTextStyle(textStyle) {
if (!textStyle) {
this.text_ = "";
} else {
const textFillStyle = textStyle.getFill();
if (!textFillStyle) {
this.textFillState_ = null;
} else {
const textFillStyleColor = textFillStyle.getColor();
this.textFillState_ = {
fillStyle: asColorLike(
textFillStyleColor ? textFillStyleColor : defaultFillStyle
)
};
}
const textStrokeStyle = textStyle.getStroke();
if (!textStrokeStyle) {
this.textStrokeState_ = null;
} else {
const textStrokeStyleColor = textStrokeStyle.getColor();
const textStrokeStyleLineCap = textStrokeStyle.getLineCap();
const textStrokeStyleLineDash = textStrokeStyle.getLineDash();
const textStrokeStyleLineDashOffset = textStrokeStyle.getLineDashOffset();
const textStrokeStyleLineJoin = textStrokeStyle.getLineJoin();
const textStrokeStyleWidth = textStrokeStyle.getWidth();
const textStrokeStyleMiterLimit = textStrokeStyle.getMiterLimit();
this.textStrokeState_ = {
lineCap: textStrokeStyleLineCap !== void 0 ? textStrokeStyleLineCap : defaultLineCap,
lineDash: textStrokeStyleLineDash ? textStrokeStyleLineDash : defaultLineDash,
lineDashOffset: textStrokeStyleLineDashOffset ? textStrokeStyleLineDashOffset : defaultLineDashOffset,
lineJoin: textStrokeStyleLineJoin !== void 0 ? textStrokeStyleLineJoin : defaultLineJoin,
lineWidth: textStrokeStyleWidth !== void 0 ? textStrokeStyleWidth : defaultLineWidth,
miterLimit: textStrokeStyleMiterLimit !== void 0 ? textStrokeStyleMiterLimit : defaultMiterLimit,
strokeStyle: asColorLike(
textStrokeStyleColor ? textStrokeStyleColor : defaultStrokeStyle
)
};
}
const textFont = textStyle.getFont();
const textOffsetX = textStyle.getOffsetX();
const textOffsetY = textStyle.getOffsetY();
const textRotateWithView = textStyle.getRotateWithView();
const textRotation = textStyle.getRotation();
const textScale = textStyle.getScaleArray();
const textText = textStyle.getText();
const textTextAlign = textStyle.getTextAlign();
const textTextBaseline = textStyle.getTextBaseline();
this.textState_ = {
font: textFont !== void 0 ? textFont : defaultFont,
textAlign: textTextAlign !== void 0 ? textTextAlign : defaultTextAlign,
textBaseline: textTextBaseline !== void 0 ? textTextBaseline : defaultTextBaseline
};
this.text_ = textText !== void 0 ? Array.isArray(textText) ? textText.reduce((acc, t, i) => acc += i % 2 ? " " : t, "") : textText : "";
this.textOffsetX_ = textOffsetX !== void 0 ? this.pixelRatio_ * textOffsetX : 0;
this.textOffsetY_ = textOffsetY !== void 0 ? this.pixelRatio_ * textOffsetY : 0;
this.textRotateWithView_ = textRotateWithView !== void 0 ? textRotateWithView : false;
this.textRotation_ = textRotation !== void 0 ? textRotation : 0;
this.textScale_ = [
this.pixelRatio_ * textScale[0],
this.pixelRatio_ * textScale[1]
];
}
}
};
var Immediate_default = CanvasImmediateRenderer;
// node_modules/ol/render/canvas/hitdetect.js
var HIT_DETECT_RESOLUTION = 0.5;
function createHitDetectionImageData(size, transforms, features, styleFunction, extent, resolution, rotation, squaredTolerance, projection) {
const userExtent = projection ? toUserExtent(extent, projection) : extent;
const width = size[0] * HIT_DETECT_RESOLUTION;
const height = size[1] * HIT_DETECT_RESOLUTION;
const context = createCanvasContext2D(width, height);
context.imageSmoothingEnabled = false;
const canvas = context.canvas;
const renderer = new Immediate_default(
context,
HIT_DETECT_RESOLUTION,
extent,
null,
rotation,
squaredTolerance,
projection ? getTransformFromProjections(getUserProjection(), projection) : null
);
const featureCount = features.length;
const indexFactor = Math.floor((256 * 256 * 256 - 1) / featureCount);
const featuresByZIndex = {};
for (let i = 1; i <= featureCount; ++i) {
const feature = features[i - 1];
const featureStyleFunction = feature.getStyleFunction() || styleFunction;
if (!featureStyleFunction) {
continue;
}
let styles = featureStyleFunction(feature, resolution);
if (!styles) {
continue;
}
if (!Array.isArray(styles)) {
styles = [styles];
}
const index = i * indexFactor;
const color = index.toString(16).padStart(7, "#00000");
for (let j = 0, jj = styles.length; j < jj; ++j) {
const originalStyle = styles[j];
const geometry = originalStyle.getGeometryFunction()(feature);
if (!geometry || !intersects(userExtent, geometry.getExtent())) {
continue;
}
const style = originalStyle.clone();
const fill = style.getFill();
if (fill) {
fill.setColor(color);
}
const stroke = style.getStroke();
if (stroke) {
stroke.setColor(color);
stroke.setLineDash(null);
}
style.setText(void 0);
const image = originalStyle.getImage();
if (image) {
const imgSize = image.getImageSize();
if (!imgSize) {
continue;
}
const imgContext = createCanvasContext2D(
imgSize[0],
imgSize[1],
void 0,
{ alpha: false }
);
const img = imgContext.canvas;
imgContext.fillStyle = color;
imgContext.fillRect(0, 0, img.width, img.height);
style.setImage(
new Icon_default({
img,
anchor: image.getAnchor(),
anchorXUnits: "pixels",
anchorYUnits: "pixels",
offset: image.getOrigin(),
opacity: 1,
size: image.getSize(),
scale: image.getScale(),
rotation: image.getRotation(),
rotateWithView: image.getRotateWithView()
})
);
}
const zIndex = style.getZIndex() || 0;
let byGeometryType = featuresByZIndex[zIndex];
if (!byGeometryType) {
byGeometryType = {};
featuresByZIndex[zIndex] = byGeometryType;
byGeometryType["Polygon"] = [];
byGeometryType["Circle"] = [];
byGeometryType["LineString"] = [];
byGeometryType["Point"] = [];
}
const type = geometry.getType();
if (type === "GeometryCollection") {
const geometries = (
/** @type {import("../../geom/GeometryCollection.js").default} */
geometry.getGeometriesArrayRecursive()
);
for (let i2 = 0, ii = geometries.length; i2 < ii; ++i2) {
const geometry2 = geometries[i2];
byGeometryType[geometry2.getType().replace("Multi", "")].push(
geometry2,
style
);
}
} else {
byGeometryType[type.replace("Multi", "")].push(geometry, style);
}
}
}
const zIndexKeys = Object.keys(featuresByZIndex).map(Number).sort(ascending);
for (let i = 0, ii = zIndexKeys.length; i < ii; ++i) {
const byGeometryType = featuresByZIndex[zIndexKeys[i]];
for (const type in byGeometryType) {
const geomAndStyle = byGeometryType[type];
for (let j = 0, jj = geomAndStyle.length; j < jj; j += 2) {
renderer.setStyle(geomAndStyle[j + 1]);
for (let k = 0, kk = transforms.length; k < kk; ++k) {
renderer.setTransform(transforms[k]);
renderer.drawGeometry(geomAndStyle[j]);
}
}
}
}
return context.getImageData(0, 0, canvas.width, canvas.height);
}
function hitDetect(pixel, features, imageData) {
const resultFeatures = [];
if (imageData) {
const x = Math.floor(Math.round(pixel[0]) * HIT_DETECT_RESOLUTION);
const y = Math.floor(Math.round(pixel[1]) * HIT_DETECT_RESOLUTION);
const index = (clamp(x, 0, imageData.width - 1) + clamp(y, 0, imageData.height - 1) * imageData.width) * 4;
const r = imageData.data[index];
const g = imageData.data[index + 1];
const b = imageData.data[index + 2];
const i = b + 256 * (g + 256 * r);
const indexFactor = Math.floor((256 * 256 * 256 - 1) / features.length);
if (i && i % indexFactor === 0) {
resultFeatures.push(features[i / indexFactor - 1]);
}
}
return resultFeatures;
}
// node_modules/ol/renderer/vector.js
var SIMPLIFY_TOLERANCE = 0.5;
var GEOMETRY_RENDERERS = {
"Point": renderPointGeometry,
"LineString": renderLineStringGeometry,
"Polygon": renderPolygonGeometry,
"MultiPoint": renderMultiPointGeometry,
"MultiLineString": renderMultiLineStringGeometry,
"MultiPolygon": renderMultiPolygonGeometry,
"GeometryCollection": renderGeometryCollectionGeometry,
"Circle": renderCircleGeometry
};
function defaultOrder(feature1, feature2) {
return parseInt(getUid(feature1), 10) - parseInt(getUid(feature2), 10);
}
function getSquaredTolerance(resolution, pixelRatio) {
const tolerance = getTolerance(resolution, pixelRatio);
return tolerance * tolerance;
}
function getTolerance(resolution, pixelRatio) {
return SIMPLIFY_TOLERANCE * resolution / pixelRatio;
}
function renderCircleGeometry(builderGroup, geometry, style, feature, index) {
const fillStyle = style.getFill();
const strokeStyle = style.getStroke();
if (fillStyle || strokeStyle) {
const circleReplay = builderGroup.getBuilder(style.getZIndex(), "Circle");
circleReplay.setFillStrokeStyle(fillStyle, strokeStyle);
circleReplay.drawCircle(geometry, feature, index);
}
const textStyle = style.getText();
if (textStyle && textStyle.getText()) {
const textReplay = builderGroup.getBuilder(style.getZIndex(), "Text");
textReplay.setTextStyle(textStyle);
textReplay.drawText(geometry, feature);
}
}
function renderFeature(replayGroup, feature, style, squaredTolerance, listener, transform, declutter, index) {
const loadingPromises = [];
const imageStyle = style.getImage();
if (imageStyle) {
let loading2 = true;
const imageState = imageStyle.getImageState();
if (imageState == ImageState_default.LOADED || imageState == ImageState_default.ERROR) {
loading2 = false;
} else {
if (imageState == ImageState_default.IDLE) {
imageStyle.load();
}
}
if (loading2) {
loadingPromises.push(imageStyle.ready());
}
}
const fillStyle = style.getFill();
if (fillStyle && fillStyle.loading()) {
loadingPromises.push(fillStyle.ready());
}
const loading = loadingPromises.length > 0;
if (loading) {
Promise.all(loadingPromises).then(() => listener(null));
}
renderFeatureInternal(
replayGroup,
feature,
style,
squaredTolerance,
transform,
declutter,
index
);
return loading;
}
function renderFeatureInternal(replayGroup, feature, style, squaredTolerance, transform, declutter, index) {
const geometry = style.getGeometryFunction()(feature);
if (!geometry) {
return;
}
const simplifiedGeometry = geometry.simplifyTransformed(
squaredTolerance,
transform
);
const renderer = style.getRenderer();
if (renderer) {
renderGeometry(replayGroup, simplifiedGeometry, style, feature, index);
} else {
const geometryRenderer = GEOMETRY_RENDERERS[simplifiedGeometry.getType()];
geometryRenderer(
replayGroup,
simplifiedGeometry,
style,
feature,
index,
declutter
);
}
}
function renderGeometry(replayGroup, geometry, style, feature, index) {
if (geometry.getType() == "GeometryCollection") {
const geometries = (
/** @type {import("../geom/GeometryCollection.js").default} */
geometry.getGeometries()
);
for (let i = 0, ii = geometries.length; i < ii; ++i) {
renderGeometry(replayGroup, geometries[i], style, feature, index);
}
return;
}
const replay = replayGroup.getBuilder(style.getZIndex(), "Default");
replay.drawCustom(
/** @type {import("../geom/SimpleGeometry.js").default} */
geometry,
feature,
style.getRenderer(),
style.getHitDetectionRenderer(),
index
);
}
function renderGeometryCollectionGeometry(replayGroup, geometry, style, feature, declutterBuilderGroup, index) {
const geometries = geometry.getGeometriesArray();
let i, ii;
for (i = 0, ii = geometries.length; i < ii; ++i) {
const geometryRenderer = GEOMETRY_RENDERERS[geometries[i].getType()];
geometryRenderer(
replayGroup,
geometries[i],
style,
feature,
declutterBuilderGroup,
index
);
}
}
function renderLineStringGeometry(builderGroup, geometry, style, feature, index) {
const strokeStyle = style.getStroke();
if (strokeStyle) {
const lineStringReplay = builderGroup.getBuilder(
style.getZIndex(),
"LineString"
);
lineStringReplay.setFillStrokeStyle(null, strokeStyle);
lineStringReplay.drawLineString(geometry, feature, index);
}
const textStyle = style.getText();
if (textStyle && textStyle.getText()) {
const textReplay = builderGroup.getBuilder(style.getZIndex(), "Text");
textReplay.setTextStyle(textStyle);
textReplay.drawText(geometry, feature, index);
}
}
function renderMultiLineStringGeometry(builderGroup, geometry, style, feature, index) {
const strokeStyle = style.getStroke();
if (strokeStyle) {
const lineStringReplay = builderGroup.getBuilder(
style.getZIndex(),
"LineString"
);
lineStringReplay.setFillStrokeStyle(null, strokeStyle);
lineStringReplay.drawMultiLineString(geometry, feature, index);
}
const textStyle = style.getText();
if (textStyle && textStyle.getText()) {
const textReplay = builderGroup.getBuilder(style.getZIndex(), "Text");
textReplay.setTextStyle(textStyle);
textReplay.drawText(geometry, feature, index);
}
}
function renderMultiPolygonGeometry(builderGroup, geometry, style, feature, index) {
const fillStyle = style.getFill();
const strokeStyle = style.getStroke();
if (strokeStyle || fillStyle) {
const polygonReplay = builderGroup.getBuilder(style.getZIndex(), "Polygon");
polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
polygonReplay.drawMultiPolygon(geometry, feature, index);
}
const textStyle = style.getText();
if (textStyle && textStyle.getText()) {
const textReplay = builderGroup.getBuilder(style.getZIndex(), "Text");
textReplay.setTextStyle(textStyle);
textReplay.drawText(geometry, feature, index);
}
}
function renderPointGeometry(builderGroup, geometry, style, feature, index, declutter) {
const imageStyle = style.getImage();
const textStyle = style.getText();
const hasText = textStyle && textStyle.getText();
const declutterImageWithText = declutter && imageStyle && hasText ? {} : void 0;
if (imageStyle) {
if (imageStyle.getImageState() != ImageState_default.LOADED) {
return;
}
const imageReplay = builderGroup.getBuilder(style.getZIndex(), "Image");
imageReplay.setImageStyle(imageStyle, declutterImageWithText);
imageReplay.drawPoint(geometry, feature, index);
}
if (hasText) {
const textReplay = builderGroup.getBuilder(style.getZIndex(), "Text");
textReplay.setTextStyle(textStyle, declutterImageWithText);
textReplay.drawText(geometry, feature, index);
}
}
function renderMultiPointGeometry(builderGroup, geometry, style, feature, index, declutter) {
const imageStyle = style.getImage();
const hasImage = imageStyle && imageStyle.getOpacity() !== 0;
const textStyle = style.getText();
const hasText = textStyle && textStyle.getText();
const declutterImageWithText = declutter && hasImage && hasText ? {} : void 0;
if (hasImage) {
if (imageStyle.getImageState() != ImageState_default.LOADED) {
return;
}
const imageReplay = builderGroup.getBuilder(style.getZIndex(), "Image");
imageReplay.setImageStyle(imageStyle, declutterImageWithText);
imageReplay.drawMultiPoint(geometry, feature, index);
}
if (hasText) {
const textReplay = builderGroup.getBuilder(style.getZIndex(), "Text");
textReplay.setTextStyle(textStyle, declutterImageWithText);
textReplay.drawText(geometry, feature, index);
}
}
function renderPolygonGeometry(builderGroup, geometry, style, feature, index) {
const fillStyle = style.getFill();
const strokeStyle = style.getStroke();
if (fillStyle || strokeStyle) {
const polygonReplay = builderGroup.getBuilder(style.getZIndex(), "Polygon");
polygonReplay.setFillStrokeStyle(fillStyle, strokeStyle);
polygonReplay.drawPolygon(geometry, feature, index);
}
const textStyle = style.getText();
if (textStyle && textStyle.getText()) {
const textReplay = builderGroup.getBuilder(style.getZIndex(), "Text");
textReplay.setTextStyle(textStyle);
textReplay.drawText(geometry, feature, index);
}
}
// node_modules/ol/renderer/canvas/VectorLayer.js
var CanvasVectorLayerRenderer = class extends Layer_default {
/**
* @param {import("../../layer/BaseVector.js").default} vectorLayer Vector layer.
*/
constructor(vectorLayer) {
super(vectorLayer);
this.boundHandleStyleImageChange_ = this.handleStyleImageChange_.bind(this);
this.animatingOrInteracting_;
this.hitDetectionImageData_ = null;
this.clipped_ = false;
this.renderedFeatures_ = null;
this.renderedRevision_ = -1;
this.renderedResolution_ = NaN;
this.renderedExtent_ = createEmpty();
this.wrappedRenderedExtent_ = createEmpty();
this.renderedRotation_;
this.renderedCenter_ = null;
this.renderedProjection_ = null;
this.renderedPixelRatio_ = 1;
this.renderedRenderOrder_ = null;
this.renderedFrameDeclutter_;
this.replayGroup_ = null;
this.replayGroupChanged = true;
this.clipping = true;
this.targetContext_ = null;
this.opacity_ = 1;
}
/**
* @param {ExecutorGroup} executorGroup Executor group.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @param {boolean} [declutterable] `true` to only render declutterable items,
* `false` to only render non-declutterable items, `undefined` to render all.
*/
renderWorlds(executorGroup, frameState, declutterable) {
const extent = frameState.extent;
const viewState = frameState.viewState;
const center = viewState.center;
const resolution = viewState.resolution;
const projection = viewState.projection;
const rotation = viewState.rotation;
const projectionExtent = projection.getExtent();
const vectorSource = this.getLayer().getSource();
const declutter = this.getLayer().getDeclutter();
const pixelRatio = frameState.pixelRatio;
const viewHints = frameState.viewHints;
const snapToPixel = !(viewHints[ViewHint_default.ANIMATING] || viewHints[ViewHint_default.INTERACTING]);
const context = this.context;
const width = Math.round(getWidth(extent) / resolution * pixelRatio);
const height = Math.round(getHeight(extent) / resolution * pixelRatio);
const multiWorld = vectorSource.getWrapX() && projection.canWrapX();
const worldWidth = multiWorld ? getWidth(projectionExtent) : null;
const endWorld = multiWorld ? Math.ceil((extent[2] - projectionExtent[2]) / worldWidth) + 1 : 1;
let world = multiWorld ? Math.floor((extent[0] - projectionExtent[0]) / worldWidth) : 0;
do {
let transform = this.getRenderTransform(
center,
resolution,
0,
pixelRatio,
width,
height,
world * worldWidth
);
if (frameState.declutter) {
transform = transform.slice(0);
}
executorGroup.execute(
context,
[context.canvas.width, context.canvas.height],
transform,
rotation,
snapToPixel,
declutterable === void 0 ? ALL : declutterable ? DECLUTTER : NON_DECLUTTER,
declutterable ? declutter && frameState.declutter[declutter] : void 0
);
} while (++world < endWorld);
}
/**
* @private
*/
setDrawContext_() {
if (this.opacity_ !== 1) {
this.targetContext_ = this.context;
this.context = createCanvasContext2D(
this.context.canvas.width,
this.context.canvas.height,
canvasPool
);
}
}
/**
* @private
*/
resetDrawContext_() {
if (this.opacity_ !== 1 && this.targetContext_) {
const alpha = this.targetContext_.globalAlpha;
this.targetContext_.globalAlpha = this.opacity_;
this.targetContext_.drawImage(this.context.canvas, 0, 0);
this.targetContext_.globalAlpha = alpha;
releaseCanvas(this.context);
canvasPool.push(this.context.canvas);
this.context = this.targetContext_;
this.targetContext_ = null;
}
}
/**
* Render declutter items for this layer
* @param {import("../../Map.js").FrameState} frameState Frame state.
*/
renderDeclutter(frameState) {
if (!this.replayGroup_ || !this.getLayer().getDeclutter()) {
return;
}
this.renderWorlds(this.replayGroup_, frameState, true);
}
/**
* Render deferred instructions.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @override
*/
renderDeferredInternal(frameState) {
if (!this.replayGroup_) {
return;
}
this.replayGroup_.renderDeferred();
if (this.clipped_) {
this.context.restore();
}
this.resetDrawContext_();
}
/**
* Render the layer.
* @param {import("../../Map.js").FrameState} frameState Frame state.
* @param {HTMLElement|null} target Target that may be used to render content to.
* @return {HTMLElement} The rendered element.
* @override
*/
renderFrame(frameState, target) {
const layerState = frameState.layerStatesArray[frameState.layerIndex];
this.opacity_ = layerState.opacity;
const viewState = frameState.viewState;
this.prepareContainer(frameState, target);
const context = this.context;
const replayGroup = this.replayGroup_;
let render = replayGroup && !replayGroup.isEmpty();
if (!render) {
const hasRenderListeners = this.getLayer().hasListener(EventType_default.PRERENDER) || this.getLayer().hasListener(EventType_default.POSTRENDER);
if (!hasRenderListeners) {
return this.container;
}
}
this.setDrawContext_();
this.preRender(context, frameState);
const projection = viewState.projection;
this.clipped_ = false;
if (render && layerState.extent && this.clipping) {
const layerExtent = fromUserExtent(layerState.extent, projection);
render = intersects(layerExtent, frameState.extent);
this.clipped_ = render && !containsExtent(layerExtent, frameState.extent);
if (this.clipped_) {
this.clipUnrotated(context, frameState, layerExtent);
}
}
if (render) {
this.renderWorlds(
replayGroup,
frameState,
this.getLayer().getDeclutter() ? false : void 0
);
}
if (!frameState.declutter && this.clipped_) {
context.restore();
}
this.postRender(context, frameState);
if (this.renderedRotation_ !== viewState.rotation) {
this.renderedRotation_ = viewState.rotation;
this.hitDetectionImageData_ = null;
}
if (!frameState.declutter) {
this.resetDrawContext_();
}
return this.container;
}
/**
* 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) {
return new Promise((resolve) => {
if (this.frameState && !this.hitDetectionImageData_ && !this.animatingOrInteracting_) {
const size = this.frameState.size.slice();
const center = this.renderedCenter_;
const resolution = this.renderedResolution_;
const rotation = this.renderedRotation_;
const projection = this.renderedProjection_;
const extent = this.wrappedRenderedExtent_;
const layer = this.getLayer();
const transforms = [];
const width = size[0] * HIT_DETECT_RESOLUTION;
const height = size[1] * HIT_DETECT_RESOLUTION;
transforms.push(
this.getRenderTransform(
center,
resolution,
rotation,
HIT_DETECT_RESOLUTION,
width,
height,
0
).slice()
);
const source = layer.getSource();
const projectionExtent = projection.getExtent();
if (source.getWrapX() && projection.canWrapX() && !containsExtent(projectionExtent, extent)) {
let startX = extent[0];
const worldWidth = getWidth(projectionExtent);
let world = 0;
let offsetX;
while (startX < projectionExtent[0]) {
--world;
offsetX = worldWidth * world;
transforms.push(
this.getRenderTransform(
center,
resolution,
rotation,
HIT_DETECT_RESOLUTION,
width,
height,
offsetX
).slice()
);
startX += worldWidth;
}
world = 0;
startX = extent[2];
while (startX > projectionExtent[2]) {
++world;
offsetX = worldWidth * world;
transforms.push(
this.getRenderTransform(
center,
resolution,
rotation,
HIT_DETECT_RESOLUTION,
width,
height,
offsetX
).slice()
);
startX -= worldWidth;
}
}
const userProjection = getUserProjection();
this.hitDetectionImageData_ = createHitDetectionImageData(
size,
transforms,
this.renderedFeatures_,
layer.getStyleFunction(),
extent,
resolution,
rotation,
getSquaredTolerance(resolution, this.renderedPixelRatio_),
userProjection ? projection : null
);
}
resolve(
hitDetect(pixel, this.renderedFeatures_, this.hitDetectionImageData_)
);
});
}
/**
* @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) {
var _a, _b;
if (!this.replayGroup_) {
return void 0;
}
const resolution = frameState.viewState.resolution;
const rotation = frameState.viewState.rotation;
const layer = this.getLayer();
const features = {};
const featureCallback = function(feature, geometry, distanceSq) {
const key = getUid(feature);
const match = features[key];
if (!match) {
if (distanceSq === 0) {
features[key] = true;
return callback(feature, layer, geometry);
}
matches.push(
features[key] = {
feature,
layer,
geometry,
distanceSq,
callback
}
);
} else if (match !== true && distanceSq < match.distanceSq) {
if (distanceSq === 0) {
features[key] = true;
matches.splice(matches.lastIndexOf(match), 1);
return callback(feature, layer, geometry);
}
match.geometry = geometry;
match.distanceSq = distanceSq;
}
return void 0;
};
const declutter = this.getLayer().getDeclutter();
return this.replayGroup_.forEachFeatureAtCoordinate(
coordinate,
resolution,
rotation,
hitTolerance,
featureCallback,
declutter ? (_b = (_a = frameState.declutter) == null ? void 0 : _a[declutter]) == null ? void 0 : _b.all().map((item) => item.value) : null
);
}
/**
* Perform action necessary to get the layer rendered after new fonts have loaded
* @override
*/
handleFontsChanged() {
const layer = this.getLayer();
if (layer.getVisible() && this.replayGroup_) {
layer.changed();
}
}
/**
* Handle changes in image style state.
* @param {import("../../events/Event.js").default} event Image style change event.
* @private
*/
handleStyleImageChange_(event) {
this.renderIfReadyAndVisible();
}
/**
* 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) {
const vectorLayer = this.getLayer();
const vectorSource = vectorLayer.getSource();
if (!vectorSource) {
return false;
}
const animating = frameState.viewHints[ViewHint_default.ANIMATING];
const interacting = frameState.viewHints[ViewHint_default.INTERACTING];
const updateWhileAnimating = vectorLayer.getUpdateWhileAnimating();
const updateWhileInteracting = vectorLayer.getUpdateWhileInteracting();
if (this.ready && !updateWhileAnimating && animating || !updateWhileInteracting && interacting) {
this.animatingOrInteracting_ = true;
return true;
}
this.animatingOrInteracting_ = false;
const frameStateExtent = frameState.extent;
const viewState = frameState.viewState;
const projection = viewState.projection;
const resolution = viewState.resolution;
const pixelRatio = frameState.pixelRatio;
const vectorLayerRevision = vectorLayer.getRevision();
const vectorLayerRenderBuffer = vectorLayer.getRenderBuffer();
let vectorLayerRenderOrder = vectorLayer.getRenderOrder();
if (vectorLayerRenderOrder === void 0) {
vectorLayerRenderOrder = defaultOrder;
}
const center = viewState.center.slice();
const extent = buffer(
frameStateExtent,
vectorLayerRenderBuffer * resolution
);
const renderedExtent = extent.slice();
const loadExtents = [extent.slice()];
const projectionExtent = projection.getExtent();
if (vectorSource.getWrapX() && projection.canWrapX() && !containsExtent(projectionExtent, frameState.extent)) {
const worldWidth = getWidth(projectionExtent);
const gutter = Math.max(getWidth(extent) / 2, worldWidth);
extent[0] = projectionExtent[0] - gutter;
extent[2] = projectionExtent[2] + gutter;
wrapX2(center, projection);
const loadExtent = wrapX(loadExtents[0], projection);
if (loadExtent[0] < projectionExtent[0] && loadExtent[2] < projectionExtent[2]) {
loadExtents.push([
loadExtent[0] + worldWidth,
loadExtent[1],
loadExtent[2] + worldWidth,
loadExtent[3]
]);
} else if (loadExtent[0] > projectionExtent[0] && loadExtent[2] > projectionExtent[2]) {
loadExtents.push([
loadExtent[0] - worldWidth,
loadExtent[1],
loadExtent[2] - worldWidth,
loadExtent[3]
]);
}
}
if (this.ready && this.renderedResolution_ == resolution && this.renderedRevision_ == vectorLayerRevision && this.renderedRenderOrder_ == vectorLayerRenderOrder && this.renderedFrameDeclutter_ === !!frameState.declutter && containsExtent(this.wrappedRenderedExtent_, extent)) {
if (!equals(this.renderedExtent_, renderedExtent)) {
this.hitDetectionImageData_ = null;
this.renderedExtent_ = renderedExtent;
}
this.renderedCenter_ = center;
this.replayGroupChanged = false;
return true;
}
this.replayGroup_ = null;
const replayGroup = new BuilderGroup_default(
getTolerance(resolution, pixelRatio),
extent,
resolution,
pixelRatio
);
const userProjection = getUserProjection();
let userTransform;
if (userProjection) {
for (let i = 0, ii = loadExtents.length; i < ii; ++i) {
const extent2 = loadExtents[i];
const userExtent2 = toUserExtent(extent2, projection);
vectorSource.loadFeatures(
userExtent2,
toUserResolution(resolution, projection),
userProjection
);
}
userTransform = getTransformFromProjections(userProjection, projection);
} else {
for (let i = 0, ii = loadExtents.length; i < ii; ++i) {
vectorSource.loadFeatures(loadExtents[i], resolution, projection);
}
}
const squaredTolerance = getSquaredTolerance(resolution, pixelRatio);
let ready = true;
const render = (
/**
* @param {import("../../Feature.js").default} feature Feature.
* @param {number} index Index.
*/
(feature, index) => {
let styles;
const styleFunction = feature.getStyleFunction() || vectorLayer.getStyleFunction();
if (styleFunction) {
styles = styleFunction(feature, resolution);
}
if (styles) {
const dirty = this.renderFeature(
feature,
squaredTolerance,
styles,
replayGroup,
userTransform,
this.getLayer().getDeclutter(),
index
);
ready = ready && !dirty;
}
}
);
const userExtent = toUserExtent(extent, projection);
const features = vectorSource.getFeaturesInExtent(userExtent);
if (vectorLayerRenderOrder) {
features.sort(vectorLayerRenderOrder);
}
for (let i = 0, ii = features.length; i < ii; ++i) {
render(features[i], i);
}
this.renderedFeatures_ = features;
this.ready = ready;
const replayGroupInstructions = replayGroup.finish();
const executorGroup = new ExecutorGroup_default(
extent,
resolution,
pixelRatio,
vectorSource.getOverlaps(),
replayGroupInstructions,
vectorLayer.getRenderBuffer(),
!!frameState.declutter
);
this.renderedResolution_ = resolution;
this.renderedRevision_ = vectorLayerRevision;
this.renderedRenderOrder_ = vectorLayerRenderOrder;
this.renderedFrameDeclutter_ = !!frameState.declutter;
this.renderedExtent_ = renderedExtent;
this.wrappedRenderedExtent_ = extent;
this.renderedCenter_ = center;
this.renderedProjection_ = projection;
this.renderedPixelRatio_ = pixelRatio;
this.replayGroup_ = executorGroup;
this.hitDetectionImageData_ = null;
this.replayGroupChanged = true;
return true;
}
/**
* @param {import("../../Feature.js").default} feature Feature.
* @param {number} squaredTolerance Squared render tolerance.
* @param {import("../../style/Style.js").default|Array<import("../../style/Style.js").default>} styles The style or array of styles.
* @param {import("../../render/canvas/BuilderGroup.js").default} builderGroup Builder group.
* @param {import("../../proj.js").TransformFunction} [transform] Transform from user to view projection.
* @param {boolean} [declutter] Enable decluttering.
* @param {number} [index] Render order index.
* @return {boolean} `true` if an image is loading.
*/
renderFeature(feature, squaredTolerance, styles, builderGroup, transform, declutter, index) {
if (!styles) {
return false;
}
let loading = false;
if (Array.isArray(styles)) {
for (let i = 0, ii = styles.length; i < ii; ++i) {
loading = renderFeature(
builderGroup,
feature,
styles[i],
squaredTolerance,
this.boundHandleStyleImageChange_,
transform,
declutter,
index
) || loading;
}
} else {
loading = renderFeature(
builderGroup,
feature,
styles,
squaredTolerance,
this.boundHandleStyleImageChange_,
transform,
declutter,
index
);
}
return loading;
}
};
var VectorLayer_default = CanvasVectorLayerRenderer;
// node_modules/ol/layer/Vector.js
var VectorLayer = class extends BaseVector_default {
/**
* @param {Options<VectorSourceType, FeatureType>} [options] Options.
*/
constructor(options) {
super(options);
}
/**
* @override
*/
createRenderer() {
return new VectorLayer_default(this);
}
};
var Vector_default = VectorLayer;
export {
Immediate_default,
getSquaredTolerance,
renderFeature,
BuilderGroup_default,
DECLUTTER,
ExecutorGroup_default,
HIT_DETECT_RESOLUTION,
createHitDetectionImageData,
hitDetect,
VectorLayer_default,
Vector_default
};
//# sourceMappingURL=chunk-2RRPH7ER.js.map