import {
  create as create2,
  fromTransform
} from "./chunk-E7S7Q7VV.js";
import {
  VectorEventType_default
} from "./chunk-V7WRBSQ6.js";
import {
  Feature_default
} from "./chunk-W7BDJOQY.js";
import {
  DataTile_default,
  LRUCache_default,
  TileLayer_default,
  TileProperty_default,
  asArrayLike,
  asImageLike
} from "./chunk-UNDFRJ2M.js";
import {
  BuilderGroup_default,
  DECLUTTER,
  ExecutorGroup_default,
  HIT_DETECT_RESOLUTION,
  createHitDetectionImageData,
  getSquaredTolerance,
  hitDetect,
  renderFeature
} from "./chunk-T3TT2KJN.js";
import {
  Layer_default,
  ZIndexContext_default
} from "./chunk-ZUI5NXIU.js";
import {
  BaseVector_default,
  BooleanType,
  CallExpression,
  ColorType,
  NumberArrayType,
  NumberType,
  Ops,
  SizeType,
  StringType,
  computeGeometryType,
  isType,
  newParsingContext,
  parse,
  typeName
} from "./chunk-ZCRXKB7J.js";
import {
  EventType_default as EventType_default2,
  Event_default
} from "./chunk-I6K7MRGV.js";
import {
  asArray
} from "./chunk-PGWX4545.js";
import {
  Property_default
} from "./chunk-AYBYZSAV.js";
import {
  ViewHint_default
} from "./chunk-YLJGUH5Z.js";
import {
  inflateEnds,
  transform2D
} from "./chunk-AZGMK675.js";
import {
  ImageTile_default,
  TileRange_default,
  Tile_default2 as Tile_default,
  createOrUpdate2 as createOrUpdate,
  getKey
} from "./chunk-7XMWB3J4.js";
import {
  TileState_default
} from "./chunk-5D2XPBR2.js";
import {
  toSize
} from "./chunk-SHUBVYN4.js";
import {
  apply,
  compose,
  create,
  makeInverse,
  multiply,
  reset,
  rotate,
  scale,
  setFromArray,
  translate
} from "./chunk-X52LGBOS.js";
import {
  assert
} from "./chunk-QFCIXVZ3.js";
import {
  equivalent,
  fromUserExtent,
  getTransform,
  getTransformFromProjections,
  getUserProjection,
  toUserExtent,
  toUserResolution,
  transformExtent,
  wrapX
} from "./chunk-A3RXLHYB.js";
import {
  clamp
} from "./chunk-54BTDBAD.js";
import {
  createCanvasContext2D
} from "./chunk-UPTVWZ45.js";
import {
  SAFARI_BUG_237906
} from "./chunk-5XHD7RSF.js";
import {
  abstract,
  getUid
} from "./chunk-Q5ZULJHM.js";
import {
  Disposable_default,
  Target_default,
  listen,
  unlistenByKey
} from "./chunk-NGFXCWUF.js";
import {
  EventType_default,
  ascending,
  descending,
  equals
} from "./chunk-K25ZO44T.js";
import {
  boundingExtent,
  buffer,
  containsCoordinate,
  containsExtent,
  createEmpty,
  equals as equals2,
  getIntersection,
  getRotatedViewport,
  getTopLeft,
  getWidth,
  intersects,
  isEmpty
} from "./chunk-SRXHWJOY.js";
import {
  clear
} from "./chunk-5RHQVMYD.js";

// node_modules/ol/renderer/canvas/VectorTileLayer.js
var IMAGE_REPLAYS = {
  "image": ["Polygon", "Circle", "LineString", "Image", "Text"],
  "hybrid": ["Polygon", "LineString"],
  "vector": []
};
var VECTOR_REPLAYS = {
  "hybrid": ["Image", "Text", "Default"],
  "vector": ["Polygon", "Circle", "LineString", "Image", "Text", "Default"]
};
var CanvasVectorTileLayerRenderer = class extends TileLayer_default {
  /**
   * @param {import("../../layer/VectorTile.js").default} layer VectorTile layer.
   * @param {import("./TileLayer.js").Options} options Options.
   */
  constructor(layer, options) {
    super(layer, options);
    this.boundHandleStyleImageChange_ = this.handleStyleImageChange_.bind(this);
    this.renderedLayerRevision_;
    this.renderedPixelToCoordinateTransform_ = null;
    this.renderedRotation_;
    this.renderedOpacity_ = 1;
    this.tmpTransform_ = create();
    this.tileClipContexts_ = null;
  }
  /**
   * Determine whether tiles for next extent should be enqueued for rendering.
   * @return {boolean} Rendering tiles for next extent is supported.
   * @override
   */
  enqueueTilesForNextExtent() {
    return this.getLayer().getRenderMode() !== "vector";
  }
  /**
   * @param {import("../../VectorRenderTile.js").default} tile Tile.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @param {number} x Left of the tile.
   * @param {number} y Top of the tile.
   * @param {number} w Width of the tile.
   * @param {number} h Height of the tile.
   * @param {number} gutter Tile gutter.
   * @param {boolean} transition Apply an alpha transition.
   * @override
   */
  drawTile(tile, frameState, x, y, w, h, gutter, transition) {
    this.updateExecutorGroup_(
      tile,
      frameState.pixelRatio,
      frameState.viewState.projection
    );
    if (this.tileImageNeedsRender_(tile)) {
      this.renderTileImage_(tile, frameState);
    }
    super.drawTile(tile, frameState, x, y, w, h, gutter, transition);
  }
  /**
   * @param {number} z Tile coordinate z.
   * @param {number} x Tile coordinate x.
   * @param {number} y Tile coordinate y.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @return {import("../../Tile.js").default|null} Tile (or null if outside source extent).
   * @override
   */
  getTile(z, x, y, frameState) {
    const tile = (
      /** @type {import("../../VectorRenderTile.js").default} */
      this.getOrCreateTile(z, x, y, frameState)
    );
    if (!tile) {
      return null;
    }
    const viewState = frameState.viewState;
    const resolution = viewState.resolution;
    const viewHints = frameState.viewHints;
    const source = this.getLayer().getSource();
    const tileGrid = source.getTileGridForProjection(viewState.projection);
    const hifi = !(viewHints[ViewHint_default.ANIMATING] || viewHints[ViewHint_default.INTERACTING]);
    const withinTileResolutionRange = tileGrid.getZForResolution(resolution, source.zDirection) === z;
    if (hifi && withinTileResolutionRange) {
      tile.wantedResolution = resolution;
    } else if (!tile.wantedResolution) {
      tile.wantedResolution = tileGrid.getResolution(z);
    }
    return tile;
  }
  /**
   * 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 layerRevision = this.getLayer().getRevision();
    if (this.renderedLayerRevision_ !== layerRevision) {
      this.renderedLayerRevision_ = layerRevision;
      this.renderedTiles.length = 0;
    }
    return super.prepareFrame(frameState);
  }
  /**
   * @param {import("../../VectorRenderTile.js").default} tile Tile.
   * @param {number} pixelRatio Pixel ratio.
   * @param {import("../../proj/Projection.js").default} projection Projection.
   * @private
   */
  updateExecutorGroup_(tile, pixelRatio, projection) {
    const layer = (
      /** @type {import("../../layer/VectorTile.js").default} */
      this.getLayer()
    );
    const revision = layer.getRevision();
    const renderOrder = layer.getRenderOrder() || null;
    const resolution = tile.wantedResolution;
    const builderState = tile.getReplayState(layer);
    if (!builderState.dirty && builderState.renderedResolution === resolution && builderState.renderedRevision == revision && builderState.renderedRenderOrder == renderOrder) {
      return;
    }
    const source = layer.getSource();
    const declutter = !!layer.getDeclutter();
    const sourceTileGrid = source.getTileGrid();
    const tileGrid = source.getTileGridForProjection(projection);
    const tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);
    const sourceTiles = source.getSourceTiles(pixelRatio, projection, tile);
    const layerUid = getUid(layer);
    delete tile.hitDetectionImageData[layerUid];
    tile.executorGroups[layerUid] = [];
    builderState.dirty = false;
    for (let t = 0, tt = sourceTiles.length; t < tt; ++t) {
      const sourceTile = sourceTiles[t];
      if (sourceTile.getState() != TileState_default.LOADED) {
        continue;
      }
      const sourceProjection = source.getProjection();
      const sourceTileCoord = sourceTile.tileCoord;
      let sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord);
      if (projection && sourceProjection && !equivalent(projection, sourceProjection)) {
        sourceTileExtent = transformExtent(
          sourceTileExtent,
          sourceProjection,
          projection,
          32
        );
      }
      const sharedExtent = getIntersection(tileExtent, sourceTileExtent);
      const builderExtent = buffer(
        sharedExtent,
        layer.getRenderBuffer() * resolution,
        this.tempExtent
      );
      const bufferedExtent = equals2(sourceTileExtent, sharedExtent) ? null : builderExtent;
      const builderGroup = new BuilderGroup_default(
        0,
        sharedExtent,
        resolution,
        pixelRatio
      );
      const squaredTolerance = getSquaredTolerance(
        resolution,
        pixelRatio
      );
      const render = function(feature, index) {
        let styles;
        const styleFunction = feature.getStyleFunction() || layer.getStyleFunction();
        if (styleFunction) {
          styles = styleFunction(feature, resolution);
        }
        if (styles) {
          const dirty = this.renderFeature(
            feature,
            squaredTolerance,
            styles,
            builderGroup,
            declutter,
            index
          );
          builderState.dirty = builderState.dirty || dirty;
        }
      };
      const features = sourceTile.getFeatures();
      if (renderOrder && renderOrder !== builderState.renderedRenderOrder) {
        features.sort(renderOrder);
      }
      for (let i = 0, ii = features.length; i < ii; ++i) {
        let feature = features[i];
        if (projection && sourceTile.projection && !equivalent(projection, sourceTile.projection)) {
          feature = feature.clone();
          feature.getGeometry().applyTransform(getTransform(sourceTile.projection, projection));
        }
        if (!bufferedExtent || intersects(bufferedExtent, feature.getGeometry().getExtent())) {
          render.call(this, feature, i);
        }
      }
      const executorGroupInstructions = builderGroup.finish();
      const replayExtent = layer.getRenderMode() !== "vector" && declutter && sourceTiles.length === 1 ? null : sharedExtent;
      const renderingReplayGroup = new ExecutorGroup_default(
        replayExtent,
        resolution,
        pixelRatio,
        source.getOverlaps(),
        executorGroupInstructions,
        layer.getRenderBuffer(),
        true
      );
      tile.executorGroups[layerUid].push(renderingReplayGroup);
    }
    builderState.renderedRevision = revision;
    builderState.renderedRenderOrder = renderOrder;
    builderState.renderedResolution = resolution;
  }
  /**
   * @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;
    const resolution = frameState.viewState.resolution;
    const rotation = frameState.viewState.rotation;
    hitTolerance = hitTolerance == void 0 ? 0 : hitTolerance;
    const layer = this.getLayer();
    const source = layer.getSource();
    const tileGrid = source.getTileGridForProjection(
      frameState.viewState.projection
    );
    const hitExtent = boundingExtent([coordinate]);
    buffer(hitExtent, resolution * hitTolerance, hitExtent);
    const features = {};
    const featureCallback = function(feature, geometry, distanceSq) {
      let key = feature.getId();
      if (key === void 0) {
        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 renderedTiles = (
      /** @type {Array<import("../../VectorRenderTile.js").default>} */
      this.renderedTiles
    );
    const layerUid = getUid(layer);
    const declutter = layer.getDeclutter();
    const declutteredFeatures = declutter ? (_b = (_a = frameState.declutter) == null ? void 0 : _a[declutter]) == null ? void 0 : _b.all().map((item) => item.value) : null;
    let found;
    foundFeature: for (let i = 0, ii = renderedTiles.length; i < ii; ++i) {
      const tile = renderedTiles[i];
      const tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);
      if (!intersects(tileExtent, hitExtent)) {
        continue;
      }
      const executorGroups = tile.executorGroups[layerUid];
      for (let t = 0, tt = executorGroups.length; t < tt; ++t) {
        found = executorGroups[t].forEachFeatureAtCoordinate(
          coordinate,
          resolution,
          rotation,
          hitTolerance,
          featureCallback,
          declutteredFeatures
        );
        if (found) {
          break foundFeature;
        }
      }
    }
    return found;
  }
  /**
   * Asynchronous layer level hit detection.
   * @param {import("../../pixel.js").Pixel} pixel Pixel.
   * @return {Promise<Array<import("../../Feature.js").FeatureLike>>} Promise that resolves with an array of features.
   * @override
   */
  getFeatures(pixel) {
    if (this.renderedTiles.length === 0) {
      return Promise.resolve([]);
    }
    return new Promise((resolve, reject) => {
      const layer = this.getLayer();
      const source = layer.getSource();
      const projection = this.renderedProjection;
      const projectionExtent = projection.getExtent();
      const resolution = this.renderedResolution;
      const tileGrid = source.getTileGridForProjection(projection);
      const coordinate = apply(
        this.renderedPixelToCoordinateTransform_,
        pixel.slice()
      );
      const tileCoordString = tileGrid.getTileCoordForCoordAndResolution(coordinate, resolution).toString();
      const tile = (
        /** @type {Array<import("../../VectorRenderTile.js").default>} */
        this.renderedTiles.find(
          (tile2) => tile2.tileCoord.toString() === tileCoordString && tile2.getState() === TileState_default.LOADED
        )
      );
      if (!tile || tile.loadingSourceTiles > 0) {
        resolve([]);
        return;
      }
      if (source.getWrapX() && projection.canWrapX() && !containsExtent(
        projectionExtent,
        tileGrid.getTileCoordExtent(tile.tileCoord)
      )) {
        wrapX(coordinate, projection);
      }
      const layerUid = getUid(layer);
      const extent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);
      const corner = getTopLeft(extent);
      const tilePixel = [
        (coordinate[0] - corner[0]) / resolution,
        (corner[1] - coordinate[1]) / resolution
      ];
      const features = tile.getSourceTiles().reduce(
        (accumulator, sourceTile) => accumulator.concat(sourceTile.getFeatures()),
        /** @type {Array<import("../../Feature.js").FeatureLike>} */
        []
      );
      let hitDetectionImageData = tile.hitDetectionImageData[layerUid];
      if (!hitDetectionImageData) {
        const tileSize = toSize(
          tileGrid.getTileSize(
            tileGrid.getZForResolution(resolution, source.zDirection)
          )
        );
        const rotation = this.renderedRotation_;
        const transforms = [
          this.getRenderTransform(
            tileGrid.getTileCoordCenter(tile.wrappedTileCoord),
            resolution,
            0,
            HIT_DETECT_RESOLUTION,
            tileSize[0] * HIT_DETECT_RESOLUTION,
            tileSize[1] * HIT_DETECT_RESOLUTION,
            0
          )
        ];
        hitDetectionImageData = createHitDetectionImageData(
          tileSize,
          transforms,
          features,
          layer.getStyleFunction(),
          tileGrid.getTileCoordExtent(tile.wrappedTileCoord),
          tile.getReplayState(layer).renderedResolution,
          rotation
        );
        tile.hitDetectionImageData[layerUid] = hitDetectionImageData;
      }
      resolve(hitDetect(tilePixel, features, hitDetectionImageData));
    });
  }
  /**
   * @param {import("../../extent.js").Extent} extent Extent.
   * @return {Array<import('../../Feature.js').FeatureLike>} Features.
   */
  getFeaturesInExtent(extent) {
    const features = [];
    const tileCache = this.getTileCache();
    if (tileCache.getCount() === 0) {
      return features;
    }
    const source = this.getLayer().getSource();
    const tileGrid = source.getTileGridForProjection(
      this.frameState.viewState.projection
    );
    const z = tileGrid.getZForResolution(this.renderedResolution);
    const visitedSourceTiles = {};
    tileCache.forEach((tile) => {
      if (tile.tileCoord[0] !== z || tile.getState() !== TileState_default.LOADED) {
        return;
      }
      const sourceTiles = tile.getSourceTiles();
      for (let i = 0, ii = sourceTiles.length; i < ii; ++i) {
        const sourceTile = sourceTiles[i];
        const key = sourceTile.getKey();
        if (key in visitedSourceTiles) {
          continue;
        }
        visitedSourceTiles[key] = true;
        const tileCoord = sourceTile.tileCoord;
        if (intersects(extent, tileGrid.getTileCoordExtent(tileCoord))) {
          const tileFeatures = sourceTile.getFeatures();
          if (tileFeatures) {
            for (let j = 0, jj = tileFeatures.length; j < jj; ++j) {
              const candidate = tileFeatures[j];
              const geometry = candidate.getGeometry();
              if (intersects(extent, geometry.getExtent())) {
                features.push(candidate);
              }
            }
          }
        }
      }
    });
    return features;
  }
  /**
   * Perform action necessary to get the layer rendered after new fonts have loaded
   * @override
   */
  handleFontsChanged() {
    const layer = this.getLayer();
    if (layer.getVisible() && this.renderedLayerRevision_ !== void 0) {
      layer.changed();
    }
  }
  /**
   * Handle changes in image style state.
   * @param {import("../../events/Event.js").default} event Image style change event.
   * @private
   */
  handleStyleImageChange_(event) {
    this.renderIfReadyAndVisible();
  }
  /**
   * Render declutter items for this layer
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @param {import("../../layer/Layer.js").State} layerState Layer state.
   */
  renderDeclutter(frameState, layerState) {
    var _a;
    const context = this.context;
    const alpha = context.globalAlpha;
    context.globalAlpha = layerState.opacity;
    const viewHints = frameState.viewHints;
    const hifi = !(viewHints[ViewHint_default.ANIMATING] || viewHints[ViewHint_default.INTERACTING]);
    const scaledCanvasSize = [
      this.context.canvas.width,
      this.context.canvas.height
    ];
    const declutter = this.getLayer().getDeclutter();
    const declutterTree = declutter ? (_a = frameState.declutter) == null ? void 0 : _a[declutter] : void 0;
    const layerUid = getUid(this.getLayer());
    const tiles = (
      /** @type {Array<import("../../VectorRenderTile.js").default>} */
      this.renderedTiles
    );
    for (let i = 0, ii = tiles.length; i < ii; ++i) {
      const tile = tiles[i];
      const executorGroups = tile.executorGroups[layerUid];
      if (executorGroups) {
        for (let j = executorGroups.length - 1; j >= 0; --j) {
          executorGroups[j].execute(
            this.context,
            scaledCanvasSize,
            this.getTileRenderTransform(tile, frameState),
            frameState.viewState.rotation,
            hifi,
            DECLUTTER,
            declutterTree
          );
        }
      }
    }
    context.globalAlpha = alpha;
  }
  /**
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @override
   */
  renderDeferredInternal(frameState) {
    const tiles = (
      /** @type {Array<import("../../VectorRenderTile.js").default>} */
      this.renderedTiles
    );
    const layerUid = getUid(this.getLayer());
    const executorGroups = tiles.reduce(
      (acc, tile, index) => {
        tile.executorGroups[layerUid].forEach(
          (executorGroup) => acc.push({
            executorGroup,
            index
          })
        );
        return acc;
      },
      /** @type {Array<{executorGroup: CanvasExecutorGroup, index: number}>} */
      []
    );
    const executorGroupZIndexContexts = executorGroups.map(
      ({ executorGroup }) => executorGroup.getDeferredZIndexContexts()
    );
    const usedZIndices = {};
    for (let i = 0, ii = executorGroups.length; i < ii; ++i) {
      const executorGroupZindexContext = executorGroups[i].executorGroup.getDeferredZIndexContexts();
      for (const key in executorGroupZindexContext) {
        usedZIndices[key] = true;
      }
    }
    const zIndexKeys = Object.keys(usedZIndices).map(Number).sort(ascending);
    zIndexKeys.forEach((zIndex) => {
      executorGroupZIndexContexts.forEach((zIndexContexts, i) => {
        if (!zIndexContexts[zIndex]) {
          return;
        }
        zIndexContexts[zIndex].forEach((zIndexContext) => {
          const { executorGroup, index } = executorGroups[i];
          const context = executorGroup.getRenderedContext();
          const alpha = context.globalAlpha;
          context.globalAlpha = this.renderedOpacity_;
          const tileClipContext = this.tileClipContexts_[index];
          if (tileClipContext) {
            tileClipContext.draw(context);
          }
          zIndexContext.draw(context);
          if (tileClipContext) {
            context.restore();
          }
          context.globalAlpha = alpha;
          zIndexContext.clear();
        });
        zIndexContexts[zIndex].length = 0;
      });
    });
  }
  /**
   * @param {import("../../VectorRenderTile.js").default} tile The tile
   * @param {import('../../Map.js').FrameState} frameState Current frame state
   * @return {import('../../transform.js').Transform} Transform to use to render this tile
   */
  getTileRenderTransform(tile, frameState) {
    const pixelRatio = frameState.pixelRatio;
    const viewState = frameState.viewState;
    const center = viewState.center;
    const resolution = viewState.resolution;
    const rotation = viewState.rotation;
    const size = frameState.size;
    const width = Math.round(size[0] * pixelRatio);
    const height = Math.round(size[1] * pixelRatio);
    const source = this.getLayer().getSource();
    const tileGrid = source.getTileGridForProjection(
      frameState.viewState.projection
    );
    const tileCoord = tile.tileCoord;
    const tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);
    const worldOffset = tileGrid.getTileCoordExtent(tileCoord, this.tempExtent)[0] - tileExtent[0];
    const transform = multiply(
      scale(this.inversePixelTransform.slice(), 1 / pixelRatio, 1 / pixelRatio),
      this.getRenderTransform(
        center,
        resolution,
        rotation,
        pixelRatio,
        width,
        height,
        worldOffset
      )
    );
    return transform;
  }
  /**
   * Render the vectors for this layer.
   * @param {CanvasRenderingContext2D|OffscreenCanvasRenderingContext2D} context Target context.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @override
   */
  postRender(context, frameState) {
    var _a;
    const viewHints = frameState.viewHints;
    const hifi = !(viewHints[ViewHint_default.ANIMATING] || viewHints[ViewHint_default.INTERACTING]);
    this.renderedPixelToCoordinateTransform_ = frameState.pixelToCoordinateTransform.slice();
    this.renderedRotation_ = frameState.viewState.rotation;
    this.renderedOpacity_ = frameState.layerStatesArray[frameState.layerIndex].opacity;
    const layer = (
      /** @type {import("../../layer/VectorTile.js").default} */
      this.getLayer()
    );
    const renderMode = layer.getRenderMode();
    const alpha = context.globalAlpha;
    context.globalAlpha = this.renderedOpacity_;
    const declutter = layer.getDeclutter();
    const replayTypes = declutter ? VECTOR_REPLAYS[renderMode].filter((type) => !DECLUTTER.includes(type)) : VECTOR_REPLAYS[renderMode];
    const viewState = frameState.viewState;
    const rotation = viewState.rotation;
    const tileSource = layer.getSource();
    const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
    const z = tileGrid.getZForResolution(
      viewState.resolution,
      tileSource.zDirection
    );
    const tiles = (
      /** @type {Array<import("../../VectorRenderTile.js").default>} */
      this.renderedTiles
    );
    const clips = [];
    const clipZs = [];
    const tileClipContexts = [];
    const layerUid = getUid(layer);
    let ready = true;
    for (let i = tiles.length - 1; i >= 0; --i) {
      const tile = tiles[i];
      ready = ready && !tile.getReplayState(layer).dirty;
      const executorGroups = tile.executorGroups[layerUid].filter(
        (group) => group.hasExecutors(replayTypes)
      );
      if (executorGroups.length === 0) {
        continue;
      }
      const transform = this.getTileRenderTransform(tile, frameState);
      const currentZ = tile.tileCoord[0];
      let contextSaved = false;
      const currentClip = executorGroups[0].getClipCoords(transform);
      let clipContext = context;
      let tileClipContext;
      if (currentClip) {
        tileClipContext = new ZIndexContext_default();
        clipContext = tileClipContext.getContext();
        for (let j = 0, jj = clips.length; j < jj; ++j) {
          if (z !== currentZ && currentZ < clipZs[j]) {
            const clip = clips[j];
            if (intersects(
              [
                currentClip[0],
                currentClip[3],
                currentClip[4],
                currentClip[7]
              ],
              [clip[0], clip[3], clip[4], clip[7]]
            )) {
              if (!contextSaved) {
                clipContext.save();
                contextSaved = true;
              }
              clipContext.beginPath();
              clipContext.moveTo(currentClip[0], currentClip[1]);
              clipContext.lineTo(currentClip[2], currentClip[3]);
              clipContext.lineTo(currentClip[4], currentClip[5]);
              clipContext.lineTo(currentClip[6], currentClip[7]);
              clipContext.moveTo(clip[6], clip[7]);
              clipContext.lineTo(clip[4], clip[5]);
              clipContext.lineTo(clip[2], clip[3]);
              clipContext.lineTo(clip[0], clip[1]);
              clipContext.clip();
            }
          }
        }
        clips.push(currentClip);
        clipZs.push(currentZ);
      }
      for (let t = 0, tt = executorGroups.length; t < tt; ++t) {
        const executorGroup = executorGroups[t];
        executorGroup.execute(
          context,
          [context.canvas.width, context.canvas.height],
          transform,
          rotation,
          hifi,
          replayTypes,
          (_a = frameState.declutter) == null ? void 0 : _a[declutter]
        );
      }
      if (contextSaved) {
        if (clipContext === context) {
          clipContext.restore();
        } else {
          tileClipContexts[i] = tileClipContext;
        }
      }
    }
    context.globalAlpha = alpha;
    this.ready = ready;
    this.tileClipContexts_ = tileClipContexts;
    if (!frameState.declutter) {
      this.renderDeferredInternal(frameState);
    }
    super.postRender(context, frameState);
  }
  /**
   * @param {import("../../Feature.js").FeatureLike} feature Feature.
   * @param {number} squaredTolerance Squared 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 Replay group.
   * @param {boolean} [declutter] Enable decluttering.
   * @param {number} [index] Render order index.
   * @return {boolean} `true` if an image is loading.
   */
  renderFeature(feature, squaredTolerance, styles, builderGroup, 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_,
          void 0,
          declutter,
          index
        ) || loading;
      }
    } else {
      loading = renderFeature(
        builderGroup,
        feature,
        styles,
        squaredTolerance,
        this.boundHandleStyleImageChange_,
        void 0,
        declutter,
        index
      );
    }
    return loading;
  }
  /**
   * @param {import("../../VectorRenderTile.js").default} tile Tile.
   * @return {boolean} A new tile image was rendered.
   * @private
   */
  tileImageNeedsRender_(tile) {
    const layer = (
      /** @type {import("../../layer/VectorTile.js").default} */
      this.getLayer()
    );
    if (layer.getRenderMode() === "vector") {
      return false;
    }
    const replayState = tile.getReplayState(layer);
    const revision = layer.getRevision();
    const resolution = tile.wantedResolution;
    const tileImageNeedsRender = replayState.renderedTileResolution !== resolution || replayState.renderedTileRevision !== revision;
    return tileImageNeedsRender;
  }
  /**
   * @param {import("../../VectorRenderTile.js").default} tile Tile.
   * @param {import("../../Map").FrameState} frameState Frame state.
   * @private
   */
  renderTileImage_(tile, frameState) {
    const layer = (
      /** @type {import("../../layer/VectorTile.js").default} */
      this.getLayer()
    );
    const replayState = tile.getReplayState(layer);
    const revision = layer.getRevision();
    const executorGroups = tile.executorGroups[getUid(layer)];
    replayState.renderedTileRevision = revision;
    const tileCoord = tile.wrappedTileCoord;
    const z = tileCoord[0];
    const source = layer.getSource();
    let pixelRatio = frameState.pixelRatio;
    const viewState = frameState.viewState;
    const projection = viewState.projection;
    const tileGrid = source.getTileGridForProjection(projection);
    const tileResolution = tileGrid.getResolution(tile.tileCoord[0]);
    const renderPixelRatio = frameState.pixelRatio / tile.wantedResolution * tileResolution;
    const resolution = tileGrid.getResolution(z);
    const context = tile.getContext();
    pixelRatio = Math.round(
      Math.max(pixelRatio, renderPixelRatio / pixelRatio)
    );
    const size = source.getTilePixelSize(z, pixelRatio, projection);
    context.canvas.width = size[0];
    context.canvas.height = size[1];
    const renderScale = pixelRatio / renderPixelRatio;
    if (renderScale !== 1) {
      const canvasTransform = reset(this.tmpTransform_);
      scale(canvasTransform, renderScale, renderScale);
      context.setTransform.apply(context, canvasTransform);
    }
    const tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tempExtent);
    const pixelScale = renderPixelRatio / resolution;
    const transform = reset(this.tmpTransform_);
    scale(transform, pixelScale, -pixelScale);
    translate(transform, -tileExtent[0], -tileExtent[3]);
    for (let i = 0, ii = executorGroups.length; i < ii; ++i) {
      const executorGroup = executorGroups[i];
      executorGroup.execute(
        context,
        [
          context.canvas.width * renderScale,
          context.canvas.height * renderScale
        ],
        transform,
        0,
        true,
        IMAGE_REPLAYS[layer.getRenderMode()],
        null
      );
    }
    replayState.renderedTileResolution = tile.wantedResolution;
  }
};
var VectorTileLayer_default = CanvasVectorTileLayerRenderer;

// node_modules/ol/layer/VectorTile.js
var VectorTileLayer = class extends BaseVector_default {
  /**
   * @param {Options<VectorTileSourceType, FeatureType>} [options] Options.
   */
  constructor(options) {
    options = options ? options : {};
    const baseOptions = Object.assign({}, options);
    delete baseOptions.preload;
    const cacheSize = options.cacheSize === void 0 ? 0 : options.cacheSize;
    delete options.cacheSize;
    delete baseOptions.useInterimTilesOnError;
    super(baseOptions);
    this.on;
    this.once;
    this.un;
    this.cacheSize_ = cacheSize;
    const renderMode = options.renderMode || "hybrid";
    assert(
      renderMode == "hybrid" || renderMode == "vector",
      "`renderMode` must be `'hybrid'` or `'vector'`"
    );
    this.renderMode_ = renderMode;
    this.setPreload(options.preload ? options.preload : 0);
    this.setUseInterimTilesOnError(
      options.useInterimTilesOnError !== void 0 ? options.useInterimTilesOnError : true
    );
    this.getBackground;
    this.setBackground;
  }
  /**
   * @override
   */
  createRenderer() {
    return new VectorTileLayer_default(this, {
      cacheSize: this.cacheSize_
    });
  }
  /**
   * Get the topmost feature that intersects the given pixel on the viewport. Returns a promise
   * that resolves with an array of features. The array will either contain the topmost feature
   * when a hit was detected, or it will be empty.
   *
   * The hit detection algorithm used for this method is optimized for performance, but is less
   * accurate than the one used in [map.getFeaturesAtPixel()]{@link import("../Map.js").default#getFeaturesAtPixel}.
   * Text is not considered, and icons are only represented by their bounding box instead of the exact
   * image.
   *
   * @param {import("../pixel.js").Pixel} pixel Pixel.
   * @return {Promise<Array<import("../Feature").FeatureLike>>} Promise that resolves with an array of features.
   * @api
   * @override
   */
  getFeatures(pixel) {
    return super.getFeatures(pixel);
  }
  /**
   * Get features whose bounding box intersects the provided extent. Only features for cached
   * tiles for the last rendered zoom level are available in the source. So this method is only
   * suitable for requesting tiles for extents that are currently rendered.
   *
   * Features are returned in random tile order and as they are included in the tiles. This means
   * they can be clipped, duplicated across tiles, and simplified to the render resolution.
   *
   * @param {import("../extent.js").Extent} extent Extent.
   * @return {Array<FeatureType>} Features.
   * @api
   */
  getFeaturesInExtent(extent) {
    return (
      /** @type {Array<FeatureType>} */
      /** @type {*} */
      this.getRenderer().getFeaturesInExtent(extent)
    );
  }
  /**
   * @return {VectorTileRenderType} The render mode.
   */
  getRenderMode() {
    return this.renderMode_;
  }
  /**
   * Return the level as number to which we will preload tiles up to.
   * @return {number} The level to preload tiles up to.
   * @observable
   * @api
   */
  getPreload() {
    return (
      /** @type {number} */
      this.get(TileProperty_default.PRELOAD)
    );
  }
  /**
   * Deprecated.  Whether we use interim tiles on error.
   * @return {boolean} Use interim tiles on error.
   * @observable
   * @api
   */
  getUseInterimTilesOnError() {
    return (
      /** @type {boolean} */
      this.get(TileProperty_default.USE_INTERIM_TILES_ON_ERROR)
    );
  }
  /**
   * Set the level as number to which we will preload tiles up to.
   * @param {number} preload The level to preload tiles up to.
   * @observable
   * @api
   */
  setPreload(preload) {
    this.set(TileProperty_default.PRELOAD, preload);
  }
  /**
   * Deprecated.  Set whether we use interim tiles on error.
   * @param {boolean} useInterimTilesOnError Use interim tiles on error.
   * @observable
   * @api
   */
  setUseInterimTilesOnError(useInterimTilesOnError) {
    this.set(TileProperty_default.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
  }
};
var VectorTile_default = VectorTileLayer;

// node_modules/ol/webgl.js
var ARRAY_BUFFER = 34962;
var ELEMENT_ARRAY_BUFFER = 34963;
var STREAM_DRAW = 35040;
var STATIC_DRAW = 35044;
var DYNAMIC_DRAW = 35048;
var UNSIGNED_BYTE = 5121;
var UNSIGNED_SHORT = 5123;
var UNSIGNED_INT = 5125;
var FLOAT = 5126;
var CONTEXT_IDS = ["experimental-webgl", "webgl", "webkit-3d", "moz-webgl"];
function getContext(canvas, attributes) {
  attributes = Object.assign(
    {
      preserveDrawingBuffer: true,
      antialias: SAFARI_BUG_237906 ? false : true
      // https://bugs.webkit.org/show_bug.cgi?id=237906
    },
    attributes
  );
  const ii = CONTEXT_IDS.length;
  for (let i = 0; i < ii; ++i) {
    try {
      const context = canvas.getContext(CONTEXT_IDS[i], attributes);
      if (context) {
        return (
          /** @type {!WebGLRenderingContext} */
          context
        );
      }
    } catch {
    }
  }
  return null;
}

// node_modules/ol/webgl/Buffer.js
var BufferUsage = {
  STATIC_DRAW,
  STREAM_DRAW,
  DYNAMIC_DRAW
};
var WebGLArrayBuffer = class {
  /**
   * @param {number} type Buffer type, either ARRAY_BUFFER or ELEMENT_ARRAY_BUFFER.
   * @param {number} [usage] Intended usage, either `STATIC_DRAW`, `STREAM_DRAW` or `DYNAMIC_DRAW`.
   * Default is `STATIC_DRAW`.
   */
  constructor(type, usage) {
    this.array_ = null;
    this.type_ = type;
    assert(
      type === ARRAY_BUFFER || type === ELEMENT_ARRAY_BUFFER,
      "A `WebGLArrayBuffer` must either be of type `ELEMENT_ARRAY_BUFFER` or `ARRAY_BUFFER`"
    );
    this.usage_ = usage !== void 0 ? usage : BufferUsage.STATIC_DRAW;
  }
  /**
   * Populates the buffer with an array of the given size (all values will be zeroes).
   * @param {number} size Array size
   * @return {WebGLArrayBuffer} This
   */
  ofSize(size) {
    this.array_ = new (getArrayClassForType(this.type_))(size);
    return this;
  }
  /**
   * Populates the buffer with an array of the given size.
   * @param {Array<number>} array Numerical array
   * @return {WebGLArrayBuffer} This
   */
  fromArray(array) {
    this.array_ = getArrayClassForType(this.type_).from(array);
    return this;
  }
  /**
   * Populates the buffer with a raw binary array buffer.
   * @param {ArrayBuffer} buffer Raw binary buffer to populate the array with. Note that this buffer must have been
   * initialized for the same typed array class.
   * @return {WebGLArrayBuffer} This
   */
  fromArrayBuffer(buffer2) {
    this.array_ = new (getArrayClassForType(this.type_))(buffer2);
    return this;
  }
  /**
   * @return {number} Buffer type.
   */
  getType() {
    return this.type_;
  }
  /**
   * Will return null if the buffer was not initialized
   * @return {Float32Array|Uint32Array|null} Array.
   */
  getArray() {
    return this.array_;
  }
  /**
   * @param {Float32Array|Uint32Array} array Array.
   */
  setArray(array) {
    const ArrayType = getArrayClassForType(this.type_);
    if (!(array instanceof ArrayType)) {
      throw new Error(`Expected ${ArrayType}`);
    }
    this.array_ = array;
  }
  /**
   * @return {number} Usage.
   */
  getUsage() {
    return this.usage_;
  }
  /**
   * Will return 0 if the buffer is not initialized
   * @return {number} Array size
   */
  getSize() {
    return this.array_ ? this.array_.length : 0;
  }
};
function getArrayClassForType(type) {
  switch (type) {
    case ARRAY_BUFFER:
      return Float32Array;
    case ELEMENT_ARRAY_BUFFER:
      return Uint32Array;
    default:
      return Float32Array;
  }
}
var Buffer_default = WebGLArrayBuffer;

// node_modules/ol/webgl/ContextEventType.js
var ContextEventType_default = {
  LOST: "webglcontextlost",
  RESTORED: "webglcontextrestored"
};

// node_modules/ol/webgl/PostProcessingPass.js
var DEFAULT_VERTEX_SHADER = `
  precision mediump float;

  attribute vec2 a_position;
  varying vec2 v_texCoord;
  varying vec2 v_screenCoord;

  uniform vec2 u_screenSize;

  void main() {
    v_texCoord = a_position * 0.5 + 0.5;
    v_screenCoord = v_texCoord * u_screenSize;
    gl_Position = vec4(a_position, 0.0, 1.0);
  }
`;
var DEFAULT_FRAGMENT_SHADER = `
  precision mediump float;

  uniform sampler2D u_image;
  uniform float u_opacity;

  varying vec2 v_texCoord;

  void main() {
    gl_FragColor = texture2D(u_image, v_texCoord) * u_opacity;
  }
`;
var WebGLPostProcessingPass = class {
  /**
   * @param {Options} options Options.
   */
  constructor(options) {
    this.gl_ = options.webGlContext;
    const gl = this.gl_;
    this.scaleRatio_ = options.scaleRatio || 1;
    this.renderTargetTexture_ = gl.createTexture();
    this.renderTargetTextureSize_ = null;
    this.frameBuffer_ = gl.createFramebuffer();
    this.depthBuffer_ = gl.createRenderbuffer();
    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(
      vertexShader,
      options.vertexShader || DEFAULT_VERTEX_SHADER
    );
    gl.compileShader(vertexShader);
    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(
      fragmentShader,
      options.fragmentShader || DEFAULT_FRAGMENT_SHADER
    );
    gl.compileShader(fragmentShader);
    this.renderTargetProgram_ = gl.createProgram();
    gl.attachShader(this.renderTargetProgram_, vertexShader);
    gl.attachShader(this.renderTargetProgram_, fragmentShader);
    gl.linkProgram(this.renderTargetProgram_);
    this.renderTargetVerticesBuffer_ = gl.createBuffer();
    const verticesArray = [-1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1];
    gl.bindBuffer(gl.ARRAY_BUFFER, this.renderTargetVerticesBuffer_);
    gl.bufferData(
      gl.ARRAY_BUFFER,
      new Float32Array(verticesArray),
      gl.STATIC_DRAW
    );
    this.renderTargetAttribLocation_ = gl.getAttribLocation(
      this.renderTargetProgram_,
      "a_position"
    );
    this.renderTargetUniformLocation_ = gl.getUniformLocation(
      this.renderTargetProgram_,
      "u_screenSize"
    );
    this.renderTargetOpacityLocation_ = gl.getUniformLocation(
      this.renderTargetProgram_,
      "u_opacity"
    );
    this.renderTargetTextureLocation_ = gl.getUniformLocation(
      this.renderTargetProgram_,
      "u_image"
    );
    this.uniforms_ = [];
    options.uniforms && Object.keys(options.uniforms).forEach((name) => {
      this.uniforms_.push({
        value: options.uniforms[name],
        location: gl.getUniformLocation(this.renderTargetProgram_, name)
      });
    });
  }
  getRenderTargetTexture() {
    return this.renderTargetTexture_;
  }
  /**
   * Get the WebGL rendering context
   * @return {WebGLRenderingContext} The rendering context.
   */
  getGL() {
    return this.gl_;
  }
  /**
   * Initialize the render target texture of the post process, make sure it is at the
   * right size and bind it as a render target for the next draw calls.
   * The last step to be initialized will be the one where the primitives are rendered.
   * @param {import("../Map.js").FrameState} frameState current frame state
   */
  init(frameState) {
    const gl = this.getGL();
    const textureSize = [
      gl.drawingBufferWidth * this.scaleRatio_,
      gl.drawingBufferHeight * this.scaleRatio_
    ];
    gl.bindFramebuffer(gl.FRAMEBUFFER, this.getFrameBuffer());
    gl.bindRenderbuffer(gl.RENDERBUFFER, this.getDepthBuffer());
    gl.viewport(0, 0, textureSize[0], textureSize[1]);
    if (!this.renderTargetTextureSize_ || this.renderTargetTextureSize_[0] !== textureSize[0] || this.renderTargetTextureSize_[1] !== textureSize[1]) {
      this.renderTargetTextureSize_ = textureSize;
      const level = 0;
      const internalFormat = gl.RGBA;
      const border = 0;
      const format = gl.RGBA;
      const type = gl.UNSIGNED_BYTE;
      const data = null;
      gl.bindTexture(gl.TEXTURE_2D, this.renderTargetTexture_);
      gl.texImage2D(
        gl.TEXTURE_2D,
        level,
        internalFormat,
        textureSize[0],
        textureSize[1],
        border,
        format,
        type,
        data
      );
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.framebufferTexture2D(
        gl.FRAMEBUFFER,
        gl.COLOR_ATTACHMENT0,
        gl.TEXTURE_2D,
        this.renderTargetTexture_,
        0
      );
      gl.renderbufferStorage(
        gl.RENDERBUFFER,
        gl.DEPTH_COMPONENT16,
        textureSize[0],
        textureSize[1]
      );
      gl.framebufferRenderbuffer(
        gl.FRAMEBUFFER,
        gl.DEPTH_ATTACHMENT,
        gl.RENDERBUFFER,
        this.depthBuffer_
      );
    }
  }
  /**
   * Render to the next postprocessing pass (or to the canvas if final pass).
   * @param {import("../Map.js").FrameState} frameState current frame state
   * @param {WebGLPostProcessingPass} [nextPass] Next pass, optional
   * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing.
   * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing.
   */
  apply(frameState, nextPass, preCompose, postCompose) {
    const gl = this.getGL();
    const size = frameState.size;
    gl.bindFramebuffer(
      gl.FRAMEBUFFER,
      nextPass ? nextPass.getFrameBuffer() : null
    );
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, this.renderTargetTexture_);
    if (!nextPass) {
      const canvasId = getUid(gl.canvas);
      if (!frameState.renderTargets[canvasId]) {
        const attributes = gl.getContextAttributes();
        if (attributes && attributes.preserveDrawingBuffer) {
          gl.clearColor(0, 0, 0, 0);
          gl.clearDepth(1);
          gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
        }
        frameState.renderTargets[canvasId] = true;
      }
    }
    gl.disable(gl.DEPTH_TEST);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
    gl.bindBuffer(gl.ARRAY_BUFFER, this.renderTargetVerticesBuffer_);
    gl.useProgram(this.renderTargetProgram_);
    gl.enableVertexAttribArray(this.renderTargetAttribLocation_);
    gl.vertexAttribPointer(
      this.renderTargetAttribLocation_,
      2,
      gl.FLOAT,
      false,
      0,
      0
    );
    gl.uniform2f(this.renderTargetUniformLocation_, size[0], size[1]);
    gl.uniform1i(this.renderTargetTextureLocation_, 0);
    const opacity = frameState.layerStatesArray[frameState.layerIndex].opacity;
    gl.uniform1f(this.renderTargetOpacityLocation_, opacity);
    this.applyUniforms(frameState);
    if (preCompose) {
      preCompose(gl, frameState);
    }
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    if (postCompose) {
      postCompose(gl, frameState);
    }
  }
  /**
   * @return {WebGLFramebuffer} Frame buffer
   */
  getFrameBuffer() {
    return this.frameBuffer_;
  }
  /**
   * @return {WebGLRenderbuffer} Depth buffer
   */
  getDepthBuffer() {
    return this.depthBuffer_;
  }
  /**
   * Sets the custom uniforms based on what was given in the constructor.
   * @param {import("../Map.js").FrameState} frameState Frame state.
   * @private
   */
  applyUniforms(frameState) {
    const gl = this.getGL();
    let value;
    let textureSlot = 1;
    this.uniforms_.forEach(function(uniform) {
      value = typeof uniform.value === "function" ? uniform.value(frameState) : uniform.value;
      if (value instanceof HTMLCanvasElement || value instanceof ImageData) {
        if (!uniform.texture) {
          uniform.texture = gl.createTexture();
        }
        gl.activeTexture(gl[`TEXTURE${textureSlot}`]);
        gl.bindTexture(gl.TEXTURE_2D, uniform.texture);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        if (value instanceof ImageData) {
          gl.texImage2D(
            gl.TEXTURE_2D,
            0,
            gl.RGBA,
            gl.RGBA,
            value.width,
            value.height,
            0,
            gl.UNSIGNED_BYTE,
            new Uint8Array(value.data)
          );
        } else {
          gl.texImage2D(
            gl.TEXTURE_2D,
            0,
            gl.RGBA,
            gl.RGBA,
            gl.UNSIGNED_BYTE,
            value
          );
        }
        gl.uniform1i(uniform.location, textureSlot++);
      } else if (Array.isArray(value)) {
        switch (value.length) {
          case 2:
            gl.uniform2f(uniform.location, value[0], value[1]);
            return;
          case 3:
            gl.uniform3f(uniform.location, value[0], value[1], value[2]);
            return;
          case 4:
            gl.uniform4f(
              uniform.location,
              value[0],
              value[1],
              value[2],
              value[3]
            );
            return;
          default:
            return;
        }
      } else if (typeof value === "number") {
        gl.uniform1f(uniform.location, value);
      }
    });
  }
};
var PostProcessingPass_default = WebGLPostProcessingPass;

// node_modules/ol/webgl/Helper.js
var DefaultUniform = {
  PROJECTION_MATRIX: "u_projectionMatrix",
  SCREEN_TO_WORLD_MATRIX: "u_screenToWorldMatrix",
  TIME: "u_time",
  ZOOM: "u_zoom",
  RESOLUTION: "u_resolution",
  ROTATION: "u_rotation",
  VIEWPORT_SIZE_PX: "u_viewportSizePx",
  PIXEL_RATIO: "u_pixelRatio",
  HIT_DETECTION: "u_hitDetection"
};
var AttributeType = {
  UNSIGNED_BYTE,
  UNSIGNED_SHORT,
  UNSIGNED_INT,
  FLOAT
};
var canvasCache = {};
function getSharedCanvasCacheKey(key) {
  return "shared/" + key;
}
var uniqueCanvasCacheKeyCount = 0;
function getUniqueCanvasCacheKey() {
  const key = "unique/" + uniqueCanvasCacheKeyCount;
  uniqueCanvasCacheKeyCount += 1;
  return key;
}
function getOrCreateContext(key) {
  let cacheItem = canvasCache[key];
  if (!cacheItem) {
    const canvas = document.createElement("canvas");
    canvas.width = 1;
    canvas.height = 1;
    canvas.style.position = "absolute";
    canvas.style.left = "0";
    const context = getContext(canvas);
    cacheItem = { users: 0, context };
    canvasCache[key] = cacheItem;
  }
  cacheItem.users += 1;
  return cacheItem.context;
}
function releaseCanvas(key) {
  const cacheItem = canvasCache[key];
  if (!cacheItem) {
    return;
  }
  cacheItem.users -= 1;
  if (cacheItem.users > 0) {
    return;
  }
  const gl = cacheItem.context;
  const extension = gl.getExtension("WEBGL_lose_context");
  if (extension) {
    extension.loseContext();
  }
  const canvas = gl.canvas;
  canvas.width = 1;
  canvas.height = 1;
  delete canvasCache[key];
}
var WebGLHelper = class extends Disposable_default {
  /**
   * @param {Options} [options] Options.
   */
  constructor(options) {
    super();
    options = options || {};
    this.boundHandleWebGLContextLost_ = this.handleWebGLContextLost.bind(this);
    this.boundHandleWebGLContextRestored_ = this.handleWebGLContextRestored.bind(this);
    this.canvasCacheKey_ = options.canvasCacheKey ? getSharedCanvasCacheKey(options.canvasCacheKey) : getUniqueCanvasCacheKey();
    this.gl_ = getOrCreateContext(this.canvasCacheKey_);
    this.bufferCache_ = {};
    this.extensionCache_ = {};
    this.currentProgram_ = null;
    this.needsToBeRecreated_ = false;
    const canvas = this.gl_.canvas;
    canvas.addEventListener(
      ContextEventType_default.LOST,
      this.boundHandleWebGLContextLost_
    );
    canvas.addEventListener(
      ContextEventType_default.RESTORED,
      this.boundHandleWebGLContextRestored_
    );
    this.offsetRotateMatrix_ = create();
    this.offsetScaleMatrix_ = create();
    this.tmpMat4_ = create2();
    this.uniformLocationsByProgram_ = {};
    this.attribLocationsByProgram_ = {};
    this.uniforms_ = [];
    if (options.uniforms) {
      this.setUniforms(options.uniforms);
    }
    this.postProcessPasses_ = options.postProcesses ? options.postProcesses.map(
      (options2) => new PostProcessingPass_default({
        webGlContext: this.gl_,
        scaleRatio: options2.scaleRatio,
        vertexShader: options2.vertexShader,
        fragmentShader: options2.fragmentShader,
        uniforms: options2.uniforms
      })
    ) : [new PostProcessingPass_default({ webGlContext: this.gl_ })];
    this.shaderCompileErrors_ = null;
    this.startTime_ = Date.now();
    this.maxAttributeCount_ = this.gl_.getParameter(
      this.gl_.MAX_VERTEX_ATTRIBS
    );
  }
  /**
   * @param {Object<string, UniformValue>} uniforms Uniform definitions.
   */
  setUniforms(uniforms) {
    this.uniforms_ = [];
    this.addUniforms(uniforms);
  }
  /**
   * @param {Object<string, UniformValue>} uniforms Uniform definitions.
   */
  addUniforms(uniforms) {
    for (const name in uniforms) {
      this.uniforms_.push({
        name,
        value: uniforms[name]
      });
    }
  }
  /**
   * @param {string} canvasCacheKey The canvas cache key.
   * @return {boolean} The provided key matches the one this helper was constructed with.
   */
  canvasCacheKeyMatches(canvasCacheKey) {
    return this.canvasCacheKey_ === getSharedCanvasCacheKey(canvasCacheKey);
  }
  /**
   * Get a WebGL extension.  If the extension is not supported, null is returned.
   * Extensions are cached after they are enabled for the first time.
   * @param {string} name The extension name.
   * @return {Object|null} The extension or null if not supported.
   */
  getExtension(name) {
    if (name in this.extensionCache_) {
      return this.extensionCache_[name];
    }
    const extension = this.gl_.getExtension(name);
    this.extensionCache_[name] = extension;
    return extension;
  }
  /**
   * Will throw if the extension is not available
   * @return {ANGLE_instanced_arrays} Extension
   */
  getInstancedRenderingExtension_() {
    const ext = this.getExtension("ANGLE_instanced_arrays");
    assert(
      !!ext,
      "WebGL extension 'ANGLE_instanced_arrays' is required for vector rendering"
    );
    return ext;
  }
  /**
   * Just bind the buffer if it's in the cache. Otherwise create
   * the WebGL buffer, bind it, populate it, and add an entry to
   * the cache.
   * @param {import("./Buffer").default} buffer Buffer.
   */
  bindBuffer(buffer2) {
    const gl = this.gl_;
    const bufferKey = getUid(buffer2);
    let bufferCache = this.bufferCache_[bufferKey];
    if (!bufferCache) {
      const webGlBuffer = gl.createBuffer();
      bufferCache = {
        buffer: buffer2,
        webGlBuffer
      };
      this.bufferCache_[bufferKey] = bufferCache;
    }
    gl.bindBuffer(buffer2.getType(), bufferCache.webGlBuffer);
  }
  /**
   * Update the data contained in the buffer array; this is required for the
   * new data to be rendered
   * @param {import("./Buffer").default} buffer Buffer.
   */
  flushBufferData(buffer2) {
    const gl = this.gl_;
    this.bindBuffer(buffer2);
    gl.bufferData(buffer2.getType(), buffer2.getArray(), buffer2.getUsage());
  }
  /**
   * @param {import("./Buffer.js").default} buf Buffer.
   */
  deleteBuffer(buf) {
    const bufferKey = getUid(buf);
    delete this.bufferCache_[bufferKey];
  }
  /**
   * Clean up.
   * @override
   */
  disposeInternal() {
    const canvas = this.gl_.canvas;
    canvas.removeEventListener(
      ContextEventType_default.LOST,
      this.boundHandleWebGLContextLost_
    );
    canvas.removeEventListener(
      ContextEventType_default.RESTORED,
      this.boundHandleWebGLContextRestored_
    );
    releaseCanvas(this.canvasCacheKey_);
    delete this.gl_;
  }
  /**
   * Clear the buffer & set the viewport to draw.
   * Post process passes will be initialized here, the first one being bound as a render target for
   * subsequent draw calls.
   * @param {import("../Map.js").FrameState} frameState current frame state
   * @param {boolean} [disableAlphaBlend] If true, no alpha blending will happen.
   * @param {boolean} [enableDepth] If true, enables depth testing.
   */
  prepareDraw(frameState, disableAlphaBlend, enableDepth) {
    const gl = this.gl_;
    const canvas = this.getCanvas();
    const size = frameState.size;
    const pixelRatio = frameState.pixelRatio;
    if (canvas.width !== size[0] * pixelRatio || canvas.height !== size[1] * pixelRatio) {
      canvas.width = size[0] * pixelRatio;
      canvas.height = size[1] * pixelRatio;
      canvas.style.width = size[0] + "px";
      canvas.style.height = size[1] + "px";
    }
    for (let i = this.postProcessPasses_.length - 1; i >= 0; i--) {
      this.postProcessPasses_[i].init(frameState);
    }
    gl.bindTexture(gl.TEXTURE_2D, null);
    gl.clearColor(0, 0, 0, 0);
    gl.depthRange(0, 1);
    gl.clearDepth(1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.ONE, disableAlphaBlend ? gl.ZERO : gl.ONE_MINUS_SRC_ALPHA);
    if (enableDepth) {
      gl.enable(gl.DEPTH_TEST);
      gl.depthFunc(gl.LEQUAL);
    } else {
      gl.disable(gl.DEPTH_TEST);
    }
  }
  /**
   * @param {WebGLFramebuffer|null} frameBuffer The frame buffer.
   * @param {WebGLTexture} [texture] The texture.
   */
  bindFrameBuffer(frameBuffer, texture) {
    const gl = this.getGL();
    gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
    if (texture) {
      gl.framebufferTexture2D(
        gl.FRAMEBUFFER,
        gl.COLOR_ATTACHMENT0,
        gl.TEXTURE_2D,
        texture,
        0
      );
    }
  }
  /**
   * Bind the frame buffer from the initial render.
   */
  bindInitialFrameBuffer() {
    const gl = this.getGL();
    const frameBuffer = this.postProcessPasses_[0].getFrameBuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
    const texture = this.postProcessPasses_[0].getRenderTargetTexture();
    gl.framebufferTexture2D(
      gl.FRAMEBUFFER,
      gl.COLOR_ATTACHMENT0,
      gl.TEXTURE_2D,
      texture,
      0
    );
  }
  /**
   * Prepare a program to use a texture.
   * @param {WebGLTexture} texture The texture.
   * @param {number} slot The texture slot.
   * @param {string} uniformName The corresponding uniform name.
   */
  bindTexture(texture, slot, uniformName) {
    const gl = this.gl_;
    gl.activeTexture(gl.TEXTURE0 + slot);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.uniform1i(this.getUniformLocation(uniformName), slot);
  }
  /**
   * Set up an attribute array buffer for use in the vertex shader.
   * @param {import("./Buffer").default} buffer The buffer.
   * @param {string} attributeName The attribute name.
   * @param {number} size The number of components per attribute vertex.
   */
  bindAttribute(buffer2, attributeName, size) {
    const gl = this.getGL();
    this.bindBuffer(buffer2);
    const index = this.getAttributeLocation(attributeName);
    gl.enableVertexAttribArray(index);
    gl.vertexAttribPointer(index, size, gl.FLOAT, false, 0, 0);
  }
  /**
   * Clear the render target & bind it for future draw operations.
   * This is similar to `prepareDraw`, only post processes will not be applied.
   * Note: the whole viewport will be drawn to the render target, regardless of its size.
   * @param {import("../Map.js").FrameState} frameState current frame state
   * @param {import("./RenderTarget.js").default} renderTarget Render target to draw to
   * @param {boolean} [disableAlphaBlend] If true, no alpha blending will happen.
   * @param {boolean} [enableDepth] If true, enables depth testing.
   */
  prepareDrawToRenderTarget(frameState, renderTarget, disableAlphaBlend, enableDepth) {
    const gl = this.gl_;
    const size = renderTarget.getSize();
    gl.bindFramebuffer(gl.FRAMEBUFFER, renderTarget.getFramebuffer());
    gl.bindRenderbuffer(gl.RENDERBUFFER, renderTarget.getDepthbuffer());
    gl.viewport(0, 0, size[0], size[1]);
    gl.bindTexture(gl.TEXTURE_2D, renderTarget.getTexture());
    gl.clearColor(0, 0, 0, 0);
    gl.depthRange(0, 1);
    gl.clearDepth(1);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.ONE, disableAlphaBlend ? gl.ZERO : gl.ONE_MINUS_SRC_ALPHA);
    if (enableDepth) {
      gl.enable(gl.DEPTH_TEST);
      gl.depthFunc(gl.LEQUAL);
    } else {
      gl.disable(gl.DEPTH_TEST);
    }
  }
  /**
   * Execute a draw call based on the currently bound program, texture, buffers, attributes.
   * @param {number} start Start index.
   * @param {number} end End index.
   */
  drawElements(start, end) {
    const gl = this.gl_;
    this.getExtension("OES_element_index_uint");
    const elementType = gl.UNSIGNED_INT;
    const elementSize = 4;
    const numItems = end - start;
    const offsetInBytes = start * elementSize;
    gl.drawElements(gl.TRIANGLES, numItems, elementType, offsetInBytes);
  }
  /**
   * Execute a draw call similar to `drawElements`, but using instanced rendering.
   * Will have no effect if `enableAttributesInstanced` was not called for this rendering pass.
   * @param {number} start Start index.
   * @param {number} end End index.
   * @param {number} instanceCount The number of instances to render
   */
  drawElementsInstanced(start, end, instanceCount) {
    const gl = this.gl_;
    this.getExtension("OES_element_index_uint");
    const ext = this.getInstancedRenderingExtension_();
    const elementType = gl.UNSIGNED_INT;
    const elementSize = 4;
    const numItems = end - start;
    const offsetInBytes = start * elementSize;
    ext.drawElementsInstancedANGLE(
      gl.TRIANGLES,
      numItems,
      elementType,
      offsetInBytes,
      instanceCount
    );
    for (let i = 0; i < this.maxAttributeCount_; i++) {
      ext.vertexAttribDivisorANGLE(i, 0);
    }
  }
  /**
   * Apply the successive post process passes which will eventually render to the actual canvas.
   * @param {import("../Map.js").FrameState} frameState current frame state
   * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [preCompose] Called before composing.
   * @param {function(WebGLRenderingContext, import("../Map.js").FrameState):void} [postCompose] Called before composing.
   */
  finalizeDraw(frameState, preCompose, postCompose) {
    for (let i = 0, ii = this.postProcessPasses_.length; i < ii; i++) {
      if (i === ii - 1) {
        this.postProcessPasses_[i].apply(
          frameState,
          null,
          preCompose,
          postCompose
        );
      } else {
        this.postProcessPasses_[i].apply(
          frameState,
          this.postProcessPasses_[i + 1]
        );
      }
    }
  }
  /**
   * @return {HTMLCanvasElement} Canvas.
   */
  getCanvas() {
    return (
      /** @type {HTMLCanvasElement} */
      this.gl_.canvas
    );
  }
  /**
   * Get the WebGL rendering context
   * @return {WebGLRenderingContext} The rendering context.
   */
  getGL() {
    return this.gl_;
  }
  /**
   * Sets the default matrix uniforms for a given frame state. This is called internally in `prepareDraw`.
   * @param {import("../Map.js").FrameState} frameState Frame state.
   */
  applyFrameState(frameState) {
    const size = frameState.size;
    const rotation = frameState.viewState.rotation;
    const pixelRatio = frameState.pixelRatio;
    this.setUniformFloatValue(
      DefaultUniform.TIME,
      (Date.now() - this.startTime_) * 1e-3
    );
    this.setUniformFloatValue(DefaultUniform.ZOOM, frameState.viewState.zoom);
    this.setUniformFloatValue(
      DefaultUniform.RESOLUTION,
      frameState.viewState.resolution
    );
    this.setUniformFloatValue(DefaultUniform.PIXEL_RATIO, pixelRatio);
    this.setUniformFloatVec2(DefaultUniform.VIEWPORT_SIZE_PX, [
      size[0],
      size[1]
    ]);
    this.setUniformFloatValue(DefaultUniform.ROTATION, rotation);
  }
  /**
   * Sets the `u_hitDetection` uniform.
   * @param {boolean} enabled Whether to enable the hit detection code path
   */
  applyHitDetectionUniform(enabled) {
    const loc = this.getUniformLocation(DefaultUniform.HIT_DETECTION);
    this.getGL().uniform1i(loc, enabled ? 1 : 0);
    if (enabled) {
      this.setUniformFloatValue(DefaultUniform.PIXEL_RATIO, 0.5);
    }
  }
  /**
   * Sets the custom uniforms based on what was given in the constructor. This is called internally in `prepareDraw`.
   * @param {import("../Map.js").FrameState} frameState Frame state.
   */
  applyUniforms(frameState) {
    const gl = this.gl_;
    let value;
    let textureSlot = 0;
    this.uniforms_.forEach((uniform) => {
      value = typeof uniform.value === "function" ? uniform.value(frameState) : uniform.value;
      if (value instanceof HTMLCanvasElement || value instanceof HTMLImageElement || value instanceof ImageData || value instanceof WebGLTexture) {
        if (value instanceof WebGLTexture && !uniform.texture) {
          uniform.prevValue = void 0;
          uniform.texture = value;
        } else if (!uniform.texture) {
          uniform.prevValue = void 0;
          uniform.texture = gl.createTexture();
        }
        this.bindTexture(uniform.texture, textureSlot, uniform.name);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        const imageReady = !(value instanceof HTMLImageElement) || /** @type {HTMLImageElement} */
        value.complete;
        if (!(value instanceof WebGLTexture) && imageReady && uniform.prevValue !== value) {
          uniform.prevValue = value;
          gl.texImage2D(
            gl.TEXTURE_2D,
            0,
            gl.RGBA,
            gl.RGBA,
            gl.UNSIGNED_BYTE,
            value
          );
        }
        textureSlot++;
      } else if (Array.isArray(value) && value.length === 6) {
        this.setUniformMatrixValue(
          uniform.name,
          fromTransform(this.tmpMat4_, value)
        );
      } else if (Array.isArray(value) && value.length <= 4) {
        switch (value.length) {
          case 2:
            gl.uniform2f(
              this.getUniformLocation(uniform.name),
              value[0],
              value[1]
            );
            return;
          case 3:
            gl.uniform3f(
              this.getUniformLocation(uniform.name),
              value[0],
              value[1],
              value[2]
            );
            return;
          case 4:
            gl.uniform4f(
              this.getUniformLocation(uniform.name),
              value[0],
              value[1],
              value[2],
              value[3]
            );
            return;
          default:
            return;
        }
      } else if (typeof value === "number") {
        gl.uniform1f(this.getUniformLocation(uniform.name), value);
      }
    });
  }
  /**
   * Set up a program for use. The program will be set as the current one. Then, the uniforms used
   * in the program will be set based on the current frame state and the helper configuration.
   * @param {WebGLProgram} program Program.
   * @param {import("../Map.js").FrameState} [frameState] Frame state.
   */
  useProgram(program, frameState) {
    this.disableAllAttributes_();
    const gl = this.gl_;
    gl.useProgram(program);
    this.currentProgram_ = program;
    if (frameState) {
      this.applyFrameState(frameState);
      this.applyUniforms(frameState);
    }
  }
  /**
   * Will attempt to compile a vertex or fragment shader based on source
   * On error, the shader will be returned but
   * `gl.getShaderParameter(shader, gl.COMPILE_STATUS)` will return `true`
   * Use `gl.getShaderInfoLog(shader)` to have details
   * @param {string} source Shader source
   * @param {ShaderType} type VERTEX_SHADER or FRAGMENT_SHADER
   * @return {WebGLShader} Shader object
   */
  compileShader(source, type) {
    const gl = this.gl_;
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    return shader;
  }
  /**
   * Create a program for a vertex and fragment shader.  Throws if shader compilation fails.
   * @param {string} fragmentShaderSource Fragment shader source.
   * @param {string} vertexShaderSource Vertex shader source.
   * @return {WebGLProgram} Program
   */
  getProgram(fragmentShaderSource, vertexShaderSource) {
    const gl = this.gl_;
    const fragmentShader = this.compileShader(
      fragmentShaderSource,
      gl.FRAGMENT_SHADER
    );
    const vertexShader = this.compileShader(
      vertexShaderSource,
      gl.VERTEX_SHADER
    );
    const program = gl.createProgram();
    gl.attachShader(program, fragmentShader);
    gl.attachShader(program, vertexShader);
    gl.linkProgram(program);
    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
      const message = `Fragment shader compilation failed: ${gl.getShaderInfoLog(
        fragmentShader
      )}`;
      throw new Error(message);
    }
    gl.deleteShader(fragmentShader);
    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
      const message = `Vertex shader compilation failed: ${gl.getShaderInfoLog(
        vertexShader
      )}`;
      throw new Error(message);
    }
    gl.deleteShader(vertexShader);
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
      const message = `GL program linking failed: ${gl.getProgramInfoLog(
        program
      )}`;
      throw new Error(message);
    }
    return program;
  }
  /**
   * Will get the location from the shader or the cache
   * @param {string} name Uniform name
   * @return {WebGLUniformLocation} uniformLocation
   */
  getUniformLocation(name) {
    const programUid = getUid(this.currentProgram_);
    if (this.uniformLocationsByProgram_[programUid] === void 0) {
      this.uniformLocationsByProgram_[programUid] = {};
    }
    if (this.uniformLocationsByProgram_[programUid][name] === void 0) {
      this.uniformLocationsByProgram_[programUid][name] = this.gl_.getUniformLocation(this.currentProgram_, name);
    }
    return this.uniformLocationsByProgram_[programUid][name];
  }
  /**
   * Will get the location from the shader or the cache
   * @param {string} name Attribute name
   * @return {number} attribLocation
   */
  getAttributeLocation(name) {
    const programUid = getUid(this.currentProgram_);
    if (this.attribLocationsByProgram_[programUid] === void 0) {
      this.attribLocationsByProgram_[programUid] = {};
    }
    if (this.attribLocationsByProgram_[programUid][name] === void 0) {
      this.attribLocationsByProgram_[programUid][name] = this.gl_.getAttribLocation(this.currentProgram_, name);
    }
    return this.attribLocationsByProgram_[programUid][name];
  }
  /**
   * Sets the given transform to apply the rotation/translation/scaling of the given frame state.
   * The resulting transform can be used to convert world space coordinates to view coordinates in the [-1, 1] range.
   * @param {import("../Map.js").FrameState} frameState Frame state.
   * @param {import("../transform").Transform} transform Transform to update.
   * @return {import("../transform").Transform} The updated transform object.
   */
  makeProjectionTransform(frameState, transform) {
    const size = frameState.size;
    const rotation = frameState.viewState.rotation;
    const resolution = frameState.viewState.resolution;
    const center = frameState.viewState.center;
    compose(
      transform,
      0,
      0,
      2 / (resolution * size[0]),
      2 / (resolution * size[1]),
      -rotation,
      -center[0],
      -center[1]
    );
    return transform;
  }
  /**
   * Give a value for a standard float uniform
   * @param {string} uniform Uniform name
   * @param {number} value Value
   */
  setUniformFloatValue(uniform, value) {
    this.gl_.uniform1f(this.getUniformLocation(uniform), value);
  }
  /**
   * Give a value for a vec2 uniform
   * @param {string} uniform Uniform name
   * @param {Array<number>} value Array of length 4.
   */
  setUniformFloatVec2(uniform, value) {
    this.gl_.uniform2fv(this.getUniformLocation(uniform), value);
  }
  /**
   * Give a value for a vec4 uniform
   * @param {string} uniform Uniform name
   * @param {Array<number>} value Array of length 4.
   */
  setUniformFloatVec4(uniform, value) {
    this.gl_.uniform4fv(this.getUniformLocation(uniform), value);
  }
  /**
   * Give a value for a standard matrix4 uniform
   * @param {string} uniform Uniform name
   * @param {Array<number>} value Matrix value
   */
  setUniformMatrixValue(uniform, value) {
    this.gl_.uniformMatrix4fv(this.getUniformLocation(uniform), false, value);
  }
  /**
   * Disable all vertex attributes.
   * @private
   */
  disableAllAttributes_() {
    for (let i = 0; i < this.maxAttributeCount_; i++) {
      this.gl_.disableVertexAttribArray(i);
    }
  }
  /**
   * Will set the currently bound buffer to an attribute of the shader program. Used by `#enableAttributes`
   * internally.
   * @param {string} attribName Attribute name
   * @param {number} size Number of components per attributes
   * @param {number} type UNSIGNED_INT, UNSIGNED_BYTE, UNSIGNED_SHORT or FLOAT
   * @param {number} stride Stride in bytes (0 means attribs are packed)
   * @param {number} offset Offset in bytes
   * @param {boolean} instanced Whether the attribute is used for instanced rendering
   * @private
   */
  enableAttributeArray_(attribName, size, type, stride, offset, instanced) {
    const location = this.getAttributeLocation(attribName);
    if (location < 0) {
      return;
    }
    this.gl_.enableVertexAttribArray(location);
    this.gl_.vertexAttribPointer(location, size, type, false, stride, offset);
    if (instanced) {
      this.getInstancedRenderingExtension_().vertexAttribDivisorANGLE(
        location,
        1
      );
    }
  }
  /**
   * @private
   * @param {Array<AttributeDescription>} attributes Ordered list of attributes to read from the buffer
   * @param {boolean} instanced Whether the attributes are instanced.
   */
  enableAttributes_(attributes, instanced) {
    const stride = computeAttributesStride(attributes);
    let offset = 0;
    for (let i = 0; i < attributes.length; i++) {
      const attr = attributes[i];
      if (attr.name) {
        this.enableAttributeArray_(
          attr.name,
          attr.size,
          attr.type || FLOAT,
          stride,
          offset,
          instanced
        );
      }
      offset += attr.size * getByteSizeFromType(attr.type);
    }
  }
  /**
   * Will enable the following attributes to be read from the currently bound buffer,
   * i.e. tell the GPU where to read the different attributes in the buffer. An error in the
   * size/type/order of attributes will most likely break the rendering and throw a WebGL exception.
   * @param {Array<AttributeDescription>} attributes Ordered list of attributes to read from the buffer
   */
  enableAttributes(attributes) {
    this.enableAttributes_(attributes, false);
  }
  /**
   * Will enable these attributes as instanced, meaning that they will only be read
   * once per instance instead of per vertex.
   * @param {Array<AttributeDescription>} attributes Ordered list of attributes to read from the buffer
   */
  enableAttributesInstanced(attributes) {
    this.enableAttributes_(attributes, true);
  }
  /**
   * WebGL context was lost
   * @param {WebGLContextEvent} event The context loss event.
   * @private
   */
  handleWebGLContextLost(event) {
    clear(this.bufferCache_);
    this.currentProgram_ = null;
    event.preventDefault();
  }
  /**
   * WebGL context was restored
   * @private
   */
  handleWebGLContextRestored() {
    this.needsToBeRecreated_ = true;
  }
  /**
   * Returns whether this helper needs to be recreated, as the context was lost and then restored.
   * @return {boolean} Whether this helper needs to be recreated.
   */
  needsToBeRecreated() {
    return this.needsToBeRecreated_;
  }
  /**
   * Will create or reuse a given webgl texture and apply the given size. If no image data
   * specified, the texture will be empty, otherwise image data will be used and the `size`
   * parameter will be ignored.  If a Uint8Array is provided for data, a size must also be provided.
   * Note: wrap parameters are set to clamp to edge, min filter is set to linear.
   * @param {Array<number>} size Expected size of the texture
   * @param {ImageData|HTMLImageElement|HTMLCanvasElement|Uint8Array|null} data Image data/object to bind to the texture
   * @param {WebGLTexture} [texture] Existing texture to reuse
   * @param {boolean} [nearest] Use gl.NEAREST for min/mag filter.
   * @return {WebGLTexture} The generated texture
   */
  createTexture(size, data, texture, nearest) {
    const gl = this.gl_;
    texture = texture || gl.createTexture();
    const filter = nearest ? gl.NEAREST : gl.LINEAR;
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    const level = 0;
    const internalFormat = gl.RGBA;
    const border = 0;
    const format = gl.RGBA;
    const type = gl.UNSIGNED_BYTE;
    if (data instanceof Uint8Array) {
      gl.texImage2D(
        gl.TEXTURE_2D,
        level,
        internalFormat,
        size[0],
        size[1],
        border,
        format,
        type,
        data
      );
    } else if (data) {
      gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, format, type, data);
    } else {
      gl.texImage2D(
        gl.TEXTURE_2D,
        level,
        internalFormat,
        size[0],
        size[1],
        border,
        format,
        type,
        null
      );
    }
    return texture;
  }
};
function computeAttributesStride(attributes) {
  let stride = 0;
  for (let i = 0; i < attributes.length; i++) {
    const attr = attributes[i];
    stride += attr.size * getByteSizeFromType(attr.type);
  }
  return stride;
}
function getByteSizeFromType(type) {
  switch (type) {
    case AttributeType.UNSIGNED_BYTE:
      return Uint8Array.BYTES_PER_ELEMENT;
    case AttributeType.UNSIGNED_SHORT:
      return Uint16Array.BYTES_PER_ELEMENT;
    case AttributeType.UNSIGNED_INT:
      return Uint32Array.BYTES_PER_ELEMENT;
    case AttributeType.FLOAT:
    default:
      return Float32Array.BYTES_PER_ELEMENT;
  }
}
var Helper_default = WebGLHelper;

// node_modules/ol/webgl/BaseTileRepresentation.js
var BaseTileRepresentation = class extends Target_default {
  /**
   * @param {TileRepresentationOptions<TileType>} options The tile representation options.
   */
  constructor(options) {
    super();
    this.tile;
    this.handleTileChange_ = this.handleTileChange_.bind(this);
    this.gutter = options.gutter || 0;
    this.helper = options.helper;
    this.loaded = false;
    this.ready = false;
  }
  /**
   * @param {TileType} tile Tile.
   */
  setTile(tile) {
    if (tile !== this.tile) {
      if (this.tile) {
        this.tile.removeEventListener(EventType_default.CHANGE, this.handleTileChange_);
      }
      this.tile = tile;
      this.loaded = tile.getState() === TileState_default.LOADED;
      if (this.loaded) {
        this.uploadTile();
      } else {
        if (tile instanceof ImageTile_default) {
          const image = tile.getImage();
          if (image instanceof Image && !image.crossOrigin) {
            image.crossOrigin = "anonymous";
          }
        }
        tile.addEventListener(EventType_default.CHANGE, this.handleTileChange_);
      }
    }
  }
  /**
   * @abstract
   * @protected
   */
  uploadTile() {
    abstract();
  }
  setReady() {
    this.ready = true;
    this.dispatchEvent(EventType_default.CHANGE);
  }
  handleTileChange_() {
    if (this.tile.getState() === TileState_default.LOADED) {
      this.loaded = true;
      this.uploadTile();
    }
  }
  /**
   * @param {import("./Helper.js").default} helper The WebGL helper.
   */
  setHelper(helper) {
    this.helper = helper;
    if (this.helper && this.loaded) {
      this.uploadTile();
    }
  }
  /**
   * @override
   */
  disposeInternal() {
    this.setHelper(null);
    this.tile.removeEventListener(EventType_default.CHANGE, this.handleTileChange_);
  }
};
var BaseTileRepresentation_default = BaseTileRepresentation;

// node_modules/ol/webgl/TileTexture.js
function bindAndConfigure(gl, texture, interpolate) {
  const resampleFilter = interpolate ? gl.LINEAR : gl.NEAREST;
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, resampleFilter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, resampleFilter);
}
function uploadImageTexture(gl, texture, image, interpolate) {
  bindAndConfigure(gl, texture, interpolate);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
}
function uploadDataTexture(helper, texture, data, size, bandCount, interpolate) {
  const gl = helper.getGL();
  let textureType;
  let canInterpolate;
  if (data instanceof Float32Array) {
    textureType = gl.FLOAT;
    helper.getExtension("OES_texture_float");
    const extension = helper.getExtension("OES_texture_float_linear");
    canInterpolate = extension !== null;
  } else {
    textureType = gl.UNSIGNED_BYTE;
    canInterpolate = true;
  }
  bindAndConfigure(gl, texture, interpolate && canInterpolate);
  const bytesPerRow = data.byteLength / size[1];
  let unpackAlignment = 1;
  if (bytesPerRow % 8 === 0) {
    unpackAlignment = 8;
  } else if (bytesPerRow % 4 === 0) {
    unpackAlignment = 4;
  } else if (bytesPerRow % 2 === 0) {
    unpackAlignment = 2;
  }
  let format;
  switch (bandCount) {
    case 1: {
      format = gl.LUMINANCE;
      break;
    }
    case 2: {
      format = gl.LUMINANCE_ALPHA;
      break;
    }
    case 3: {
      format = gl.RGB;
      break;
    }
    case 4: {
      format = gl.RGBA;
      break;
    }
    default: {
      throw new Error(`Unsupported number of bands: ${bandCount}`);
    }
  }
  const oldUnpackAlignment = gl.getParameter(gl.UNPACK_ALIGNMENT);
  gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);
  gl.texImage2D(
    gl.TEXTURE_2D,
    0,
    format,
    size[0],
    size[1],
    0,
    format,
    textureType,
    data
  );
  gl.pixelStorei(gl.UNPACK_ALIGNMENT, oldUnpackAlignment);
}
var pixelContext = null;
function createPixelContext() {
  pixelContext = createCanvasContext2D(1, 1, void 0, {
    willReadFrequently: true
  });
}
var TileTexture = class extends BaseTileRepresentation_default {
  /**
   * @param {import("./BaseTileRepresentation.js").TileRepresentationOptions<TileType>} options The tile texture options.
   */
  constructor(options) {
    super(options);
    this.textures = [];
    this.renderSize_ = toSize(
      options.grid.getTileSize(options.tile.tileCoord[0])
    );
    this.bandCount = NaN;
    const coords = new Buffer_default(ARRAY_BUFFER, STATIC_DRAW);
    coords.fromArray([
      0,
      // P0
      1,
      1,
      // P1
      1,
      1,
      // P2
      0,
      0,
      // P3
      0
    ]);
    this.helper.flushBufferData(coords);
    this.coords = coords;
    this.setTile(options.tile);
  }
  /**
   * @override
   * @param {import("./Helper.js").default} helper The WebGL helper.
   */
  setHelper(helper) {
    var _a;
    const gl = (_a = this.helper) == null ? void 0 : _a.getGL();
    if (gl) {
      this.helper.deleteBuffer(this.coords);
      for (let i = 0; i < this.textures.length; ++i) {
        gl.deleteTexture(this.textures[i]);
      }
    }
    super.setHelper(helper);
    if (helper) {
      helper.flushBufferData(this.coords);
    }
  }
  /**
   * @override
   */
  uploadTile() {
    const helper = this.helper;
    const gl = helper.getGL();
    const tile = this.tile;
    this.textures.length = 0;
    let data;
    if (tile instanceof ImageTile_default || tile instanceof Tile_default) {
      data = tile.getImage();
    } else {
      data = tile.getData();
    }
    const image = asImageLike(data);
    if (image) {
      const texture = gl.createTexture();
      this.textures.push(texture);
      this.bandCount = 4;
      uploadImageTexture(gl, texture, image, tile.interpolate);
      this.setReady();
      return;
    }
    data = asArrayLike(data);
    const sourceTileSize = (
      /** @type {DataTile} */
      tile.getSize()
    );
    const pixelSize = [
      sourceTileSize[0] + 2 * this.gutter,
      sourceTileSize[1] + 2 * this.gutter
    ];
    const isFloat = data instanceof Float32Array;
    const pixelCount = pixelSize[0] * pixelSize[1];
    const DataType = isFloat ? Float32Array : Uint8Array;
    const bytesPerElement = DataType.BYTES_PER_ELEMENT;
    const bytesPerRow = data.byteLength / pixelSize[1];
    this.bandCount = Math.floor(bytesPerRow / bytesPerElement / pixelSize[0]);
    const textureCount = Math.ceil(this.bandCount / 4);
    if (textureCount === 1) {
      const texture = gl.createTexture();
      this.textures.push(texture);
      uploadDataTexture(
        helper,
        texture,
        data,
        pixelSize,
        this.bandCount,
        tile.interpolate
      );
      this.setReady();
      return;
    }
    const textureDataArrays = new Array(textureCount);
    for (let textureIndex = 0; textureIndex < textureCount; ++textureIndex) {
      const texture = gl.createTexture();
      this.textures.push(texture);
      const bandCount = textureIndex < textureCount - 1 ? 4 : (this.bandCount - 1) % 4 + 1;
      textureDataArrays[textureIndex] = new DataType(pixelCount * bandCount);
    }
    let dataIndex = 0;
    let rowOffset = 0;
    const colCount = pixelSize[0] * this.bandCount;
    for (let rowIndex = 0; rowIndex < pixelSize[1]; ++rowIndex) {
      for (let colIndex = 0; colIndex < colCount; ++colIndex) {
        const dataValue = data[rowOffset + colIndex];
        const pixelIndex = Math.floor(dataIndex / this.bandCount);
        const bandIndex = colIndex % this.bandCount;
        const textureIndex = Math.floor(bandIndex / 4);
        const textureData = textureDataArrays[textureIndex];
        const bandCount = textureData.length / pixelCount;
        const textureBandIndex = bandIndex % 4;
        textureData[pixelIndex * bandCount + textureBandIndex] = dataValue;
        ++dataIndex;
      }
      rowOffset += bytesPerRow / bytesPerElement;
    }
    for (let textureIndex = 0; textureIndex < textureCount; ++textureIndex) {
      const texture = this.textures[textureIndex];
      const textureData = textureDataArrays[textureIndex];
      const bandCount = textureData.length / pixelCount;
      uploadDataTexture(
        helper,
        texture,
        textureData,
        pixelSize,
        bandCount,
        tile.interpolate
      );
    }
    this.setReady();
  }
  /**
   * @param {import("../DataTile.js").ImageLike} image The image.
   * @param {number} renderCol The column index (in rendered tile space).
   * @param {number} renderRow The row index (in rendered tile space).
   * @return {Uint8ClampedArray|null} The data.
   * @private
   */
  getImagePixelData_(image, renderCol, renderRow) {
    const gutter = this.gutter;
    const renderWidth = this.renderSize_[0];
    const renderHeight = this.renderSize_[1];
    if (!pixelContext) {
      createPixelContext();
    }
    pixelContext.clearRect(0, 0, 1, 1);
    const sourceWidth = image.width;
    const sourceHeight = image.height;
    const sourceWidthWithoutGutter = sourceWidth - 2 * gutter;
    const sourceHeightWithoutGutter = sourceHeight - 2 * gutter;
    const sourceCol = gutter + Math.floor(sourceWidthWithoutGutter * (renderCol / renderWidth));
    const sourceRow = gutter + Math.floor(sourceHeightWithoutGutter * (renderRow / renderHeight));
    let data;
    try {
      pixelContext.drawImage(image, sourceCol, sourceRow, 1, 1, 0, 0, 1, 1);
      data = pixelContext.getImageData(0, 0, 1, 1).data;
    } catch {
      pixelContext = null;
      return null;
    }
    return data;
  }
  /**
   * @param {import("../DataTile.js").ArrayLike} data The data.
   * @param {import("../size.js").Size} sourceSize The size.
   * @param {number} renderCol The column index (in rendered tile space).
   * @param {number} renderRow The row index (in rendered tile space).
   * @return {import("../DataTile.js").ArrayLike|null} The data.
   * @private
   */
  getArrayPixelData_(data, sourceSize, renderCol, renderRow) {
    const gutter = this.gutter;
    const renderWidth = this.renderSize_[0];
    const renderHeight = this.renderSize_[1];
    const sourceWidthWithoutGutter = sourceSize[0];
    const sourceHeightWithoutGutter = sourceSize[1];
    const sourceWidth = sourceWidthWithoutGutter + 2 * gutter;
    const sourceHeight = sourceHeightWithoutGutter + 2 * gutter;
    const sourceCol = gutter + Math.floor(sourceWidthWithoutGutter * (renderCol / renderWidth));
    const sourceRow = gutter + Math.floor(sourceHeightWithoutGutter * (renderRow / renderHeight));
    if (data instanceof DataView) {
      const bytesPerPixel = data.byteLength / (sourceWidth * sourceHeight);
      const offset2 = bytesPerPixel * (sourceRow * sourceWidth + sourceCol);
      const buffer2 = data.buffer.slice(offset2, offset2 + bytesPerPixel);
      return new DataView(buffer2);
    }
    const offset = this.bandCount * (sourceRow * sourceWidth + sourceCol);
    return data.slice(offset, offset + this.bandCount);
  }
  /**
   * Get data for a pixel.  If the tile is not loaded, null is returned.
   * @param {number} renderCol The column index (in rendered tile space).
   * @param {number} renderRow The row index (in rendered tile space).
   * @return {import("../DataTile.js").ArrayLike|null} The data.
   */
  getPixelData(renderCol, renderRow) {
    if (!this.loaded) {
      return null;
    }
    if (this.tile instanceof DataTile_default) {
      const data = this.tile.getData();
      const arrayData = asArrayLike(data);
      if (arrayData) {
        const sourceSize = this.tile.getSize();
        return this.getArrayPixelData_(
          arrayData,
          sourceSize,
          renderCol,
          renderRow
        );
      }
      return this.getImagePixelData_(asImageLike(data), renderCol, renderRow);
    }
    return this.getImagePixelData_(this.tile.getImage(), renderCol, renderRow);
  }
};
var TileTexture_default = TileTexture;

// node_modules/ol/renderer/webgl/Layer.js
var WebGLLayerRenderer = class _WebGLLayerRenderer extends Layer_default {
  /**
   * @param {LayerType} layer Layer.
   * @param {Options} [options] Options.
   */
  constructor(layer, options) {
    super(layer);
    options = options || {};
    this.inversePixelTransform_ = create();
    this.postProcesses_ = options.postProcesses;
    this.uniforms_ = options.uniforms;
    this.helper;
    this.onMapChanged_ = () => {
      this.clearCache();
      this.removeHelper();
    };
    layer.addChangeListener(Property_default.MAP, this.onMapChanged_);
    this.dispatchPreComposeEvent = this.dispatchPreComposeEvent.bind(this);
    this.dispatchPostComposeEvent = this.dispatchPostComposeEvent.bind(this);
  }
  /**
   * @param {WebGLRenderingContext} context The WebGL rendering context.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @protected
   */
  dispatchPreComposeEvent(context, frameState) {
    const layer = this.getLayer();
    if (layer.hasListener(EventType_default2.PRECOMPOSE)) {
      const event = new Event_default(
        EventType_default2.PRECOMPOSE,
        void 0,
        frameState,
        context
      );
      layer.dispatchEvent(event);
    }
  }
  /**
   * @param {WebGLRenderingContext} context The WebGL rendering context.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @protected
   */
  dispatchPostComposeEvent(context, frameState) {
    const layer = this.getLayer();
    if (layer.hasListener(EventType_default2.POSTCOMPOSE)) {
      const event = new Event_default(
        EventType_default2.POSTCOMPOSE,
        void 0,
        frameState,
        context
      );
      layer.dispatchEvent(event);
    }
  }
  /**
   * Reset options (only handles uniforms).
   * @param {Options} options Options.
   */
  reset(options) {
    this.uniforms_ = options.uniforms;
    if (this.helper) {
      this.helper.setUniforms(this.uniforms_);
    }
  }
  /**
   * @protected
   */
  removeHelper() {
    if (this.helper) {
      this.helper.dispose();
      delete this.helper;
    }
  }
  /**
   * Determine whether renderFrame should be called.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @return {boolean} Layer is ready to be rendered.
   * @override
   */
  prepareFrame(frameState) {
    if (this.getLayer().getRenderSource()) {
      let incrementGroup = true;
      let groupNumber = -1;
      let className;
      for (let i = 0, ii = frameState.layerStatesArray.length; i < ii; i++) {
        const layer = frameState.layerStatesArray[i].layer;
        const renderer = layer.getRenderer();
        if (!(renderer instanceof _WebGLLayerRenderer)) {
          incrementGroup = true;
          continue;
        }
        const layerClassName = layer.getClassName();
        if (incrementGroup || layerClassName !== className) {
          groupNumber += 1;
          incrementGroup = false;
        }
        className = layerClassName;
        if (renderer === this) {
          break;
        }
      }
      const canvasCacheKey = "map/" + frameState.mapId + "/group/" + groupNumber;
      if (!this.helper || !this.helper.canvasCacheKeyMatches(canvasCacheKey) || this.helper.needsToBeRecreated()) {
        this.removeHelper();
        this.helper = new Helper_default({
          postProcesses: this.postProcesses_,
          uniforms: this.uniforms_,
          canvasCacheKey
        });
        if (className) {
          this.helper.getCanvas().className = className;
        }
        this.afterHelperCreated();
      }
    }
    return this.prepareFrameInternal(frameState);
  }
  /**
   * @protected
   */
  afterHelperCreated() {
  }
  /**
   * Determine whether renderFrame should be called.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @return {boolean} Layer is ready to be rendered.
   * @protected
   */
  prepareFrameInternal(frameState) {
    return true;
  }
  /**
   * @protected
   */
  clearCache() {
  }
  /**
   * Clean up.
   * @override
   */
  disposeInternal() {
    var _a;
    this.clearCache();
    this.removeHelper();
    (_a = this.getLayer()) == null ? void 0 : _a.removeChangeListener(
      Property_default.MAP,
      this.onMapChanged_
    );
    super.disposeInternal();
  }
  /**
   * @param {import("../../render/EventType.js").default} type Event type.
   * @param {WebGLRenderingContext} context The rendering context.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @private
   */
  dispatchRenderEvent_(type, context, frameState) {
    const layer = this.getLayer();
    if (layer.hasListener(type)) {
      compose(
        this.inversePixelTransform_,
        0,
        0,
        frameState.pixelRatio,
        -frameState.pixelRatio,
        0,
        0,
        -frameState.size[1]
      );
      const event = new Event_default(
        type,
        this.inversePixelTransform_,
        frameState,
        context
      );
      layer.dispatchEvent(event);
    }
  }
  /**
   * @param {WebGLRenderingContext} context The rendering context.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @protected
   */
  preRender(context, frameState) {
    this.dispatchRenderEvent_(EventType_default2.PRERENDER, context, frameState);
  }
  /**
   * @param {WebGLRenderingContext} context The rendering context.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @protected
   */
  postRender(context, frameState) {
    this.dispatchRenderEvent_(EventType_default2.POSTRENDER, context, frameState);
  }
};
var Layer_default2 = WebGLLayerRenderer;

// node_modules/ol/renderer/webgl/TileLayerBase.js
var Uniforms = {
  TILE_TRANSFORM: "u_tileTransform",
  TRANSITION_ALPHA: "u_transitionAlpha",
  DEPTH: "u_depth",
  RENDER_EXTENT: "u_renderExtent",
  // intersection of layer, source, and view extent
  PATTERN_ORIGIN: "u_patternOrigin",
  RESOLUTION: "u_resolution",
  ZOOM: "u_zoom",
  GLOBAL_ALPHA: "u_globalAlpha",
  PROJECTION_MATRIX: "u_projectionMatrix",
  SCREEN_TO_WORLD_MATRIX: "u_screenToWorldMatrix"
};
function depthForZ(z) {
  return 1 / (z + 2);
}
function newTileRepresentationLookup() {
  return { tileIds: /* @__PURE__ */ new Set(), representationsByZ: {} };
}
function lookupHasTile(tileRepresentationLookup, tile) {
  return tileRepresentationLookup.tileIds.has(getUid(tile));
}
function addTileRepresentationToLookup(tileRepresentationLookup, tileRepresentation, z) {
  const representationsByZ = tileRepresentationLookup.representationsByZ;
  if (!(z in representationsByZ)) {
    representationsByZ[z] = /* @__PURE__ */ new Set();
  }
  representationsByZ[z].add(tileRepresentation);
  tileRepresentationLookup.tileIds.add(getUid(tileRepresentation.tile));
}
function getRenderExtent(frameState, extent) {
  const layerState = frameState.layerStatesArray[frameState.layerIndex];
  if (layerState.extent) {
    extent = getIntersection(
      extent,
      fromUserExtent(layerState.extent, frameState.viewState.projection)
    );
  }
  const source = (
    /** @type {import("../../source/Tile.js").default} */
    layerState.layer.getRenderSource()
  );
  if (!source.getWrapX()) {
    const gridExtent = source.getTileGridForProjection(frameState.viewState.projection).getExtent();
    if (gridExtent) {
      extent = getIntersection(extent, gridExtent);
    }
  }
  return extent;
}
function getCacheKey(source, tileCoord) {
  return `${getUid(source)},${source.getKey()},${source.getRevision()},${getKey(tileCoord)}`;
}
var WebGLBaseTileLayerRenderer = class extends Layer_default2 {
  /**
   * @param {LayerType} tileLayer Tile layer.
   * @param {Options} options Options.
   */
  constructor(tileLayer, options) {
    super(tileLayer, {
      uniforms: options.uniforms,
      postProcesses: options.postProcesses
    });
    this.renderComplete = false;
    this.tileTransform_ = create();
    this.tempMat4 = create2();
    this.tempTileRange_ = new TileRange_default(0, 0, 0, 0);
    this.tempTileCoord_ = createOrUpdate(0, 0, 0);
    this.tempSize_ = [0, 0];
    const cacheSize = options.cacheSize !== void 0 ? options.cacheSize : 512;
    this.tileRepresentationCache = new LRUCache_default(cacheSize);
    this.frameState = null;
    this.renderedProjection_ = void 0;
  }
  /**
   * @param {Options} options Options.
   * @override
   */
  reset(options) {
    super.reset({
      uniforms: options.uniforms
    });
  }
  /**
   * Determine whether renderFrame should be called.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @return {boolean} Layer is ready to be rendered.
   * @override
   */
  prepareFrameInternal(frameState) {
    if (!this.renderedProjection_) {
      this.renderedProjection_ = frameState.viewState.projection;
    } else if (frameState.viewState.projection !== this.renderedProjection_) {
      this.clearCache();
      this.renderedProjection_ = frameState.viewState.projection;
    }
    const layer = this.getLayer();
    const source = layer.getRenderSource();
    if (!source) {
      return false;
    }
    if (isEmpty(getRenderExtent(frameState, frameState.extent))) {
      return false;
    }
    return source.getState() === "ready";
  }
  /**
   * @abstract
   * @param {import("../../webgl/BaseTileRepresentation.js").TileRepresentationOptions<TileType>} options tile representation options
   * @return {TileRepresentation} A new tile representation
   * @protected
   */
  createTileRepresentation(options) {
    return abstract();
  }
  /**
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @param {import("../../extent.js").Extent} extent The extent to be rendered.
   * @param {number} initialZ The zoom level.
   * @param {TileRepresentationLookup} tileRepresentationLookup The zoom level.
   * @param {number} preload Number of additional levels to load.
   */
  enqueueTiles(frameState, extent, initialZ, tileRepresentationLookup, preload) {
    const viewState = frameState.viewState;
    const tileLayer = this.getLayer();
    const tileSource = tileLayer.getRenderSource();
    const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
    const gutter = tileSource.getGutterForProjection(viewState.projection);
    const tileSourceKey = getUid(tileSource);
    if (!(tileSourceKey in frameState.wantedTiles)) {
      frameState.wantedTiles[tileSourceKey] = {};
    }
    const wantedTiles = frameState.wantedTiles[tileSourceKey];
    const tileRepresentationCache = this.tileRepresentationCache;
    const map = tileLayer.getMapInternal();
    const minZ = Math.max(
      initialZ - preload,
      tileGrid.getMinZoom(),
      tileGrid.getZForResolution(
        Math.min(
          tileLayer.getMaxResolution(),
          map ? map.getView().getResolutionForZoom(Math.max(tileLayer.getMinZoom(), 0)) : tileGrid.getResolution(0)
        ),
        tileSource.zDirection
      )
    );
    const rotation = viewState.rotation;
    const viewport = rotation ? getRotatedViewport(
      viewState.center,
      viewState.resolution,
      rotation,
      frameState.size
    ) : void 0;
    for (let z = initialZ; z >= minZ; --z) {
      const tileRange = tileGrid.getTileRangeForExtentAndZ(
        extent,
        z,
        this.tempTileRange_
      );
      const tileResolution = tileGrid.getResolution(z);
      for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
        for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
          if (rotation && !tileGrid.tileCoordIntersectsViewport([z, x, y], viewport)) {
            continue;
          }
          const tileCoord = createOrUpdate(z, x, y, this.tempTileCoord_);
          const cacheKey = getCacheKey(tileSource, tileCoord);
          let tileRepresentation;
          let tile;
          if (tileRepresentationCache.containsKey(cacheKey)) {
            tileRepresentation = tileRepresentationCache.get(cacheKey);
            tile = tileRepresentation.tile;
          }
          if (!tileRepresentation || tileRepresentation.tile.key !== tileSource.getKey()) {
            tile = tileSource.getTile(
              z,
              x,
              y,
              frameState.pixelRatio,
              viewState.projection
            );
            if (!tile) {
              continue;
            }
          }
          if (lookupHasTile(tileRepresentationLookup, tile)) {
            continue;
          }
          if (!tileRepresentation) {
            tileRepresentation = this.createTileRepresentation({
              tile,
              grid: tileGrid,
              helper: this.helper,
              gutter
            });
            tileRepresentationCache.set(cacheKey, tileRepresentation);
          } else {
            tileRepresentation.setTile(tile);
          }
          addTileRepresentationToLookup(
            tileRepresentationLookup,
            tileRepresentation,
            z
          );
          const tileQueueKey = tile.getKey();
          wantedTiles[tileQueueKey] = true;
          if (tile.getState() === TileState_default.IDLE) {
            if (!frameState.tileQueue.isKeyQueued(tileQueueKey)) {
              frameState.tileQueue.enqueue([
                tile,
                tileSourceKey,
                tileGrid.getTileCoordCenter(tileCoord),
                tileResolution
              ]);
            }
          }
        }
      }
    }
  }
  /**
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @param {boolean} tilesWithAlpha True if at least one of the rendered tiles has alpha
   * @protected
   */
  beforeTilesRender(frameState, tilesWithAlpha) {
    this.helper.prepareDraw(this.frameState, !tilesWithAlpha, true);
  }
  /**
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @return {boolean} If returns false, tile mask rendering will be skipped
   * @protected
   */
  beforeTilesMaskRender(frameState) {
    return false;
  }
  /**
   * @param {TileRepresentation} tileRepresentation Tile representation
   * @param {import("../../transform.js").Transform} tileTransform Tile transform
   * @param {import("../../Map.js").FrameState} frameState Frame state
   * @param {import("../../extent.js").Extent} renderExtent Render extent
   * @param {number} tileResolution Tile resolution
   * @param {import("../../size.js").Size} tileSize Tile size
   * @param {import("../../coordinate.js").Coordinate} tileOrigin Tile origin
   * @param {import("../../extent.js").Extent} tileExtent tile Extent
   * @param {number} depth Depth
   * @param {number} gutter Gutter
   * @param {number} alpha Alpha
   * @protected
   */
  renderTile(tileRepresentation, tileTransform, frameState, renderExtent, tileResolution, tileSize, tileOrigin, tileExtent, depth, gutter, alpha) {
  }
  /**
   * @param {TileRepresentation} tileRepresentation Tile representation
   * @param {number} tileZ Tile Z
   * @param {import("../../extent.js").Extent} extent Render extent
   * @param {number} depth Depth
   * @protected
   */
  renderTileMask(tileRepresentation, tileZ, extent, depth) {
  }
  drawTile_(frameState, tileRepresentation, tileZ, gutter, extent, alphaLookup, tileGrid) {
    if (!tileRepresentation.ready) {
      return;
    }
    const tile = tileRepresentation.tile;
    const tileCoord = tile.tileCoord;
    const tileCoordKey = getKey(tileCoord);
    const alpha = tileCoordKey in alphaLookup ? alphaLookup[tileCoordKey] : 1;
    const tileResolution = tileGrid.getResolution(tileZ);
    const tileSize = toSize(tileGrid.getTileSize(tileZ), this.tempSize_);
    const tileOrigin = tileGrid.getOrigin(tileZ);
    const tileExtent = tileGrid.getTileCoordExtent(tileCoord);
    const depth = alpha < 1 ? -1 : depthForZ(tileZ);
    if (alpha < 1) {
      frameState.animate = true;
    }
    const viewState = frameState.viewState;
    const centerX = viewState.center[0];
    const centerY = viewState.center[1];
    const tileWidthWithGutter = tileSize[0] + 2 * gutter;
    const tileHeightWithGutter = tileSize[1] + 2 * gutter;
    const aspectRatio = tileWidthWithGutter / tileHeightWithGutter;
    const centerI = (centerX - tileOrigin[0]) / (tileSize[0] * tileResolution);
    const centerJ = (tileOrigin[1] - centerY) / (tileSize[1] * tileResolution);
    const tileScale = viewState.resolution / tileResolution;
    const tileCenterI = tileCoord[1];
    const tileCenterJ = tileCoord[2];
    reset(this.tileTransform_);
    scale(
      this.tileTransform_,
      2 / (frameState.size[0] * tileScale / tileWidthWithGutter),
      -2 / (frameState.size[1] * tileScale / tileWidthWithGutter)
    );
    rotate(this.tileTransform_, viewState.rotation);
    scale(this.tileTransform_, 1, 1 / aspectRatio);
    translate(
      this.tileTransform_,
      (tileSize[0] * (tileCenterI - centerI) - gutter) / tileWidthWithGutter,
      (tileSize[1] * (tileCenterJ - centerJ) - gutter) / tileHeightWithGutter
    );
    this.renderTile(
      /** @type {TileRepresentation} */
      tileRepresentation,
      this.tileTransform_,
      frameState,
      extent,
      tileResolution,
      tileSize,
      tileOrigin,
      tileExtent,
      depth,
      gutter,
      alpha
    );
  }
  /**
   * Render the layer.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @return {HTMLElement} The rendered element.
   * @override
   */
  renderFrame(frameState) {
    this.frameState = frameState;
    this.renderComplete = true;
    const gl = this.helper.getGL();
    this.preRender(gl, frameState);
    const viewState = frameState.viewState;
    const tileLayer = this.getLayer();
    const tileSource = tileLayer.getRenderSource();
    const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
    const gutter = tileSource.getGutterForProjection(viewState.projection);
    const extent = getRenderExtent(frameState, frameState.extent);
    const z = tileGrid.getZForResolution(
      viewState.resolution,
      tileSource.zDirection
    );
    const tileRepresentationLookup = newTileRepresentationLookup();
    const preload = tileLayer.getPreload();
    if (frameState.nextExtent) {
      const targetZ = tileGrid.getZForResolution(
        viewState.nextResolution,
        tileSource.zDirection
      );
      const nextExtent = getRenderExtent(frameState, frameState.nextExtent);
      this.enqueueTiles(
        frameState,
        nextExtent,
        targetZ,
        tileRepresentationLookup,
        preload
      );
    }
    this.enqueueTiles(frameState, extent, z, tileRepresentationLookup, 0);
    if (preload > 0) {
      setTimeout(() => {
        this.enqueueTiles(
          frameState,
          extent,
          z - 1,
          tileRepresentationLookup,
          preload - 1
        );
      }, 0);
    }
    const alphaLookup = {};
    let blend = false;
    const representationsByZ = tileRepresentationLookup.representationsByZ;
    if (z in representationsByZ) {
      const uid = getUid(this);
      const time = frameState.time;
      for (const tileRepresentation of representationsByZ[z]) {
        const tile = tileRepresentation.tile;
        if (tile.getState() === TileState_default.EMPTY) {
          continue;
        }
        const tileCoord = tile.tileCoord;
        if (tileRepresentation.ready) {
          const alpha = tile.getAlpha(uid, time);
          if (alpha === 1) {
            tile.endTransition(uid);
            continue;
          }
          blend = true;
          const tileCoordKey = getKey(tileCoord);
          alphaLookup[tileCoordKey] = alpha;
        }
        this.renderComplete = false;
        const coveredByChildren = this.findAltTiles_(
          tileGrid,
          tileCoord,
          z + 1,
          tileRepresentationLookup
        );
        if (coveredByChildren) {
          continue;
        }
        const minZoom = tileGrid.getMinZoom();
        for (let parentZ = z - 1; parentZ >= minZoom; --parentZ) {
          const coveredByParent = this.findAltTiles_(
            tileGrid,
            tileCoord,
            parentZ,
            tileRepresentationLookup
          );
          if (coveredByParent) {
            break;
          }
        }
      }
    }
    const zs = Object.keys(representationsByZ).map(Number).sort(descending);
    const renderTileMask = this.beforeTilesMaskRender(frameState);
    if (renderTileMask) {
      for (let j = 0, jj = zs.length; j < jj; ++j) {
        const tileZ = zs[j];
        for (const tileRepresentation of representationsByZ[tileZ]) {
          const tileCoord = tileRepresentation.tile.tileCoord;
          const tileCoordKey = getKey(tileCoord);
          if (tileCoordKey in alphaLookup) {
            continue;
          }
          const tileExtent = tileGrid.getTileCoordExtent(tileCoord);
          this.renderTileMask(
            /** @type {TileRepresentation} */
            tileRepresentation,
            tileZ,
            tileExtent,
            depthForZ(tileZ)
          );
        }
      }
    }
    this.beforeTilesRender(frameState, blend);
    for (let j = 0, jj = zs.length; j < jj; ++j) {
      const tileZ = zs[j];
      for (const tileRepresentation of representationsByZ[tileZ]) {
        const tileCoord = tileRepresentation.tile.tileCoord;
        const tileCoordKey = getKey(tileCoord);
        if (tileCoordKey in alphaLookup) {
          continue;
        }
        this.drawTile_(
          frameState,
          tileRepresentation,
          tileZ,
          gutter,
          extent,
          alphaLookup,
          tileGrid
        );
      }
    }
    if (z in representationsByZ) {
      for (const tileRepresentation of representationsByZ[z]) {
        const tileCoord = tileRepresentation.tile.tileCoord;
        const tileCoordKey = getKey(tileCoord);
        if (tileCoordKey in alphaLookup) {
          this.drawTile_(
            frameState,
            tileRepresentation,
            z,
            gutter,
            extent,
            alphaLookup,
            tileGrid
          );
        }
      }
    }
    this.beforeFinalize(frameState);
    this.helper.finalizeDraw(
      frameState,
      this.dispatchPreComposeEvent,
      this.dispatchPostComposeEvent
    );
    const canvas = this.helper.getCanvas();
    const tileRepresentationCache = this.tileRepresentationCache;
    tileRepresentationCache.expireCache();
    this.postRender(gl, frameState);
    return canvas;
  }
  /**
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @protected
   */
  beforeFinalize(frameState) {
    return;
  }
  /**
   * Look for tiles covering the provided tile coordinate at an alternate
   * zoom level.  Loaded tiles will be added to the provided tile representation lookup.
   * @param {import("../../tilegrid/TileGrid.js").default} tileGrid The tile grid.
   * @param {import("../../tilecoord.js").TileCoord} tileCoord The target tile coordinate.
   * @param {number} altZ The alternate zoom level.
   * @param {TileRepresentationLookup} tileRepresentationLookup Lookup of
   * tile representations by zoom level.
   * @return {boolean} The tile coordinate is covered by loaded tiles at the alternate zoom level.
   * @private
   */
  findAltTiles_(tileGrid, tileCoord, altZ, tileRepresentationLookup) {
    const tileRange = tileGrid.getTileRangeForTileCoordAndZ(
      tileCoord,
      altZ,
      this.tempTileRange_
    );
    if (!tileRange) {
      return false;
    }
    let covered = true;
    const tileRepresentationCache = this.tileRepresentationCache;
    const source = this.getLayer().getRenderSource();
    for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
      for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
        const cacheKey = getCacheKey(source, [altZ, x, y]);
        let loaded = false;
        if (tileRepresentationCache.containsKey(cacheKey)) {
          const tileRepresentation = tileRepresentationCache.get(cacheKey);
          if (tileRepresentation.ready && !lookupHasTile(tileRepresentationLookup, tileRepresentation.tile)) {
            addTileRepresentationToLookup(
              tileRepresentationLookup,
              tileRepresentation,
              altZ
            );
            loaded = true;
          }
        }
        if (!loaded) {
          covered = false;
        }
      }
    }
    return covered;
  }
  /**
   * @override
   */
  clearCache() {
    super.clearCache();
    const tileRepresentationCache = this.tileRepresentationCache;
    tileRepresentationCache.forEach(
      (tileRepresentation) => tileRepresentation.dispose()
    );
    tileRepresentationCache.clear();
  }
  /**
   * @override
   */
  afterHelperCreated() {
    super.afterHelperCreated();
    this.tileRepresentationCache.forEach(
      (tileRepresentation) => tileRepresentation.setHelper(this.helper)
    );
  }
  /**
   * Clean up.
   * @override
   */
  disposeInternal() {
    super.disposeInternal();
    delete this.frameState;
  }
};
var TileLayerBase_default = WebGLBaseTileLayerRenderer;

// node_modules/ol/renderer/webgl/TileLayer.js
var Uniforms2 = {
  ...Uniforms,
  TILE_TEXTURE_ARRAY: "u_tileTextures",
  TEXTURE_PIXEL_WIDTH: "u_texturePixelWidth",
  TEXTURE_PIXEL_HEIGHT: "u_texturePixelHeight",
  TEXTURE_RESOLUTION: "u_textureResolution",
  // map units per texture pixel
  TEXTURE_ORIGIN_X: "u_textureOriginX",
  // map x coordinate of left edge of texture
  TEXTURE_ORIGIN_Y: "u_textureOriginY"
  // map y coordinate of top edge of texture
};
var Attributes = {
  TEXTURE_COORD: "a_textureCoord"
};
var attributeDescriptions = [
  {
    name: Attributes.TEXTURE_COORD,
    size: 2,
    type: AttributeType.FLOAT
  }
];
var WebGLTileLayerRenderer = class extends TileLayerBase_default {
  /**
   * @param {LayerType} tileLayer Tile layer.
   * @param {Options} options Options.
   */
  constructor(tileLayer, options) {
    super(tileLayer, options);
    this.program_;
    this.vertexShader_ = options.vertexShader;
    this.fragmentShader_ = options.fragmentShader;
    this.indices_ = new Buffer_default(ELEMENT_ARRAY_BUFFER, STATIC_DRAW);
    this.indices_.fromArray([0, 1, 3, 1, 2, 3]);
    this.paletteTextures_ = options.paletteTextures || [];
  }
  /**
   * @param {Options} options Options.
   * @override
   */
  reset(options) {
    super.reset(options);
    if (this.helper) {
      const gl = this.helper.getGL();
      for (const paletteTexture of this.paletteTextures_) {
        paletteTexture.delete(gl);
      }
    }
    this.vertexShader_ = options.vertexShader;
    this.fragmentShader_ = options.fragmentShader;
    this.paletteTextures_ = options.paletteTextures || [];
    if (this.helper) {
      this.program_ = this.helper.getProgram(
        this.fragmentShader_,
        this.vertexShader_
      );
      const gl = this.helper.getGL();
      for (const paletteTexture of this.paletteTextures_) {
        paletteTexture.getTexture(gl);
      }
    }
  }
  /**
   * @override
   */
  afterHelperCreated() {
    super.afterHelperCreated();
    const gl = this.helper.getGL();
    for (const paletteTexture of this.paletteTextures_) {
      paletteTexture.getTexture(gl);
    }
    this.program_ = this.helper.getProgram(
      this.fragmentShader_,
      this.vertexShader_
    );
    this.helper.flushBufferData(this.indices_);
  }
  /**
   * @override
   */
  removeHelper() {
    if (this.helper) {
      const gl = this.helper.getGL();
      for (const paletteTexture of this.paletteTextures_) {
        paletteTexture.delete(gl);
      }
    }
    super.removeHelper();
  }
  /**
   * @override
   */
  createTileRepresentation(options) {
    return new TileTexture_default(options);
  }
  /**
   * @override
   */
  beforeTilesRender(frameState, tilesWithAlpha) {
    super.beforeTilesRender(frameState, tilesWithAlpha);
    this.helper.useProgram(this.program_, frameState);
  }
  /**
   * @override
   */
  renderTile(tileTexture, tileTransform, frameState, renderExtent, tileResolution, tileSize, tileOrigin, tileExtent, depth, gutter, alpha) {
    const gl = this.helper.getGL();
    this.helper.bindBuffer(tileTexture.coords);
    this.helper.bindBuffer(this.indices_);
    this.helper.enableAttributes(attributeDescriptions);
    let textureSlot = 0;
    while (textureSlot < tileTexture.textures.length) {
      const uniformName = `${Uniforms2.TILE_TEXTURE_ARRAY}[${textureSlot}]`;
      this.helper.bindTexture(
        tileTexture.textures[textureSlot],
        textureSlot,
        uniformName
      );
      ++textureSlot;
    }
    for (let paletteIndex = 0; paletteIndex < this.paletteTextures_.length; ++paletteIndex) {
      const paletteTexture = this.paletteTextures_[paletteIndex];
      const texture = paletteTexture.getTexture(gl);
      this.helper.bindTexture(texture, textureSlot, paletteTexture.name);
      ++textureSlot;
    }
    const viewState = frameState.viewState;
    const tileWidthWithGutter = tileSize[0] + 2 * gutter;
    const tileHeightWithGutter = tileSize[1] + 2 * gutter;
    const tile = tileTexture.tile;
    const tileCoord = tile.tileCoord;
    const tileCenterI = tileCoord[1];
    const tileCenterJ = tileCoord[2];
    this.helper.setUniformMatrixValue(
      Uniforms2.TILE_TRANSFORM,
      fromTransform(this.tempMat4, tileTransform)
    );
    this.helper.setUniformFloatValue(Uniforms2.TRANSITION_ALPHA, alpha);
    this.helper.setUniformFloatValue(Uniforms2.DEPTH, depth);
    let gutterExtent = renderExtent;
    if (gutter > 0) {
      gutterExtent = tileExtent;
      getIntersection(gutterExtent, renderExtent, gutterExtent);
    }
    this.helper.setUniformFloatVec4(Uniforms2.RENDER_EXTENT, gutterExtent);
    this.helper.setUniformFloatValue(Uniforms2.RESOLUTION, viewState.resolution);
    this.helper.setUniformFloatValue(Uniforms2.ZOOM, viewState.zoom);
    this.helper.setUniformFloatValue(
      Uniforms2.TEXTURE_PIXEL_WIDTH,
      tileWidthWithGutter
    );
    this.helper.setUniformFloatValue(
      Uniforms2.TEXTURE_PIXEL_HEIGHT,
      tileHeightWithGutter
    );
    this.helper.setUniformFloatValue(
      Uniforms2.TEXTURE_RESOLUTION,
      tileResolution
    );
    this.helper.setUniformFloatValue(
      Uniforms2.TEXTURE_ORIGIN_X,
      tileOrigin[0] + tileCenterI * tileSize[0] * tileResolution - gutter * tileResolution
    );
    this.helper.setUniformFloatValue(
      Uniforms2.TEXTURE_ORIGIN_Y,
      tileOrigin[1] - tileCenterJ * tileSize[1] * tileResolution + gutter * tileResolution
    );
    this.helper.drawElements(0, this.indices_.getSize());
  }
  /**
   * @param {import("../../pixel.js").Pixel} pixel Pixel.
   * @return {Uint8ClampedArray|Uint8Array|Float32Array|DataView} Data at the pixel location.
   * @override
   */
  getData(pixel) {
    const gl = this.helper.getGL();
    if (!gl) {
      return null;
    }
    const frameState = this.frameState;
    if (!frameState) {
      return null;
    }
    const layer = this.getLayer();
    const coordinate = apply(
      frameState.pixelToCoordinateTransform,
      pixel.slice()
    );
    const viewState = frameState.viewState;
    const layerExtent = layer.getExtent();
    if (layerExtent) {
      if (!containsCoordinate(
        fromUserExtent(layerExtent, viewState.projection),
        coordinate
      )) {
        return null;
      }
    }
    const sources = layer.getSources(
      boundingExtent([coordinate]),
      viewState.resolution
    );
    let i, source, tileGrid;
    for (i = sources.length - 1; i >= 0; --i) {
      source = sources[i];
      if (source.getState() === "ready") {
        tileGrid = source.getTileGridForProjection(viewState.projection);
        if (source.getWrapX()) {
          break;
        }
        const gridExtent = tileGrid.getExtent();
        if (!gridExtent || containsCoordinate(gridExtent, coordinate)) {
          break;
        }
      }
    }
    if (i < 0) {
      return null;
    }
    const tileTextureCache = this.tileRepresentationCache;
    for (let z = tileGrid.getZForResolution(viewState.resolution); z >= tileGrid.getMinZoom(); --z) {
      const tileCoord = tileGrid.getTileCoordForCoordAndZ(coordinate, z);
      const cacheKey = getCacheKey(source, tileCoord);
      if (!tileTextureCache.containsKey(cacheKey)) {
        continue;
      }
      const tileTexture = tileTextureCache.get(cacheKey);
      const tile = tileTexture.tile;
      if (tile.getState() === TileState_default.EMPTY) {
        return null;
      }
      if (!tileTexture.loaded) {
        continue;
      }
      const tileOrigin = tileGrid.getOrigin(z);
      const tileSize = toSize(tileGrid.getTileSize(z));
      const tileResolution = tileGrid.getResolution(z);
      const col = (coordinate[0] - tileOrigin[0]) / tileResolution - tileCoord[1] * tileSize[0];
      const row = (tileOrigin[1] - coordinate[1]) / tileResolution - tileCoord[2] * tileSize[1];
      return tileTexture.getPixelData(col, row);
    }
    return null;
  }
  /**
   * Clean up.
   * @override
   */
  disposeInternal() {
    const helper = this.helper;
    if (helper) {
      const gl = helper.getGL();
      for (const paletteTexture of this.paletteTextures_) {
        paletteTexture.delete(gl);
      }
      this.paletteTextures_.length = 0;
      gl.deleteProgram(this.program_);
      delete this.program_;
      helper.deleteBuffer(this.indices_);
    }
    super.disposeInternal();
    delete this.indices_;
  }
};
var TileLayer_default2 = WebGLTileLayerRenderer;

// node_modules/ol/webgl/PaletteTexture.js
var PaletteTexture = class {
  /**
   * @param {string} name The name of the texture.
   * @param {Uint8Array} data The texture data.
   */
  constructor(name, data) {
    this.name = name;
    this.data = data;
    this.texture_ = null;
  }
  /**
   * @param {WebGLRenderingContext} gl Rendering context.
   * @return {WebGLTexture} The texture.
   */
  getTexture(gl) {
    if (!this.texture_) {
      const texture = gl.createTexture();
      gl.bindTexture(gl.TEXTURE_2D, texture);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      gl.texImage2D(
        gl.TEXTURE_2D,
        0,
        gl.RGBA,
        this.data.length / 4,
        1,
        0,
        gl.RGBA,
        gl.UNSIGNED_BYTE,
        this.data
      );
      this.texture_ = texture;
    }
    return this.texture_;
  }
  /**
   * @param {WebGLRenderingContext} gl Rendering context.
   */
  delete(gl) {
    if (this.texture_) {
      gl.deleteTexture(this.texture_);
    }
    this.texture_ = null;
  }
};
var PaletteTexture_default = PaletteTexture;

// node_modules/ol/expr/gpu.js
function computeOperatorFunctionName(operator, context) {
  return `operator_${operator}_${Object.keys(context.functions).length}`;
}
function numberToGlsl(v) {
  const s = v.toString();
  return s.includes(".") ? s : s + ".0";
}
function arrayToGlsl(array) {
  if (array.length < 2 || array.length > 4) {
    throw new Error(
      "`formatArray` can only output `vec2`, `vec3` or `vec4` arrays."
    );
  }
  return `vec${array.length}(${array.map(numberToGlsl).join(", ")})`;
}
function colorToGlsl(color) {
  const array = asArray(color);
  const alpha = array.length > 3 ? array[3] : 1;
  return arrayToGlsl([array[0] / 255, array[1] / 255, array[2] / 255, alpha]);
}
function sizeToGlsl(size) {
  const array = toSize(size);
  return arrayToGlsl(array);
}
var stringToFloatMap = {};
var stringToFloatCounter = 0;
function getStringNumberEquivalent(string) {
  if (!(string in stringToFloatMap)) {
    stringToFloatMap[string] = stringToFloatCounter++;
  }
  return stringToFloatMap[string];
}
function stringToGlsl(string) {
  return numberToGlsl(getStringNumberEquivalent(string));
}
function uniformNameForVariable(variableName) {
  return "u_var_" + variableName;
}
function newCompilationContext() {
  return {
    variables: {},
    properties: {},
    functions: {},
    bandCount: 0,
    featureId: false,
    geometryType: false
  };
}
var GET_BAND_VALUE_FUNC = "getBandValue";
var PALETTE_TEXTURE_ARRAY = "u_paletteTextures";
var FEATURE_ID_PROPERTY_NAME = "featureId";
var GEOMETRY_TYPE_PROPERTY_NAME = "geometryType";
var UNDEFINED_PROP_VALUE = -9999999;
function buildExpression(encoded, type, parsingContext, compilationContext) {
  const expression = parse(encoded, type, parsingContext);
  return compile(expression, type, compilationContext);
}
function createCompiler(output) {
  return (context, expression, type) => {
    const length = expression.args.length;
    const args = new Array(length);
    for (let i = 0; i < length; ++i) {
      args[i] = compile(expression.args[i], type, context);
    }
    return output(args, context);
  };
}
var compilers = {
  [Ops.Get]: (context, expression) => {
    const firstArg = (
      /** @type {LiteralExpression} */
      expression.args[0]
    );
    const propName = (
      /** @type {string} */
      firstArg.value
    );
    const isExisting = propName in context.properties;
    if (!isExisting) {
      context.properties[propName] = {
        name: propName,
        type: expression.type
      };
    }
    let result = "a_prop_" + propName;
    if (isType(expression.type, BooleanType)) {
      result = `(${result} > 0.0)`;
    }
    return result;
  },
  [Ops.Id]: (context) => {
    context.featureId = true;
    return "a_" + FEATURE_ID_PROPERTY_NAME;
  },
  [Ops.GeometryType]: (context) => {
    context.geometryType = true;
    return "a_" + GEOMETRY_TYPE_PROPERTY_NAME;
  },
  [Ops.LineMetric]: () => "currentLineMetric",
  // this variable is assumed to always be present in shaders, default is 0.
  [Ops.Var]: (context, expression) => {
    const firstArg = (
      /** @type {LiteralExpression} */
      expression.args[0]
    );
    const varName = (
      /** @type {string} */
      firstArg.value
    );
    const isExisting = varName in context.variables;
    if (!isExisting) {
      context.variables[varName] = {
        name: varName,
        type: expression.type
      };
    }
    let result = uniformNameForVariable(varName);
    if (isType(expression.type, BooleanType)) {
      result = `(${result} > 0.0)`;
    }
    return result;
  },
  [Ops.Has]: (context, expression) => {
    const firstArg = (
      /** @type {LiteralExpression} */
      expression.args[0]
    );
    const propName = (
      /** @type {string} */
      firstArg.value
    );
    const isExisting = propName in context.properties;
    if (!isExisting) {
      context.properties[propName] = {
        name: propName,
        type: expression.type
      };
    }
    return `(a_prop_${propName} != ${numberToGlsl(UNDEFINED_PROP_VALUE)})`;
  },
  [Ops.Resolution]: () => "u_resolution",
  [Ops.Zoom]: () => "u_zoom",
  [Ops.Time]: () => "u_time",
  [Ops.Any]: createCompiler((compiledArgs) => `(${compiledArgs.join(` || `)})`),
  [Ops.All]: createCompiler((compiledArgs) => `(${compiledArgs.join(` && `)})`),
  [Ops.Not]: createCompiler(([value]) => `(!${value})`),
  [Ops.Equal]: createCompiler(
    ([firstValue, secondValue]) => `(${firstValue} == ${secondValue})`
  ),
  [Ops.NotEqual]: createCompiler(
    ([firstValue, secondValue]) => `(${firstValue} != ${secondValue})`
  ),
  [Ops.GreaterThan]: createCompiler(
    ([firstValue, secondValue]) => `(${firstValue} > ${secondValue})`
  ),
  [Ops.GreaterThanOrEqualTo]: createCompiler(
    ([firstValue, secondValue]) => `(${firstValue} >= ${secondValue})`
  ),
  [Ops.LessThan]: createCompiler(
    ([firstValue, secondValue]) => `(${firstValue} < ${secondValue})`
  ),
  [Ops.LessThanOrEqualTo]: createCompiler(
    ([firstValue, secondValue]) => `(${firstValue} <= ${secondValue})`
  ),
  [Ops.Multiply]: createCompiler(
    (compiledArgs) => `(${compiledArgs.join(" * ")})`
  ),
  [Ops.Divide]: createCompiler(
    ([firstValue, secondValue]) => `(${firstValue} / ${secondValue})`
  ),
  [Ops.Add]: createCompiler((compiledArgs) => `(${compiledArgs.join(" + ")})`),
  [Ops.Subtract]: createCompiler(
    ([firstValue, secondValue]) => `(${firstValue} - ${secondValue})`
  ),
  [Ops.Clamp]: createCompiler(
    ([value, min, max]) => `clamp(${value}, ${min}, ${max})`
  ),
  [Ops.Mod]: createCompiler(([value, modulo]) => `mod(${value}, ${modulo})`),
  [Ops.Pow]: createCompiler(([value, power]) => `pow(${value}, ${power})`),
  [Ops.Abs]: createCompiler(([value]) => `abs(${value})`),
  [Ops.Floor]: createCompiler(([value]) => `floor(${value})`),
  [Ops.Ceil]: createCompiler(([value]) => `ceil(${value})`),
  [Ops.Round]: createCompiler(([value]) => `floor(${value} + 0.5)`),
  [Ops.Sin]: createCompiler(([value]) => `sin(${value})`),
  [Ops.Cos]: createCompiler(([value]) => `cos(${value})`),
  [Ops.Atan]: createCompiler(([firstValue, secondValue]) => {
    return secondValue !== void 0 ? `atan(${firstValue}, ${secondValue})` : `atan(${firstValue})`;
  }),
  [Ops.Sqrt]: createCompiler(([value]) => `sqrt(${value})`),
  [Ops.Match]: createCompiler((compiledArgs) => {
    const input = compiledArgs[0];
    const fallback = compiledArgs[compiledArgs.length - 1];
    let result = null;
    for (let i = compiledArgs.length - 3; i >= 1; i -= 2) {
      const match = compiledArgs[i];
      const output = compiledArgs[i + 1];
      result = `(${input} == ${match} ? ${output} : ${result || fallback})`;
    }
    return result;
  }),
  [Ops.Between]: createCompiler(
    ([value, min, max]) => `(${value} >= ${min} && ${value} <= ${max})`
  ),
  [Ops.Interpolate]: createCompiler(([exponent, input, ...compiledArgs]) => {
    let result = "";
    for (let i = 0; i < compiledArgs.length - 2; i += 2) {
      const stop1 = compiledArgs[i];
      const output1 = result || compiledArgs[i + 1];
      const stop2 = compiledArgs[i + 2];
      const output2 = compiledArgs[i + 3];
      let ratio;
      if (exponent === numberToGlsl(1)) {
        ratio = `(${input} - ${stop1}) / (${stop2} - ${stop1})`;
      } else {
        ratio = `(pow(${exponent}, (${input} - ${stop1})) - 1.0) / (pow(${exponent}, (${stop2} - ${stop1})) - 1.0)`;
      }
      result = `mix(${output1}, ${output2}, clamp(${ratio}, 0.0, 1.0))`;
    }
    return result;
  }),
  [Ops.Case]: createCompiler((compiledArgs) => {
    const fallback = compiledArgs[compiledArgs.length - 1];
    let result = null;
    for (let i = compiledArgs.length - 3; i >= 0; i -= 2) {
      const condition = compiledArgs[i];
      const output = compiledArgs[i + 1];
      result = `(${condition} ? ${output} : ${result || fallback})`;
    }
    return result;
  }),
  [Ops.In]: createCompiler(([needle, ...haystack], context) => {
    const funcName = computeOperatorFunctionName("in", context);
    const tests = [];
    for (let i = 0; i < haystack.length; i += 1) {
      tests.push(`  if (inputValue == ${haystack[i]}) { return true; }`);
    }
    context.functions[funcName] = `bool ${funcName}(float inputValue) {
${tests.join("\n")}
  return false;
}`;
    return `${funcName}(${needle})`;
  }),
  [Ops.Array]: createCompiler(
    (args) => `vec${args.length}(${args.join(", ")})`
  ),
  [Ops.Color]: createCompiler((compiledArgs) => {
    if (compiledArgs.length === 1) {
      return `vec4(vec3(${compiledArgs[0]} / 255.0), 1.0)`;
    }
    if (compiledArgs.length === 2) {
      return `vec4(vec3(${compiledArgs[0]} / 255.0), ${compiledArgs[1]})`;
    }
    const rgb = compiledArgs.slice(0, 3).map((color) => `${color} / 255.0`);
    if (compiledArgs.length === 3) {
      return `vec4(${rgb.join(", ")}, 1.0)`;
    }
    const alpha = compiledArgs[3];
    return `vec4(${rgb.join(", ")}, ${alpha})`;
  }),
  [Ops.Band]: createCompiler(([band, xOffset, yOffset], context) => {
    if (!(GET_BAND_VALUE_FUNC in context.functions)) {
      let ifBlocks = "";
      const bandCount = context.bandCount || 1;
      for (let i = 0; i < bandCount; i++) {
        const colorIndex = Math.floor(i / 4);
        let bandIndex = i % 4;
        if (i === bandCount - 1 && bandIndex === 1) {
          bandIndex = 3;
        }
        const textureName = `${Uniforms2.TILE_TEXTURE_ARRAY}[${colorIndex}]`;
        ifBlocks += `  if (band == ${i + 1}.0) {
    return texture2D(${textureName}, v_textureCoord + vec2(dx, dy))[${bandIndex}];
  }
`;
      }
      context.functions[GET_BAND_VALUE_FUNC] = `float getBandValue(float band, float xOffset, float yOffset) {
  float dx = xOffset / ${Uniforms2.TEXTURE_PIXEL_WIDTH};
  float dy = yOffset / ${Uniforms2.TEXTURE_PIXEL_HEIGHT};
${ifBlocks}
}`;
    }
    return `${GET_BAND_VALUE_FUNC}(${band}, ${xOffset ?? "0.0"}, ${yOffset ?? "0.0"})`;
  }),
  [Ops.Palette]: (context, expression) => {
    const [index, ...colors] = expression.args;
    const numColors = colors.length;
    const palette = new Uint8Array(numColors * 4);
    for (let i = 0; i < colors.length; i++) {
      const parsedValue = (
        /** @type {string | Array<number>} */
        /** @type {LiteralExpression} */
        colors[i].value
      );
      const color = asArray(parsedValue);
      const offset = i * 4;
      palette[offset] = color[0];
      palette[offset + 1] = color[1];
      palette[offset + 2] = color[2];
      palette[offset + 3] = color[3] * 255;
    }
    if (!context.paletteTextures) {
      context.paletteTextures = [];
    }
    const paletteName = `${PALETTE_TEXTURE_ARRAY}[${context.paletteTextures.length}]`;
    const paletteTexture = new PaletteTexture_default(paletteName, palette);
    context.paletteTextures.push(paletteTexture);
    const compiledIndex = compile(index, NumberType, context);
    return `texture2D(${paletteName}, vec2((${compiledIndex} + 0.5) / ${numColors}.0, 0.5))`;
  }
  // TODO: unimplemented
  // Ops.Number
  // Ops.String
  // Ops.Coalesce
  // Ops.Concat
  // Ops.ToString
};
function compile(expression, returnType, context) {
  if (expression instanceof CallExpression) {
    const compiler = compilers[expression.operator];
    if (compiler === void 0) {
      throw new Error(
        `No compiler defined for this operator: ${JSON.stringify(
          expression.operator
        )}`
      );
    }
    return compiler(context, expression, returnType);
  }
  if ((expression.type & NumberType) > 0) {
    return numberToGlsl(
      /** @type {number} */
      expression.value
    );
  }
  if ((expression.type & BooleanType) > 0) {
    return expression.value.toString();
  }
  if ((expression.type & StringType) > 0) {
    return stringToGlsl(expression.value.toString());
  }
  if ((expression.type & ColorType) > 0) {
    return colorToGlsl(
      /** @type {Array<number> | string} */
      expression.value
    );
  }
  if ((expression.type & NumberArrayType) > 0) {
    return arrayToGlsl(
      /** @type {Array<number>} */
      expression.value
    );
  }
  if ((expression.type & SizeType) > 0) {
    return sizeToGlsl(
      /** @type {number|import('../size.js').Size} */
      expression.value
    );
  }
  throw new Error(
    `Unexpected expression ${expression.value} (expected type ${typeName(
      returnType
    )})`
  );
}

// node_modules/ol/style/flat.js
function createDefaultStyle() {
  return {
    "fill-color": "rgba(255,255,255,0.4)",
    "stroke-color": "#3399CC",
    "stroke-width": 1.25,
    "circle-radius": 5,
    "circle-fill-color": "rgba(255,255,255,0.4)",
    "circle-stroke-width": 1.25,
    "circle-stroke-color": "#3399CC"
  };
}

// node_modules/ol/render/webgl/bufferUtil.js
var LINESTRING_ANGLE_COSINE_CUTOFF = 0.985;

// node_modules/ol/render/webgl/compileUtil.js
function expressionToGlsl(compilationContext, value, expectedType) {
  const parsingContext = newParsingContext();
  return buildExpression(
    value,
    expectedType,
    parsingContext,
    compilationContext
  );
}
function packColor(color) {
  const array = asArray(color);
  const r = array[0] * 256;
  const g = array[1];
  const b = array[2] * 256;
  const a = Math.round(array[3] * 255);
  return [r + g, b + a];
}
var UNPACK_COLOR_FN = `vec4 unpackColor(vec2 packedColor) {
  return vec4(
    min(floor(packedColor[0] / 256.0) / 255.0, 1.0),
    min(mod(packedColor[0], 256.0) / 255.0, 1.0),
    min(floor(packedColor[1] / 256.0) / 255.0, 1.0),
    min(mod(packedColor[1], 256.0) / 255.0, 1.0)
  );
}`;
function getGlslSizeFromType(type) {
  if (type === ColorType || type === SizeType) {
    return 2;
  }
  if (type === NumberArrayType) {
    return 4;
  }
  return 1;
}
function getGlslTypeFromType(type) {
  const size = getGlslSizeFromType(type);
  if (size > 1) {
    return (
      /** @type {'vec2'|'vec3'|'vec4'} */
      `vec${size}`
    );
  }
  return "float";
}
function applyContextToBuilder(builder, context) {
  for (const varName in context.variables) {
    const variable = context.variables[varName];
    const uniformName = uniformNameForVariable(variable.name);
    let glslType = getGlslTypeFromType(variable.type);
    if (variable.type === ColorType) {
      glslType = "vec4";
    }
    builder.addUniform(uniformName, glslType);
  }
  for (const propName in context.properties) {
    const property = context.properties[propName];
    const glslType = getGlslTypeFromType(property.type);
    const attributeName = `a_prop_${property.name}`;
    if (property.type === ColorType) {
      builder.addAttribute(
        attributeName,
        glslType,
        `unpackColor(${attributeName})`,
        "vec4"
      );
    } else {
      builder.addAttribute(attributeName, glslType);
    }
  }
  for (const functionName in context.functions) {
    builder.addVertexShaderFunction(context.functions[functionName]);
    builder.addFragmentShaderFunction(context.functions[functionName]);
  }
}
function generateUniformsFromContext(context, variables) {
  const uniforms = {};
  for (const varName in context.variables) {
    const variable = context.variables[varName];
    const uniformName = uniformNameForVariable(variable.name);
    uniforms[uniformName] = () => {
      const value = variables[variable.name];
      if (typeof value === "number") {
        return value;
      }
      if (typeof value === "boolean") {
        return value ? 1 : 0;
      }
      if (variable.type === ColorType) {
        const color = [...asArray(value || "#eee")];
        color[0] /= 255;
        color[1] /= 255;
        color[2] /= 255;
        color[3] ?? (color[3] = 1);
        return color;
      }
      if (typeof value === "string") {
        return getStringNumberEquivalent(value);
      }
      return value;
    };
  }
  return uniforms;
}
function generateAttributesFromContext(context) {
  const attributes = {};
  for (const propName in context.properties) {
    const property = context.properties[propName];
    const callback = (feature) => {
      const value = feature.get(property.name);
      if (property.type === ColorType) {
        return packColor([...asArray(value || "#eee")]);
      }
      if (typeof value === "string") {
        return getStringNumberEquivalent(value);
      }
      if (typeof value === "boolean") {
        return value ? 1 : 0;
      }
      return value;
    };
    attributes[`prop_${property.name}`] = {
      size: getGlslSizeFromType(property.type),
      callback
    };
  }
  return attributes;
}

// node_modules/ol/render/webgl/ShaderBuilder.js
var COMMON_HEADER = `#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
uniform mat4 u_projectionMatrix;
uniform mat4 u_screenToWorldMatrix;
uniform vec2 u_viewportSizePx;
uniform float u_pixelRatio;
uniform float u_globalAlpha;
uniform float u_time;
uniform float u_zoom;
uniform float u_resolution;
uniform float u_rotation;
uniform vec4 u_renderExtent;
uniform vec2 u_patternOrigin;
uniform float u_depth;
uniform mediump int u_hitDetection;

const float PI = 3.141592653589793238;
const float TWO_PI = 2.0 * PI;
float currentLineMetric = 0.; // an actual value will be used in the stroke shaders

${UNPACK_COLOR_FN}
`;
var DEFAULT_STYLE = createDefaultStyle();
var ShaderBuilder = class {
  constructor() {
    this.uniforms_ = [];
    this.attributes_ = [];
    this.hasSymbol_ = false;
    this.symbolSizeExpression_ = `vec2(${numberToGlsl(
      DEFAULT_STYLE["circle-radius"]
    )} + ${numberToGlsl(DEFAULT_STYLE["circle-stroke-width"] * 0.5)})`;
    this.symbolRotationExpression_ = "0.0";
    this.symbolOffsetExpression_ = "vec2(0.0)";
    this.symbolColorExpression_ = colorToGlsl(
      /** @type {string} */
      DEFAULT_STYLE["circle-fill-color"]
    );
    this.texCoordExpression_ = "vec4(0.0, 0.0, 1.0, 1.0)";
    this.discardExpression_ = "false";
    this.symbolRotateWithView_ = false;
    this.hasStroke_ = false;
    this.strokeWidthExpression_ = numberToGlsl(DEFAULT_STYLE["stroke-width"]);
    this.strokeColorExpression_ = colorToGlsl(
      /** @type {string} */
      DEFAULT_STYLE["stroke-color"]
    );
    this.strokeOffsetExpression_ = "0.";
    this.strokeCapExpression_ = stringToGlsl("round");
    this.strokeJoinExpression_ = stringToGlsl("round");
    this.strokeMiterLimitExpression_ = "10.";
    this.strokeDistanceFieldExpression_ = "-1000.";
    this.strokePatternLengthExpression_ = null;
    this.hasFill_ = false;
    this.fillColorExpression_ = colorToGlsl(
      /** @type {string} */
      DEFAULT_STYLE["fill-color"]
    );
    this.vertexShaderFunctions_ = [];
    this.fragmentShaderFunctions_ = [];
  }
  /**
   * Adds a uniform accessible in both fragment and vertex shaders.
   * The given name should include a type, such as `sampler2D u_texture`.
   * @param {string} name Uniform name, including the `u_` prefix
   * @param {'float'|'vec2'|'vec3'|'vec4'|'sampler2D'} type GLSL type
   * @return {ShaderBuilder} the builder object
   */
  addUniform(name, type) {
    this.uniforms_.push({
      name,
      type
    });
    return this;
  }
  /**
   * Adds an attribute accessible in the vertex shader, read from the geometry buffer.
   * The given name should include a type, such as `vec2 a_position`.
   * Attributes will also be made available under the same name in fragment shaders.
   * @param {string} name Attribute name, including the `a_` prefix
   * @param {'float'|'vec2'|'vec3'|'vec4'} type GLSL type
   * @param {string} [varyingExpression] Expression which will be assigned to the varying in the vertex shader, and
   * passed on to the fragment shader.
   * @param {'float'|'vec2'|'vec3'|'vec4'} [varyingType] Type of the attribute after transformation;
   * e.g. `vec4` after unpacking color components
   * @return {ShaderBuilder} the builder object
   */
  addAttribute(name, type, varyingExpression, varyingType) {
    this.attributes_.push({
      name,
      type,
      varyingName: name.replace(/^a_/, "v_"),
      varyingType: varyingType ?? type,
      varyingExpression: varyingExpression ?? name
    });
    return this;
  }
  /**
   * Sets an expression to compute the size of the shape.
   * This expression can use all the uniforms and attributes available
   * in the vertex shader, and should evaluate to a `vec2` value.
   * @param {string} expression Size expression
   * @return {ShaderBuilder} the builder object
   */
  setSymbolSizeExpression(expression) {
    this.hasSymbol_ = true;
    this.symbolSizeExpression_ = expression;
    return this;
  }
  /**
   * @return {string} The current symbol size expression
   */
  getSymbolSizeExpression() {
    return this.symbolSizeExpression_;
  }
  /**
   * Sets an expression to compute the rotation of the shape.
   * This expression can use all the uniforms and attributes available
   * in the vertex shader, and should evaluate to a `float` value in radians.
   * @param {string} expression Size expression
   * @return {ShaderBuilder} the builder object
   */
  setSymbolRotationExpression(expression) {
    this.symbolRotationExpression_ = expression;
    return this;
  }
  /**
   * Sets an expression to compute the offset of the symbol from the point center.
   * This expression can use all the uniforms and attributes available
   * in the vertex shader, and should evaluate to a `vec2` value.
   * @param {string} expression Offset expression
   * @return {ShaderBuilder} the builder object
   */
  setSymbolOffsetExpression(expression) {
    this.symbolOffsetExpression_ = expression;
    return this;
  }
  /**
   * @return {string} The current symbol offset expression
   */
  getSymbolOffsetExpression() {
    return this.symbolOffsetExpression_;
  }
  /**
   * Sets an expression to compute the color of the shape.
   * This expression can use all the uniforms, varyings and attributes available
   * in the fragment shader, and should evaluate to a `vec4` value.
   * @param {string} expression Color expression
   * @return {ShaderBuilder} the builder object
   */
  setSymbolColorExpression(expression) {
    this.hasSymbol_ = true;
    this.symbolColorExpression_ = expression;
    return this;
  }
  /**
   * @return {string} The current symbol color expression
   */
  getSymbolColorExpression() {
    return this.symbolColorExpression_;
  }
  /**
   * Sets an expression to compute the texture coordinates of the vertices.
   * This expression can use all the uniforms and attributes available
   * in the vertex shader, and should evaluate to a `vec4` value.
   * @param {string} expression Texture coordinate expression
   * @return {ShaderBuilder} the builder object
   */
  setTextureCoordinateExpression(expression) {
    this.texCoordExpression_ = expression;
    return this;
  }
  /**
   * Sets an expression to determine whether a fragment (pixel) should be discarded,
   * i.e. not drawn at all.
   * This expression can use all the uniforms, varyings and attributes available
   * in the fragment shader, and should evaluate to a `bool` value (it will be
   * used in an `if` statement)
   * @param {string} expression Fragment discard expression
   * @return {ShaderBuilder} the builder object
   */
  setFragmentDiscardExpression(expression) {
    this.discardExpression_ = expression;
    return this;
  }
  /**
   * @return {string} The current fragment discard expression
   */
  getFragmentDiscardExpression() {
    return this.discardExpression_;
  }
  /**
   * Sets whether the symbols should rotate with the view or stay aligned with the map.
   * Note: will only be used for point geometry shaders.
   * @param {boolean} rotateWithView Rotate with view
   * @return {ShaderBuilder} the builder object
   */
  setSymbolRotateWithView(rotateWithView) {
    this.symbolRotateWithView_ = rotateWithView;
    return this;
  }
  /**
   * @param {string} expression Stroke width expression, returning value in pixels
   * @return {ShaderBuilder} the builder object
   */
  setStrokeWidthExpression(expression) {
    this.hasStroke_ = true;
    this.strokeWidthExpression_ = expression;
    return this;
  }
  /**
   * @param {string} expression Stroke color expression, evaluate to `vec4`: can rely on currentLengthPx and currentRadiusPx
   * @return {ShaderBuilder} the builder object
   */
  setStrokeColorExpression(expression) {
    this.hasStroke_ = true;
    this.strokeColorExpression_ = expression;
    return this;
  }
  /**
   * @return {string} The current stroke color expression
   */
  getStrokeColorExpression() {
    return this.strokeColorExpression_;
  }
  /**
   * @param {string} expression Stroke color expression, evaluate to `float`
   * @return {ShaderBuilder} the builder object
   */
  setStrokeOffsetExpression(expression) {
    this.strokeOffsetExpression_ = expression;
    return this;
  }
  /**
   * @param {string} expression Stroke line cap expression, evaluate to `float`
   * @return {ShaderBuilder} the builder object
   */
  setStrokeCapExpression(expression) {
    this.strokeCapExpression_ = expression;
    return this;
  }
  /**
   * @param {string} expression Stroke line join expression, evaluate to `float`
   * @return {ShaderBuilder} the builder object
   */
  setStrokeJoinExpression(expression) {
    this.strokeJoinExpression_ = expression;
    return this;
  }
  /**
   * @param {string} expression Stroke miter limit expression, evaluate to `float`
   * @return {ShaderBuilder} the builder object
   */
  setStrokeMiterLimitExpression(expression) {
    this.strokeMiterLimitExpression_ = expression;
    return this;
  }
  /**
   * @param {string} expression Stroke distance field expression, evaluate to `float`
   * This can override the default distance field; can rely on currentLengthPx and currentRadiusPx
   * @return {ShaderBuilder} the builder object
   */
  setStrokeDistanceFieldExpression(expression) {
    this.strokeDistanceFieldExpression_ = expression;
    return this;
  }
  /**
   * Defining a pattern length for a stroke lets us avoid having visual artifacts when
   * a linestring is very long and thus has very high "distance" attributes on its vertices.
   * If we apply a pattern or dash array to a stroke we know for certain that the full distance value
   * is not necessary and can be trimmed down using `mod(currentDistance, patternLength)`.
   * @param {string} expression Stroke expression that evaluates to a`float; value is expected to be
   * in pixels.
   * @return {ShaderBuilder} the builder object
   */
  setStrokePatternLengthExpression(expression) {
    this.strokePatternLengthExpression_ = expression;
    return this;
  }
  /**
   * @return {string} The current stroke pattern length expression.
   */
  getStrokePatternLengthExpression() {
    return this.strokePatternLengthExpression_;
  }
  /**
   * @param {string} expression Fill color expression, evaluate to `vec4`
   * @return {ShaderBuilder} the builder object
   */
  setFillColorExpression(expression) {
    this.hasFill_ = true;
    this.fillColorExpression_ = expression;
    return this;
  }
  /**
   * @return {string} The current fill color expression
   */
  getFillColorExpression() {
    return this.fillColorExpression_;
  }
  addVertexShaderFunction(code) {
    if (this.vertexShaderFunctions_.includes(code)) {
      return this;
    }
    this.vertexShaderFunctions_.push(code);
    return this;
  }
  addFragmentShaderFunction(code) {
    if (this.fragmentShaderFunctions_.includes(code)) {
      return this;
    }
    this.fragmentShaderFunctions_.push(code);
    return this;
  }
  /**
   * Generates a symbol vertex shader from the builder parameters
   * @return {string|null} The full shader as a string; null if no size or color specified
   */
  getSymbolVertexShader() {
    if (!this.hasSymbol_) {
      return null;
    }
    return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join("\n")}
attribute vec2 a_position;
attribute vec2 a_localPosition;
attribute vec2 a_hitColor;

varying vec2 v_texCoord;
varying vec2 v_quadCoord;
varying vec4 v_hitColor;
varying vec2 v_centerPx;
varying float v_angle;
varying vec2 v_quadSizePx;

${this.attributes_.map(
      (attribute) => `attribute ${attribute.type} ${attribute.name};
varying ${attribute.varyingType} ${attribute.varyingName};`
    ).join("\n")}
${this.vertexShaderFunctions_.join("\n")}
vec2 pxToScreen(vec2 coordPx) {
  vec2 scaled = coordPx / u_viewportSizePx / 0.5;
  return scaled;
}

vec2 screenToPx(vec2 coordScreen) {
  return (coordScreen * 0.5 + 0.5) * u_viewportSizePx;
}

void main(void) {
  v_quadSizePx = ${this.symbolSizeExpression_};
  vec2 halfSizePx = v_quadSizePx * 0.5;
  vec2 centerOffsetPx = ${this.symbolOffsetExpression_};
  vec2 offsetPx = centerOffsetPx + a_localPosition * halfSizePx * vec2(1., -1.);
  float angle = ${this.symbolRotationExpression_}${this.symbolRotateWithView_ ? " + u_rotation" : ""};
  float c = cos(-angle);
  float s = sin(-angle);
  offsetPx = vec2(c * offsetPx.x - s * offsetPx.y, s * offsetPx.x + c * offsetPx.y);
  vec4 center = u_projectionMatrix * vec4(a_position, 0.0, 1.0);
  gl_Position = center + vec4(pxToScreen(offsetPx), u_depth, 0.);
  vec4 texCoord = ${this.texCoordExpression_};
  float u = mix(texCoord.s, texCoord.p, a_localPosition.x * 0.5 + 0.5);
  float v = mix(texCoord.t, texCoord.q, a_localPosition.y * 0.5 + 0.5);
  v_texCoord = vec2(u, v);
  v_hitColor = unpackColor(a_hitColor);
  v_angle = angle;
  c = cos(-v_angle);
  s = sin(-v_angle);
  centerOffsetPx = vec2(c * centerOffsetPx.x - s * centerOffsetPx.y, s * centerOffsetPx.x + c * centerOffsetPx.y);
  v_centerPx = screenToPx(center.xy) + centerOffsetPx;
${this.attributes_.map(
      (attribute) => `  ${attribute.varyingName} = ${attribute.varyingExpression};`
    ).join("\n")}
}`;
  }
  /**
   * Generates a symbol fragment shader from the builder parameters
   * @return {string|null} The full shader as a string; null if no size or color specified
   */
  getSymbolFragmentShader() {
    if (!this.hasSymbol_) {
      return null;
    }
    return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join("\n")}
varying vec2 v_texCoord;
varying vec4 v_hitColor;
varying vec2 v_centerPx;
varying float v_angle;
varying vec2 v_quadSizePx;
${this.attributes_.map(
      (attribute) => `varying ${attribute.varyingType} ${attribute.varyingName};`
    ).join("\n")}
${this.fragmentShaderFunctions_.join("\n")}

void main(void) {
${this.attributes_.map(
      (attribute) => `  ${attribute.varyingType} ${attribute.name} = ${attribute.varyingName}; // assign to original attribute name`
    ).join("\n")}
  if (${this.discardExpression_}) { discard; }
  vec2 coordsPx = gl_FragCoord.xy / u_pixelRatio - v_centerPx; // relative to center
  float c = cos(v_angle);
  float s = sin(v_angle);
  coordsPx = vec2(c * coordsPx.x - s * coordsPx.y, s * coordsPx.x + c * coordsPx.y);
  gl_FragColor = ${this.symbolColorExpression_};
  gl_FragColor.rgb *= gl_FragColor.a;
  if (u_hitDetection > 0) {
    if (gl_FragColor.a < 0.05) { discard; };
    gl_FragColor = v_hitColor;
  }
}`;
  }
  /**
   * Generates a stroke vertex shader from the builder parameters
   * @return {string|null} The full shader as a string; null if no size or color specified
   */
  getStrokeVertexShader() {
    if (!this.hasStroke_) {
      return null;
    }
    return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join("\n")}
attribute vec2 a_segmentStart;
attribute vec2 a_segmentEnd;
attribute vec2 a_localPosition;
attribute float a_measureStart;
attribute float a_measureEnd;
attribute float a_angleTangentSum;
attribute float a_distanceLow;
attribute float a_distanceHigh;
attribute vec2 a_joinAngles;
attribute vec2 a_hitColor;

varying vec2 v_segmentStartPx;
varying vec2 v_segmentEndPx;
varying float v_angleStart;
varying float v_angleEnd;
varying float v_width;
varying vec4 v_hitColor;
varying float v_distancePx;
varying float v_measureStart;
varying float v_measureEnd;

${this.attributes_.map(
      (attribute) => `attribute ${attribute.type} ${attribute.name};
varying ${attribute.varyingType} ${attribute.varyingName};`
    ).join("\n")}
${this.vertexShaderFunctions_.join("\n")}
vec2 worldToPx(vec2 worldPos) {
  vec4 screenPos = u_projectionMatrix * vec4(worldPos, 0.0, 1.0);
  return (0.5 * screenPos.xy + 0.5) * u_viewportSizePx;
}

vec4 pxToScreen(vec2 pxPos) {
  vec2 screenPos = 2.0 * pxPos / u_viewportSizePx - 1.0;
  return vec4(screenPos, u_depth, 1.0);
}

bool isCap(float joinAngle) {
  return joinAngle < -0.1;
}

vec2 getJoinOffsetDirection(vec2 normalPx, float joinAngle) {
  float halfAngle = joinAngle / 2.0;
  float c = cos(halfAngle);
  float s = sin(halfAngle);
  vec2 angleBisectorNormal = vec2(s * normalPx.x + c * normalPx.y, -c * normalPx.x + s * normalPx.y);
  float length = 1.0 / s;
  return angleBisectorNormal * length;
}

vec2 getOffsetPoint(vec2 point, vec2 normal, float joinAngle, float offsetPx) {
  // if on a cap or the join angle is too high, offset the line along the segment normal
  if (cos(joinAngle) > 0.998 || isCap(joinAngle)) {
    return point - normal * offsetPx;
  }
  // offset is applied along the inverted normal (positive offset goes "right" relative to line direction)
  return point - getJoinOffsetDirection(normal, joinAngle) * offsetPx;
}

void main(void) {
  v_angleStart = a_joinAngles.x;
  v_angleEnd = a_joinAngles.y;
  float startEndRatio = a_localPosition.x * 0.5 + 0.5;
  currentLineMetric = mix(a_measureStart, a_measureEnd, startEndRatio);
  // we're reading the fractional part while keeping the sign (so -4.12 gives -0.12, 3.45 gives 0.45)

  float lineWidth = ${this.strokeWidthExpression_};
  float lineOffsetPx = ${this.strokeOffsetExpression_};

  // compute segment start/end in px with offset
  vec2 segmentStartPx = worldToPx(a_segmentStart);
  vec2 segmentEndPx = worldToPx(a_segmentEnd);
  vec2 tangentPx = normalize(segmentEndPx - segmentStartPx);
  vec2 normalPx = vec2(-tangentPx.y, tangentPx.x);
  segmentStartPx = getOffsetPoint(segmentStartPx, normalPx, v_angleStart, lineOffsetPx),
  segmentEndPx = getOffsetPoint(segmentEndPx, normalPx, v_angleEnd, lineOffsetPx);

  // compute current vertex position
  float normalDir = -1. * a_localPosition.y;
  float tangentDir = -1. * a_localPosition.x;
  float angle = mix(v_angleStart, v_angleEnd, startEndRatio);
  vec2 joinDirection;
  vec2 positionPx = mix(segmentStartPx, segmentEndPx, startEndRatio);
  // if angle is too high, do not make a proper join
  if (cos(angle) > ${LINESTRING_ANGLE_COSINE_CUTOFF} || isCap(angle)) {
    joinDirection = normalPx * normalDir - tangentPx * tangentDir;
  } else {
    joinDirection = getJoinOffsetDirection(normalPx * normalDir, angle);
  }
  positionPx = positionPx + joinDirection * (lineWidth * 0.5 + 1.); // adding 1 pixel for antialiasing
  gl_Position = pxToScreen(positionPx);

  v_segmentStartPx = segmentStartPx;
  v_segmentEndPx = segmentEndPx;
  v_width = lineWidth;
  v_hitColor = unpackColor(a_hitColor);

  v_distancePx = a_distanceLow / u_resolution - (lineOffsetPx * a_angleTangentSum);
  float distanceHighPx = a_distanceHigh / u_resolution;
  ${this.strokePatternLengthExpression_ !== null ? `v_distancePx = mod(v_distancePx, ${this.strokePatternLengthExpression_});
  distanceHighPx = mod(distanceHighPx, ${this.strokePatternLengthExpression_});
  ` : ""}v_distancePx += distanceHighPx;

  v_measureStart = a_measureStart;
  v_measureEnd = a_measureEnd;
${this.attributes_.map(
      (attribute) => `  ${attribute.varyingName} = ${attribute.varyingExpression};`
    ).join("\n")}
}`;
  }
  /**
   * Generates a stroke fragment shader from the builder parameters
   *
   * @return {string|null} The full shader as a string; null if no size or color specified
   */
  getStrokeFragmentShader() {
    if (!this.hasStroke_) {
      return null;
    }
    return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join("\n")}
varying vec2 v_segmentStartPx;
varying vec2 v_segmentEndPx;
varying float v_angleStart;
varying float v_angleEnd;
varying float v_width;
varying vec4 v_hitColor;
varying float v_distancePx;
varying float v_measureStart;
varying float v_measureEnd;
${this.attributes_.map(
      (attribute) => `varying ${attribute.varyingType} ${attribute.varyingName};`
    ).join("\n")}
${this.fragmentShaderFunctions_.join("\n")}

vec2 pxToWorld(vec2 pxPos) {
  vec2 screenPos = 2.0 * pxPos / u_viewportSizePx - 1.0;
  return (u_screenToWorldMatrix * vec4(screenPos, 0.0, 1.0)).xy;
}

bool isCap(float joinAngle) {
  return joinAngle < -0.1;
}

float segmentDistanceField(vec2 point, vec2 start, vec2 end, float width) {
  vec2 tangent = normalize(end - start);
  vec2 normal = vec2(-tangent.y, tangent.x);
  vec2 startToPoint = point - start;
  return abs(dot(startToPoint, normal)) - width * 0.5;
}

float buttCapDistanceField(vec2 point, vec2 start, vec2 end) {
  vec2 startToPoint = point - start;
  vec2 tangent = normalize(end - start);
  return dot(startToPoint, -tangent);
}

float squareCapDistanceField(vec2 point, vec2 start, vec2 end, float width) {
  return buttCapDistanceField(point, start, end) - width * 0.5;
}

float roundCapDistanceField(vec2 point, vec2 start, vec2 end, float width) {
  float onSegment = max(0., 1000. * dot(point - start, end - start)); // this is very high when inside the segment
  return length(point - start) - width * 0.5 - onSegment;
}

float roundJoinDistanceField(vec2 point, vec2 start, vec2 end, float width) {
  return roundCapDistanceField(point, start, end, width);
}

float bevelJoinField(vec2 point, vec2 start, vec2 end, float width, float joinAngle) {
  vec2 startToPoint = point - start;
  vec2 tangent = normalize(end - start);
  float c = cos(joinAngle * 0.5);
  float s = sin(joinAngle * 0.5);
  float direction = -sign(sin(joinAngle));
  vec2 bisector = vec2(c * tangent.x - s * tangent.y, s * tangent.x + c * tangent.y);
  float radius = width * 0.5 * s;
  return dot(startToPoint, bisector * direction) - radius;
}

float miterJoinDistanceField(vec2 point, vec2 start, vec2 end, float width, float joinAngle) {
  if (cos(joinAngle) > ${LINESTRING_ANGLE_COSINE_CUTOFF}) { // avoid risking a division by zero
    return bevelJoinField(point, start, end, width, joinAngle);
  }
  float miterLength = 1. / sin(joinAngle * 0.5);
  float miterLimit = ${this.strokeMiterLimitExpression_};
  if (miterLength > miterLimit) {
    return bevelJoinField(point, start, end, width, joinAngle);
  }
  return -1000.;
}

float capDistanceField(vec2 point, vec2 start, vec2 end, float width, float capType) {
   if (capType == ${stringToGlsl("butt")}) {
    return buttCapDistanceField(point, start, end);
  } else if (capType == ${stringToGlsl("square")}) {
    return squareCapDistanceField(point, start, end, width);
  }
  return roundCapDistanceField(point, start, end, width);
}

float joinDistanceField(vec2 point, vec2 start, vec2 end, float width, float joinAngle, float joinType) {
  if (joinType == ${stringToGlsl("bevel")}) {
    return bevelJoinField(point, start, end, width, joinAngle);
  } else if (joinType == ${stringToGlsl("miter")}) {
    return miterJoinDistanceField(point, start, end, width, joinAngle);
  }
  return roundJoinDistanceField(point, start, end, width);
}

float computeSegmentPointDistance(vec2 point, vec2 start, vec2 end, float width, float joinAngle, float capType, float joinType) {
  if (isCap(joinAngle)) {
    return capDistanceField(point, start, end, width, capType);
  }
  return joinDistanceField(point, start, end, width, joinAngle, joinType);
}

float distanceFromSegment(vec2 point, vec2 start, vec2 end) {
  vec2 tangent = end - start;
  vec2 startToPoint = point - start;
  // inspire by capsule fn in https://iquilezles.org/articles/distfunctions/
  float h = clamp(dot(startToPoint, tangent) / dot(tangent, tangent), 0.0, 1.0);
  return length(startToPoint - tangent * h);
}

void main(void) {
${this.attributes_.map(
      (attribute) => `  ${attribute.varyingType} ${attribute.name} = ${attribute.varyingName}; // assign to original attribute name`
    ).join("\n")}

  vec2 currentPointPx = gl_FragCoord.xy / u_pixelRatio;
  #ifdef GL_FRAGMENT_PRECISION_HIGH
  vec2 worldPos = pxToWorld(currentPointPx);
  if (
    abs(u_renderExtent[0] - u_renderExtent[2]) > 0.0 && (
      worldPos[0] < u_renderExtent[0] ||
      worldPos[1] < u_renderExtent[1] ||
      worldPos[0] > u_renderExtent[2] ||
      worldPos[1] > u_renderExtent[3]
    )
  ) {
    discard;
  }
  #endif

  float segmentLengthPx = length(v_segmentEndPx - v_segmentStartPx);
  segmentLengthPx = max(segmentLengthPx, 1.17549429e-38); // avoid divide by zero
  vec2 segmentTangent = (v_segmentEndPx - v_segmentStartPx) / segmentLengthPx;
  vec2 segmentNormal = vec2(-segmentTangent.y, segmentTangent.x);
  vec2 startToPointPx = currentPointPx - v_segmentStartPx;
  float lengthToPointPx = max(0., min(dot(segmentTangent, startToPointPx), segmentLengthPx));
  float currentLengthPx = lengthToPointPx + v_distancePx;
  float currentRadiusPx = distanceFromSegment(currentPointPx, v_segmentStartPx, v_segmentEndPx);
  float currentRadiusRatio = dot(segmentNormal, startToPointPx) * 2. / v_width;
  currentLineMetric = mix(v_measureStart, v_measureEnd, lengthToPointPx / segmentLengthPx);

  if (${this.discardExpression_}) { discard; }

  float capType = ${this.strokeCapExpression_};
  float joinType = ${this.strokeJoinExpression_};
  float segmentStartDistance = computeSegmentPointDistance(currentPointPx, v_segmentStartPx, v_segmentEndPx, v_width, v_angleStart, capType, joinType);
  float segmentEndDistance = computeSegmentPointDistance(currentPointPx, v_segmentEndPx, v_segmentStartPx, v_width, v_angleEnd, capType, joinType);
  float distanceField = max(
    segmentDistanceField(currentPointPx, v_segmentStartPx, v_segmentEndPx, v_width),
    max(segmentStartDistance, segmentEndDistance)
  );
  distanceField = max(distanceField, ${this.strokeDistanceFieldExpression_});

  vec4 color = ${this.strokeColorExpression_};
  color.a *= smoothstep(0.5, -0.5, distanceField);
  gl_FragColor = color;
  gl_FragColor.a *= u_globalAlpha;
  gl_FragColor.rgb *= gl_FragColor.a;
  if (u_hitDetection > 0) {
    if (gl_FragColor.a < 0.1) { discard; };
    gl_FragColor = v_hitColor;
  }
}`;
  }
  /**
   * Generates a fill vertex shader from the builder parameters
   *
   * @return {string|null} The full shader as a string; null if no color specified
   */
  getFillVertexShader() {
    if (!this.hasFill_) {
      return null;
    }
    return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join("\n")}
attribute vec2 a_position;
attribute vec2 a_hitColor;

varying vec4 v_hitColor;

${this.attributes_.map(
      (attribute) => `attribute ${attribute.type} ${attribute.name};
varying ${attribute.varyingType} ${attribute.varyingName};`
    ).join("\n")}
${this.vertexShaderFunctions_.join("\n")}
void main(void) {
  gl_Position = u_projectionMatrix * vec4(a_position, u_depth, 1.0);
  v_hitColor = unpackColor(a_hitColor);
${this.attributes_.map(
      (attribute) => `  ${attribute.varyingName} = ${attribute.varyingExpression};`
    ).join("\n")}
}`;
  }
  /**
   * Generates a fill fragment shader from the builder parameters
   * @return {string|null} The full shader as a string; null if no color specified
   */
  getFillFragmentShader() {
    if (!this.hasFill_) {
      return null;
    }
    return `${COMMON_HEADER}
${this.uniforms_.map((uniform) => `uniform ${uniform.type} ${uniform.name};`).join("\n")}
varying vec4 v_hitColor;
${this.attributes_.map(
      (attribute) => `varying ${attribute.varyingType} ${attribute.varyingName};`
    ).join("\n")}
${this.fragmentShaderFunctions_.join("\n")}
vec2 pxToWorld(vec2 pxPos) {
  vec2 screenPos = 2.0 * pxPos / u_viewportSizePx - 1.0;
  return (u_screenToWorldMatrix * vec4(screenPos, 0.0, 1.0)).xy;
}

vec2 worldToPx(vec2 worldPos) {
  vec4 screenPos = u_projectionMatrix * vec4(worldPos, 0.0, 1.0);
  return (0.5 * screenPos.xy + 0.5) * u_viewportSizePx;
}

void main(void) {
${this.attributes_.map(
      (attribute) => `  ${attribute.varyingType} ${attribute.name} = ${attribute.varyingName}; // assign to original attribute name`
    ).join("\n")}
  vec2 pxPos = gl_FragCoord.xy / u_pixelRatio;
  vec2 pxOrigin = worldToPx(u_patternOrigin);
  #ifdef GL_FRAGMENT_PRECISION_HIGH
  vec2 worldPos = pxToWorld(pxPos);
  if (
    abs(u_renderExtent[0] - u_renderExtent[2]) > 0.0 && (
      worldPos[0] < u_renderExtent[0] ||
      worldPos[1] < u_renderExtent[1] ||
      worldPos[0] > u_renderExtent[2] ||
      worldPos[1] > u_renderExtent[3]
    )
  ) {
    discard;
  }
  #endif
  if (${this.discardExpression_}) { discard; }
  gl_FragColor = ${this.fillColorExpression_};
  gl_FragColor.a *= u_globalAlpha;
  gl_FragColor.rgb *= gl_FragColor.a;
  if (u_hitDetection > 0) {
    if (gl_FragColor.a < 0.1) { discard; };
    gl_FragColor = v_hitColor;
  }
}`;
  }
};

// node_modules/ol/render/webgl/MixedGeometryBatch.js
var MixedGeometryBatch = class _MixedGeometryBatch {
  constructor() {
    this.globalCounter_ = 0;
    this.refToFeature_ = /* @__PURE__ */ new Map();
    this.uidToRef_ = /* @__PURE__ */ new Map();
    this.freeGlobalRef_ = [];
    this.polygonBatch = {
      entries: {},
      geometriesCount: 0,
      verticesCount: 0,
      ringsCount: 0
    };
    this.pointBatch = {
      entries: {},
      geometriesCount: 0
    };
    this.lineStringBatch = {
      entries: {},
      geometriesCount: 0,
      verticesCount: 0
    };
  }
  /**
   * @param {Array<Feature|RenderFeature>} features Array of features to add to the batch
   * @param {import("../../proj.js").TransformFunction} [projectionTransform] Projection transform.
   */
  addFeatures(features, projectionTransform) {
    for (let i = 0; i < features.length; i++) {
      this.addFeature(features[i], projectionTransform);
    }
  }
  /**
   * @param {Feature|RenderFeature} feature Feature to add to the batch
   * @param {import("../../proj.js").TransformFunction} [projectionTransform] Projection transform.
   */
  addFeature(feature, projectionTransform) {
    let geometry = feature.getGeometry();
    if (!geometry) {
      return;
    }
    if (projectionTransform) {
      geometry = geometry.clone();
      geometry.applyTransform(projectionTransform);
    }
    this.addGeometry_(geometry, feature);
  }
  /**
   * @param {Feature|RenderFeature} feature Feature
   * @return {GeometryBatchItem|void} the cleared entry
   * @private
   */
  clearFeatureEntryInPointBatch_(feature) {
    const featureUid = getUid(feature);
    const entry = this.pointBatch.entries[featureUid];
    if (!entry) {
      return;
    }
    this.pointBatch.geometriesCount -= entry.flatCoordss.length;
    delete this.pointBatch.entries[featureUid];
    return entry;
  }
  /**
   * @param {Feature|RenderFeature} feature Feature
   * @return {GeometryBatchItem|void} the cleared entry
   * @private
   */
  clearFeatureEntryInLineStringBatch_(feature) {
    const featureUid = getUid(feature);
    const entry = this.lineStringBatch.entries[featureUid];
    if (!entry) {
      return;
    }
    this.lineStringBatch.verticesCount -= entry.verticesCount;
    this.lineStringBatch.geometriesCount -= entry.flatCoordss.length;
    delete this.lineStringBatch.entries[featureUid];
    return entry;
  }
  /**
   * @param {Feature|RenderFeature} feature Feature
   * @return {GeometryBatchItem|void} the cleared entry
   * @private
   */
  clearFeatureEntryInPolygonBatch_(feature) {
    const featureUid = getUid(feature);
    const entry = this.polygonBatch.entries[featureUid];
    if (!entry) {
      return;
    }
    this.polygonBatch.verticesCount -= entry.verticesCount;
    this.polygonBatch.ringsCount -= entry.ringsCount;
    this.polygonBatch.geometriesCount -= entry.flatCoordss.length;
    delete this.polygonBatch.entries[featureUid];
    return entry;
  }
  /**
   * @param {import("../../geom.js").Geometry|RenderFeature} geometry Geometry
   * @param {Feature|RenderFeature} feature Feature
   * @private
   */
  addGeometry_(geometry, feature) {
    var _a;
    const type = geometry.getType();
    switch (type) {
      case "GeometryCollection": {
        const geometries = (
          /** @type {import("../../geom.js").GeometryCollection} */
          geometry.getGeometriesArray()
        );
        for (const geometry2 of geometries) {
          this.addGeometry_(geometry2, feature);
        }
        break;
      }
      case "MultiPolygon": {
        const multiPolygonGeom = (
          /** @type {import("../../geom.js").MultiPolygon} */
          geometry
        );
        this.addCoordinates_(
          type,
          multiPolygonGeom.getFlatCoordinates(),
          multiPolygonGeom.getEndss(),
          feature,
          getUid(feature),
          multiPolygonGeom.getStride()
        );
        break;
      }
      case "MultiLineString": {
        const multiLineGeom = (
          /** @type {import("../../geom.js").MultiLineString|RenderFeature} */
          geometry
        );
        this.addCoordinates_(
          type,
          multiLineGeom.getFlatCoordinates(),
          multiLineGeom.getEnds(),
          feature,
          getUid(feature),
          multiLineGeom.getStride()
        );
        break;
      }
      case "MultiPoint": {
        const multiPointGeom = (
          /** @type {import("../../geom.js").MultiPoint|RenderFeature} */
          geometry
        );
        this.addCoordinates_(
          type,
          multiPointGeom.getFlatCoordinates(),
          null,
          feature,
          getUid(feature),
          multiPointGeom.getStride()
        );
        break;
      }
      case "Polygon": {
        const polygonGeom = (
          /** @type {import("../../geom.js").Polygon|RenderFeature} */
          geometry
        );
        this.addCoordinates_(
          type,
          polygonGeom.getFlatCoordinates(),
          polygonGeom.getEnds(),
          feature,
          getUid(feature),
          polygonGeom.getStride()
        );
        break;
      }
      case "Point": {
        const pointGeom = (
          /** @type {import("../../geom.js").Point} */
          geometry
        );
        this.addCoordinates_(
          type,
          pointGeom.getFlatCoordinates(),
          null,
          feature,
          getUid(feature),
          pointGeom.getStride()
        );
        break;
      }
      case "LineString":
      case "LinearRing": {
        const lineGeom = (
          /** @type {import("../../geom.js").LineString} */
          geometry
        );
        const stride = lineGeom.getStride();
        this.addCoordinates_(
          type,
          lineGeom.getFlatCoordinates(),
          null,
          feature,
          getUid(feature),
          stride,
          (_a = lineGeom.getLayout) == null ? void 0 : _a.call(lineGeom)
        );
        break;
      }
      default:
    }
  }
  /**
   * @param {GeometryType} type Geometry type
   * @param {Array<number>} flatCoords Flat coordinates
   * @param {Array<number> | Array<Array<number>> | null} ends Coordinate ends
   * @param {Feature|RenderFeature} feature Feature
   * @param {string} featureUid Feature uid
   * @param {number} stride Stride
   * @param {import('../../geom/Geometry.js').GeometryLayout} [layout] Layout
   * @private
   */
  addCoordinates_(type, flatCoords, ends, feature, featureUid, stride, layout) {
    let verticesCount;
    switch (type) {
      case "MultiPolygon": {
        const multiPolygonEndss = (
          /** @type {Array<Array<number>>} */
          ends
        );
        for (let i = 0, ii = multiPolygonEndss.length; i < ii; i++) {
          let polygonEnds = multiPolygonEndss[i];
          const prevPolygonEnds = i > 0 ? multiPolygonEndss[i - 1] : null;
          const startIndex = prevPolygonEnds ? prevPolygonEnds[prevPolygonEnds.length - 1] : 0;
          const endIndex = polygonEnds[polygonEnds.length - 1];
          polygonEnds = startIndex > 0 ? polygonEnds.map((end) => end - startIndex) : polygonEnds;
          this.addCoordinates_(
            "Polygon",
            flatCoords.slice(startIndex, endIndex),
            polygonEnds,
            feature,
            featureUid,
            stride,
            layout
          );
        }
        break;
      }
      case "MultiLineString": {
        const multiLineEnds = (
          /** @type {Array<number>} */
          ends
        );
        for (let i = 0, ii = multiLineEnds.length; i < ii; i++) {
          const startIndex = i > 0 ? multiLineEnds[i - 1] : 0;
          this.addCoordinates_(
            "LineString",
            flatCoords.slice(startIndex, multiLineEnds[i]),
            null,
            feature,
            featureUid,
            stride,
            layout
          );
        }
        break;
      }
      case "MultiPoint":
        for (let i = 0, ii = flatCoords.length; i < ii; i += stride) {
          this.addCoordinates_(
            "Point",
            flatCoords.slice(i, i + 2),
            null,
            feature,
            featureUid,
            null,
            null
          );
        }
        break;
      case "Polygon": {
        const polygonEnds = (
          /** @type {Array<number>} */
          ends
        );
        if (feature instanceof Feature_default) {
          const multiPolygonEnds = inflateEnds(flatCoords, polygonEnds);
          if (multiPolygonEnds.length > 1) {
            this.addCoordinates_(
              "MultiPolygon",
              flatCoords,
              multiPolygonEnds,
              feature,
              featureUid,
              stride,
              layout
            );
            return;
          }
        }
        if (!this.polygonBatch.entries[featureUid]) {
          this.polygonBatch.entries[featureUid] = this.addRefToEntry_(
            featureUid,
            {
              feature,
              flatCoordss: [],
              verticesCount: 0,
              ringsCount: 0,
              ringsVerticesCounts: []
            }
          );
        }
        verticesCount = flatCoords.length / stride;
        const ringsCount = ends.length;
        const ringsVerticesCount = ends.map(
          (end, ind, arr) => ind > 0 ? (end - arr[ind - 1]) / stride : end / stride
        );
        this.polygonBatch.verticesCount += verticesCount;
        this.polygonBatch.ringsCount += ringsCount;
        this.polygonBatch.geometriesCount++;
        this.polygonBatch.entries[featureUid].flatCoordss.push(
          getFlatCoordinatesXY(flatCoords, stride)
        );
        this.polygonBatch.entries[featureUid].ringsVerticesCounts.push(
          ringsVerticesCount
        );
        this.polygonBatch.entries[featureUid].verticesCount += verticesCount;
        this.polygonBatch.entries[featureUid].ringsCount += ringsCount;
        for (let i = 0, ii = polygonEnds.length; i < ii; i++) {
          const startIndex = i > 0 ? polygonEnds[i - 1] : 0;
          this.addCoordinates_(
            "LinearRing",
            flatCoords.slice(startIndex, polygonEnds[i]),
            null,
            feature,
            featureUid,
            stride,
            layout
          );
        }
        break;
      }
      case "Point":
        if (!this.pointBatch.entries[featureUid]) {
          this.pointBatch.entries[featureUid] = this.addRefToEntry_(
            featureUid,
            {
              feature,
              flatCoordss: []
            }
          );
        }
        this.pointBatch.geometriesCount++;
        this.pointBatch.entries[featureUid].flatCoordss.push(flatCoords);
        break;
      case "LineString":
      case "LinearRing":
        if (!this.lineStringBatch.entries[featureUid]) {
          this.lineStringBatch.entries[featureUid] = this.addRefToEntry_(
            featureUid,
            {
              feature,
              flatCoordss: [],
              verticesCount: 0
            }
          );
        }
        verticesCount = flatCoords.length / stride;
        this.lineStringBatch.verticesCount += verticesCount;
        this.lineStringBatch.geometriesCount++;
        this.lineStringBatch.entries[featureUid].flatCoordss.push(
          getFlatCoordinatesXYM(flatCoords, stride, layout)
        );
        this.lineStringBatch.entries[featureUid].verticesCount += verticesCount;
        break;
      default:
    }
  }
  /**
   * @param {string} featureUid Feature uid
   * @param {GeometryBatchItem} entry The entry to add
   * @return {GeometryBatchItem} the added entry
   * @private
   */
  addRefToEntry_(featureUid, entry) {
    const currentRef = this.uidToRef_.get(featureUid);
    const ref = currentRef || this.freeGlobalRef_.pop() || ++this.globalCounter_;
    entry.ref = ref;
    if (!currentRef) {
      this.refToFeature_.set(ref, entry.feature);
      this.uidToRef_.set(featureUid, ref);
    }
    return entry;
  }
  /**
   * Return a ref to the pool of available refs.
   * @param {number} ref the ref to return
   * @param {string} featureUid the feature uid
   * @private
   */
  removeRef_(ref, featureUid) {
    if (!ref) {
      throw new Error("This feature has no ref: " + featureUid);
    }
    this.refToFeature_.delete(ref);
    this.uidToRef_.delete(featureUid);
    this.freeGlobalRef_.push(ref);
  }
  /**
   * @param {Feature|RenderFeature} feature Feature
   * @param {import("../../proj.js").TransformFunction} [projectionTransform] Projection transform.
   */
  changeFeature(feature, projectionTransform) {
    if (!this.uidToRef_.get(getUid(feature))) {
      return;
    }
    this.removeFeature(feature);
    let geometry = feature.getGeometry();
    if (!geometry) {
      return;
    }
    if (projectionTransform) {
      geometry = geometry.clone();
      geometry.applyTransform(projectionTransform);
    }
    this.addGeometry_(geometry, feature);
  }
  /**
   * @param {Feature|RenderFeature} feature Feature
   */
  removeFeature(feature) {
    let entry = this.clearFeatureEntryInPointBatch_(feature);
    entry = this.clearFeatureEntryInPolygonBatch_(feature) || entry;
    entry = this.clearFeatureEntryInLineStringBatch_(feature) || entry;
    if (entry) {
      this.removeRef_(entry.ref, getUid(entry.feature));
    }
  }
  clear() {
    this.polygonBatch.entries = {};
    this.polygonBatch.geometriesCount = 0;
    this.polygonBatch.verticesCount = 0;
    this.polygonBatch.ringsCount = 0;
    this.lineStringBatch.entries = {};
    this.lineStringBatch.geometriesCount = 0;
    this.lineStringBatch.verticesCount = 0;
    this.pointBatch.entries = {};
    this.pointBatch.geometriesCount = 0;
    this.globalCounter_ = 0;
    this.freeGlobalRef_ = [];
    this.refToFeature_.clear();
    this.uidToRef_.clear();
  }
  /**
   * Resolve the feature associated to a ref.
   * @param {number} ref Hit detected ref
   * @return {Feature|RenderFeature} feature
   */
  getFeatureFromRef(ref) {
    return this.refToFeature_.get(ref);
  }
  isEmpty() {
    return this.globalCounter_ === 0;
  }
  /**
   * Will return a new instance of this class that only contains the features
   * for which the provided callback returned true
   * @param {function((Feature|RenderFeature)): boolean} featureFilter Feature filter callback
   * @return {MixedGeometryBatch} Filtered geometry batch
   */
  filter(featureFilter) {
    const filtered = new _MixedGeometryBatch();
    filtered.globalCounter_ = this.globalCounter_;
    filtered.uidToRef_ = this.uidToRef_;
    filtered.refToFeature_ = this.refToFeature_;
    let empty = true;
    for (const feature of this.refToFeature_.values()) {
      if (featureFilter(feature)) {
        filtered.addFeature(feature);
        empty = false;
      }
    }
    if (empty) {
      return new _MixedGeometryBatch();
    }
    return filtered;
  }
};
function getFlatCoordinatesXY(flatCoords, stride) {
  if (stride === 2) {
    return flatCoords;
  }
  return flatCoords.filter((v, i) => i % stride < 2);
}
function getFlatCoordinatesXYM(flatCoords, stride, layout) {
  if (stride === 3 && layout === "XYM") {
    return flatCoords;
  }
  if (stride === 4) {
    return flatCoords.filter((v, i) => i % stride !== 2);
  }
  if (stride === 3) {
    return flatCoords.map((v, i) => i % stride !== 2 ? v : 0);
  }
  return new Array(flatCoords.length * 1.5).fill(0).map((v, i) => i % 3 === 2 ? 0 : flatCoords[Math.round(i / 1.5)]);
}
var MixedGeometryBatch_default = MixedGeometryBatch;

// node_modules/ol/worker/webgl.js
function create3() {
  const source = 'function t(t,n,x=2){const o=n&&n.length,i=o?n[0]*x:t.length;let f=e(t,0,i,x,!0);const l=[];if(!f||f.next===f.prev)return l;let c,y,h;if(o&&(f=function(t,n,r,x){const o=[];for(let r=0,i=n.length;r<i;r++){const f=e(t,n[r]*x,r<i-1?n[r+1]*x:t.length,x,!1);f===f.next&&(f.steiner=!0),o.push(a(f))}o.sort(u);for(let t=0;t<o.length;t++)r=s(o[t],r);return r}(t,n,f,x)),t.length>80*x){c=t[0],y=t[1];let e=c,n=y;for(let r=x;r<i;r+=x){const x=t[r],o=t[r+1];x<c&&(c=x),o<y&&(y=o),x>e&&(e=x),o>n&&(n=o)}h=Math.max(e-c,n-y),h=0!==h?32767/h:0}return r(f,l,x,c,y,h,0),l}function e(t,e,n,r,x){let o;if(x===function(t,e,n,r){let x=0;for(let o=e,i=n-r;o<n;o+=r)x+=(t[i]-t[o])*(t[o+1]+t[i+1]),i=o;return x}(t,e,n,r)>0)for(let x=e;x<n;x+=r)o=d(x/r|0,t[x],t[x+1],o);else for(let x=n-r;x>=e;x-=r)o=d(x/r|0,t[x],t[x+1],o);return o&&b(o,o.next)&&(w(o),o=o.next),o}function n(t,e){if(!t)return t;e||(e=t);let n,r=t;do{if(n=!1,r.steiner||!b(r,r.next)&&0!==v(r.prev,r,r.next))r=r.next;else{if(w(r),r=e=r.prev,r===r.next)break;n=!0}}while(n||r!==e);return e}function r(t,e,u,s,l,a,y){if(!t)return;!y&&a&&function(t,e,n,r){let x=t;do{0===x.z&&(x.z=c(x.x,x.y,e,n,r)),x.prevZ=x.prev,x.nextZ=x.next,x=x.next}while(x!==t);x.prevZ.nextZ=null,x.prevZ=null,function(t){let e,n=1;do{let r,x=t;t=null;let o=null;for(e=0;x;){e++;let i=x,f=0;for(let t=0;t<n&&(f++,i=i.nextZ,i);t++);let u=n;for(;f>0||u>0&&i;)0!==f&&(0===u||!i||x.z<=i.z)?(r=x,x=x.nextZ,f--):(r=i,i=i.nextZ,u--),o?o.nextZ=r:t=r,r.prevZ=o,o=r;x=i}o.nextZ=null,n*=2}while(e>1)}(x)}(t,s,l,a);let h=t;for(;t.prev!==t.next;){const c=t.prev,p=t.next;if(a?o(t,s,l,a):x(t))e.push(c.i,t.i,p.i),w(t),t=p.next,h=p.next;else if((t=p)===h){y?1===y?r(t=i(n(t),e),e,u,s,l,a,2):2===y&&f(t,e,u,s,l,a):r(n(t),e,u,s,l,a,1);break}}}function x(t){const e=t.prev,n=t,r=t.next;if(v(e,n,r)>=0)return!1;const x=e.x,o=n.x,i=r.x,f=e.y,u=n.y,s=r.y,l=Math.min(x,o,i),c=Math.min(f,u,s),a=Math.max(x,o,i),y=Math.max(f,u,s);let p=r.next;for(;p!==e;){if(p.x>=l&&p.x<=a&&p.y>=c&&p.y<=y&&h(x,f,o,u,i,s,p.x,p.y)&&v(p.prev,p,p.next)>=0)return!1;p=p.next}return!0}function o(t,e,n,r){const x=t.prev,o=t,i=t.next;if(v(x,o,i)>=0)return!1;const f=x.x,u=o.x,s=i.x,l=x.y,a=o.y,y=i.y,p=Math.min(f,u,s),b=Math.min(l,a,y),M=Math.max(f,u,s),m=Math.max(l,a,y),A=c(p,b,e,n,r),g=c(M,m,e,n,r);let Z=t.prevZ,d=t.nextZ;for(;Z&&Z.z>=A&&d&&d.z<=g;){if(Z.x>=p&&Z.x<=M&&Z.y>=b&&Z.y<=m&&Z!==x&&Z!==i&&h(f,l,u,a,s,y,Z.x,Z.y)&&v(Z.prev,Z,Z.next)>=0)return!1;if(Z=Z.prevZ,d.x>=p&&d.x<=M&&d.y>=b&&d.y<=m&&d!==x&&d!==i&&h(f,l,u,a,s,y,d.x,d.y)&&v(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(;Z&&Z.z>=A;){if(Z.x>=p&&Z.x<=M&&Z.y>=b&&Z.y<=m&&Z!==x&&Z!==i&&h(f,l,u,a,s,y,Z.x,Z.y)&&v(Z.prev,Z,Z.next)>=0)return!1;Z=Z.prevZ}for(;d&&d.z<=g;){if(d.x>=p&&d.x<=M&&d.y>=b&&d.y<=m&&d!==x&&d!==i&&h(f,l,u,a,s,y,d.x,d.y)&&v(d.prev,d,d.next)>=0)return!1;d=d.nextZ}return!0}function i(t,e){let r=t;do{const n=r.prev,x=r.next.next;!b(n,x)&&M(n,r,r.next,x)&&g(n,x)&&g(x,n)&&(e.push(n.i,r.i,x.i),w(r),w(r.next),r=t=x),r=r.next}while(r!==t);return n(r)}function f(t,e,x,o,i,f){let u=t;do{let t=u.next.next;for(;t!==u.prev;){if(u.i!==t.i&&p(u,t)){let s=Z(u,t);return u=n(u,u.next),s=n(s,s.next),r(u,e,x,o,i,f,0),void r(s,e,x,o,i,f,0)}t=t.next}u=u.next}while(u!==t)}function u(t,e){let n=t.x-e.x;if(0===n&&(n=t.y-e.y,0===n)){n=(t.next.y-t.y)/(t.next.x-t.x)-(e.next.y-e.y)/(e.next.x-e.x)}return n}function s(t,e){const r=function(t,e){let n=e;const r=t.x,x=t.y;let o,i=-1/0;if(b(t,n))return n;do{if(b(t,n.next))return n.next;if(x<=n.y&&x>=n.next.y&&n.next.y!==n.y){const t=n.x+(x-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(t<=r&&t>i&&(i=t,o=n.x<n.next.x?n:n.next,t===r))return o}n=n.next}while(n!==e);if(!o)return null;const f=o,u=o.x,s=o.y;let c=1/0;n=o;do{if(r>=n.x&&n.x>=u&&r!==n.x&&y(x<s?r:i,x,u,s,x<s?i:r,x,n.x,n.y)){const e=Math.abs(x-n.y)/(r-n.x);g(n,t)&&(e<c||e===c&&(n.x>o.x||n.x===o.x&&l(o,n)))&&(o=n,c=e)}n=n.next}while(n!==f);return o}(t,e);if(!r)return e;const x=Z(r,t);return n(x,x.next),n(r,r.next)}function l(t,e){return v(t.prev,t,e.prev)<0&&v(e.next,t,t.next)<0}function c(t,e,n,r,x){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-n)*x|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-r)*x|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function a(t){let e=t,n=t;do{(e.x<n.x||e.x===n.x&&e.y<n.y)&&(n=e),e=e.next}while(e!==t);return n}function y(t,e,n,r,x,o,i,f){return(x-i)*(e-f)>=(t-i)*(o-f)&&(t-i)*(r-f)>=(n-i)*(e-f)&&(n-i)*(o-f)>=(x-i)*(r-f)}function h(t,e,n,r,x,o,i,f){return!(t===i&&e===f)&&y(t,e,n,r,x,o,i,f)}function p(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&M(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(g(t,e)&&g(e,t)&&function(t,e){let n=t,r=!1;const x=(t.x+e.x)/2,o=(t.y+e.y)/2;do{n.y>o!=n.next.y>o&&n.next.y!==n.y&&x<(n.next.x-n.x)*(o-n.y)/(n.next.y-n.y)+n.x&&(r=!r),n=n.next}while(n!==t);return r}(t,e)&&(v(t.prev,t,e.prev)||v(t,e.prev,e))||b(t,e)&&v(t.prev,t,t.next)>0&&v(e.prev,e,e.next)>0)}function v(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function b(t,e){return t.x===e.x&&t.y===e.y}function M(t,e,n,r){const x=A(v(t,e,n)),o=A(v(t,e,r)),i=A(v(n,r,t)),f=A(v(n,r,e));return x!==o&&i!==f||(!(0!==x||!m(t,n,e))||(!(0!==o||!m(t,r,e))||(!(0!==i||!m(n,t,r))||!(0!==f||!m(n,e,r)))))}function m(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function A(t){return t>0?1:t<0?-1:0}function g(t,e){return v(t.prev,t,t.next)<0?v(t,e,t.next)>=0&&v(t,t.prev,e)>=0:v(t,e,t.prev)<0||v(t,t.next,e)<0}function Z(t,e){const n=F(t.i,t.x,t.y),r=F(e.i,e.x,e.y),x=t.next,o=e.prev;return t.next=e,e.prev=t,n.next=x,x.prev=n,r.next=n,n.prev=r,o.next=r,r.prev=o,r}function d(t,e,n,r){const x=F(t,e,n);return r?(x.next=r.next,x.prev=r,r.next.prev=x,r.next=x):(x.prev=x,x.next=x),x}function w(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function F(t,e,n){return{i:t,x:e,y:n,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function E(t,e){const n=e[0],r=e[1];return e[0]=t[0]*n+t[2]*r+t[4],e[1]=t[1]*n+t[3]*r+t[5],e}function I(t,e){const n=(r=e)[0]*r[3]-r[1]*r[2];var r;!function(t,e){if(!t)throw new Error(e)}(0!==n,"Transformation matrix cannot be inverted");const x=e[0],o=e[1],i=e[2],f=e[3],u=e[4],s=e[5];return t[0]=f/n,t[1]=-o/n,t[2]=-i/n,t[3]=x/n,t[4]=(i*s-f*u)/n,t[5]=-(x*s-o*u)/n,t}new Array(6);const z=[],B={vertexAttributesPosition:0,instanceAttributesPosition:0,indicesPosition:0};function P(t,e,n,r,x){const o=t[e++],i=t[e++],f=z;f.length=r;for(let n=0;n<f.length;n++)f[n]=t[e+n];let u=x?x.instanceAttributesPosition:0;return n[u++]=o,n[u++]=i,f.length&&(n.set(f,u),u+=f.length),B.instanceAttributesPosition=u,B}function N(t,e,n,r,x,o,i,f,u,s){const l=[t[e],t[e+1]],c=[t[n],t[n+1]],a=t[e+2],y=t[n+2],h=E(f,[...l]),p=E(f,[...c]);function v(t,e,n){const r=Math.sqrt((e[0]-t[0])*(e[0]-t[0])+(e[1]-t[1])*(e[1]-t[1])),x=[(e[0]-t[0])/r,(e[1]-t[1])/r],o=[-x[1],x[0]],i=Math.sqrt((n[0]-t[0])*(n[0]-t[0])+(n[1]-t[1])*(n[1]-t[1])),f=[(n[0]-t[0])/i,(n[1]-t[1])/i];let u=0===r||0===i?0:Math.acos((s=f[0]*x[0]+f[1]*x[1],l=-1,c=1,Math.min(Math.max(s,l),c)));var s,l,c;u=Math.max(u,1e-5);return f[0]*o[0]+f[1]*o[1]>0?u:2*Math.PI-u}let b=-1,M=-1,m=s;const A=null!==x;if(null!==r){b=v(h,p,E(f,[...[t[r],t[r+1]]])),Math.cos(b)<=.985&&(m+=Math.tan((b-Math.PI)/2))}if(A){M=v(p,h,E(f,[...[t[x],t[x+1]]])),Math.cos(M)<=.985&&(m+=Math.tan((Math.PI-M)/2))}const g=Math.pow(2,24),Z=u%g,d=Math.floor(u/g)*g;return o.push(l[0],l[1],a,c[0],c[1],y,b,M,Z,d,s),o.push(...i),{length:u+Math.sqrt((p[0]-h[0])*(p[0]-h[0])+(p[1]-h[1])*(p[1]-h[1])),angle:m}}function R(e,n,r,x,o){const i=2+o;let f=n;const u=e.slice(f,f+o);f+=o;const s=e[f++];let l=0;const c=new Array(s-1);for(let t=0;t<s;t++)l+=e[f++],t<s-1&&(c[t]=l);const a=e.slice(f,f+2*l),y=t(a,c,2);for(let t=0;t<y.length;t++)x.push(y[t]+r.length/i);for(let t=0;t<a.length;t+=2)r.push(a[t],a[t+1],...u);return f+2*l}const S="GENERATE_POLYGON_BUFFERS",T="GENERATE_POINT_BUFFERS",_="GENERATE_LINE_STRING_BUFFERS",O=self;O.onmessage=t=>{const e=t.data;switch(e.type){case T:{const t=2,n=2,r=e.customAttributesSize,x=n+r,o=new Float32Array(e.renderInstructions),i=o.length/x*(t+r),f=Uint32Array.from([0,1,3,1,2,3]),u=Float32Array.from([-1,-1,1,-1,1,1,-1,1]),s=new Float32Array(i);let l;for(let t=0;t<o.length;t+=x)l=P(o,t,s,r,l);const c=Object.assign({indicesBuffer:f.buffer,vertexAttributesBuffer:u.buffer,instanceAttributesBuffer:s.buffer,renderInstructions:o.buffer},e);O.postMessage(c,[u.buffer,s.buffer,f.buffer,o.buffer]);break}case _:{const t=[],n=e.customAttributesSize,r=3,x=new Float32Array(e.renderInstructions);let o=0;const i=[1,0,0,1,0,0];let f,u;for(I(i,e.renderInstructionsTransform);o<x.length;){u=Array.from(x.slice(o,o+n)),o+=n,f=x[o++];const e=o,s=o+(f-1)*r,l=x[e]===x[s]&&x[e+1]===x[s+1];let c=0,a=0;for(let n=0;n<f-1;n++){let y=null;n>0?y=o+(n-1)*r:l&&(y=s-r);let h=null;n<f-2?h=o+(n+2)*r:l&&(h=e+r);const p=N(x,o+n*r,o+(n+1)*r,y,h,t,u,i,c,a);c=p.length,a=p.angle}o+=f*r}const s=Uint32Array.from([0,1,3,1,2,3]),l=Float32Array.from([-1,-1,1,-1,1,1,-1,1]),c=Float32Array.from(t),a=Object.assign({indicesBuffer:s.buffer,vertexAttributesBuffer:l.buffer,instanceAttributesBuffer:c.buffer,renderInstructions:x.buffer},e);O.postMessage(a,[l.buffer,c.buffer,s.buffer,x.buffer]);break}case S:{const t=[],n=[],r=e.customAttributesSize,x=new Float32Array(e.renderInstructions);let o=0;for(;o<x.length;)o=R(x,o,t,n,r);const i=Uint32Array.from(n),f=Float32Array.from(t),u=Float32Array.from([]),s=Object.assign({indicesBuffer:i.buffer,vertexAttributesBuffer:f.buffer,instanceAttributesBuffer:u.buffer,renderInstructions:x.buffer},e);O.postMessage(s,[f.buffer,u.buffer,i.buffer,x.buffer]);break}}};';
  return new Worker(typeof Blob === "undefined" ? "data:application/javascript;base64," + Buffer.from(source, "binary").toString("base64") : URL.createObjectURL(new Blob([source], { type: "application/javascript" })));
}

// node_modules/ol/render/webgl/constants.js
var WebGLWorkerMessageType = {
  GENERATE_POLYGON_BUFFERS: "GENERATE_POLYGON_BUFFERS",
  GENERATE_POINT_BUFFERS: "GENERATE_POINT_BUFFERS",
  GENERATE_LINE_STRING_BUFFERS: "GENERATE_LINE_STRING_BUFFERS"
};

// node_modules/ol/render/webgl/encodeUtil.js
function colorEncodeIdAndPack(id, array) {
  array = array || [];
  const radix = 256;
  const divide = radix - 1;
  const r = Math.floor(id / radix / radix / radix) / divide;
  const g = Math.floor(id / radix / radix) % radix / divide;
  const b = Math.floor(id / radix) % radix / divide;
  const a = id % radix / divide;
  array[0] = r * 256 * 255 + g * 255;
  array[1] = b * 256 * 255 + a * 255;
  return array;
}
function colorDecodeId(color) {
  let id = 0;
  const radix = 256;
  const mult = radix - 1;
  id += Math.round(color[0] * radix * radix * radix * mult);
  id += Math.round(color[1] * radix * radix * mult);
  id += Math.round(color[2] * radix * mult);
  id += Math.round(color[3] * mult);
  return id;
}

// node_modules/ol/render/webgl/renderinstructions.js
function pushCustomAttributesInRenderInstructions(renderInstructions, customAttributes, batchEntry, currentIndex) {
  let shift = 0;
  for (const key in customAttributes) {
    const attr = customAttributes[key];
    const value = attr.callback.call(batchEntry, batchEntry.feature);
    let first = (value == null ? void 0 : value[0]) ?? value;
    if (first === UNDEFINED_PROP_VALUE) {
      console.warn('The "has" operator might return false positives.');
    }
    if (first === void 0) {
      first = UNDEFINED_PROP_VALUE;
    } else if (first === null) {
      first = 0;
    }
    renderInstructions[currentIndex + shift++] = first;
    if (!attr.size || attr.size === 1) {
      continue;
    }
    renderInstructions[currentIndex + shift++] = value[1];
    if (attr.size < 3) {
      continue;
    }
    renderInstructions[currentIndex + shift++] = value[2];
    if (attr.size < 4) {
      continue;
    }
    renderInstructions[currentIndex + shift++] = value[3];
  }
  return shift;
}
function getCustomAttributesSize(customAttributes) {
  return Object.keys(customAttributes).reduce(
    (prev, curr) => prev + (customAttributes[curr].size || 1),
    0
  );
}
function generatePointRenderInstructions(batch, renderInstructions, customAttributes, transform) {
  const totalInstructionsCount = (2 + getCustomAttributesSize(customAttributes)) * batch.geometriesCount;
  if (!renderInstructions || renderInstructions.length !== totalInstructionsCount) {
    renderInstructions = new Float32Array(totalInstructionsCount);
  }
  const tmpCoords = [];
  let renderIndex = 0;
  for (const featureUid in batch.entries) {
    const batchEntry = batch.entries[featureUid];
    for (let i = 0, ii = batchEntry.flatCoordss.length; i < ii; i++) {
      tmpCoords[0] = batchEntry.flatCoordss[i][0];
      tmpCoords[1] = batchEntry.flatCoordss[i][1];
      apply(transform, tmpCoords);
      renderInstructions[renderIndex++] = tmpCoords[0];
      renderInstructions[renderIndex++] = tmpCoords[1];
      renderIndex += pushCustomAttributesInRenderInstructions(
        renderInstructions,
        customAttributes,
        batchEntry,
        renderIndex
      );
    }
  }
  return renderInstructions;
}
function generateLineStringRenderInstructions(batch, renderInstructions, customAttributes, transform) {
  const totalInstructionsCount = 3 * batch.verticesCount + (1 + getCustomAttributesSize(customAttributes)) * batch.geometriesCount;
  if (!renderInstructions || renderInstructions.length !== totalInstructionsCount) {
    renderInstructions = new Float32Array(totalInstructionsCount);
  }
  const flatCoords = [];
  let renderIndex = 0;
  for (const featureUid in batch.entries) {
    const batchEntry = batch.entries[featureUid];
    for (let i = 0, ii = batchEntry.flatCoordss.length; i < ii; i++) {
      flatCoords.length = batchEntry.flatCoordss[i].length;
      transform2D(
        batchEntry.flatCoordss[i],
        0,
        flatCoords.length,
        3,
        transform,
        flatCoords,
        3
      );
      renderIndex += pushCustomAttributesInRenderInstructions(
        renderInstructions,
        customAttributes,
        batchEntry,
        renderIndex
      );
      renderInstructions[renderIndex++] = flatCoords.length / 3;
      for (let j = 0, jj = flatCoords.length; j < jj; j += 3) {
        renderInstructions[renderIndex++] = flatCoords[j];
        renderInstructions[renderIndex++] = flatCoords[j + 1];
        renderInstructions[renderIndex++] = flatCoords[j + 2];
      }
    }
  }
  return renderInstructions;
}
function generatePolygonRenderInstructions(batch, renderInstructions, customAttributes, transform) {
  const totalInstructionsCount = 2 * batch.verticesCount + (1 + getCustomAttributesSize(customAttributes)) * batch.geometriesCount + batch.ringsCount;
  if (!renderInstructions || renderInstructions.length !== totalInstructionsCount) {
    renderInstructions = new Float32Array(totalInstructionsCount);
  }
  const flatCoords = [];
  let renderIndex = 0;
  for (const featureUid in batch.entries) {
    const batchEntry = batch.entries[featureUid];
    for (let i = 0, ii = batchEntry.flatCoordss.length; i < ii; i++) {
      flatCoords.length = batchEntry.flatCoordss[i].length;
      transform2D(
        batchEntry.flatCoordss[i],
        0,
        flatCoords.length,
        2,
        transform,
        flatCoords
      );
      renderIndex += pushCustomAttributesInRenderInstructions(
        renderInstructions,
        customAttributes,
        batchEntry,
        renderIndex
      );
      renderInstructions[renderIndex++] = batchEntry.ringsVerticesCounts[i].length;
      for (let j = 0, jj = batchEntry.ringsVerticesCounts[i].length; j < jj; j++) {
        renderInstructions[renderIndex++] = batchEntry.ringsVerticesCounts[i][j];
      }
      for (let j = 0, jj = flatCoords.length; j < jj; j += 2) {
        renderInstructions[renderIndex++] = flatCoords[j];
        renderInstructions[renderIndex++] = flatCoords[j + 1];
      }
    }
  }
  return renderInstructions;
}

// node_modules/ol/render/webgl/style.js
function computeHash(input) {
  const hash = JSON.stringify(input).split("").reduce((prev, curr) => (prev << 5) - prev + curr.charCodeAt(0), 0);
  return (hash >>> 0).toString();
}
function parseCommonSymbolProperties(style, builder, vertContext, prefix) {
  if (`${prefix}radius` in style && prefix !== "icon-") {
    let radius = expressionToGlsl(
      vertContext,
      style[`${prefix}radius`],
      NumberType
    );
    if (`${prefix}radius2` in style) {
      const radius2 = expressionToGlsl(
        vertContext,
        style[`${prefix}radius2`],
        NumberType
      );
      radius = `max(${radius}, ${radius2})`;
    }
    if (`${prefix}stroke-width` in style) {
      radius = `(${radius} + ${expressionToGlsl(
        vertContext,
        style[`${prefix}stroke-width`],
        NumberType
      )} * 0.5)`;
    }
    builder.setSymbolSizeExpression(`vec2(${radius} * 2. + 0.5)`);
  }
  if (`${prefix}scale` in style) {
    const scale2 = expressionToGlsl(
      vertContext,
      style[`${prefix}scale`],
      SizeType
    );
    builder.setSymbolSizeExpression(
      `${builder.getSymbolSizeExpression()} * ${scale2}`
    );
  }
  if (`${prefix}displacement` in style) {
    builder.setSymbolOffsetExpression(
      expressionToGlsl(
        vertContext,
        style[`${prefix}displacement`],
        NumberArrayType
      )
    );
  }
  if (`${prefix}rotation` in style) {
    builder.setSymbolRotationExpression(
      expressionToGlsl(vertContext, style[`${prefix}rotation`], NumberType)
    );
  }
  if (`${prefix}rotate-with-view` in style) {
    builder.setSymbolRotateWithView(!!style[`${prefix}rotate-with-view`]);
  }
}
function getColorFromDistanceField(distanceField, fillColor, strokeColor, strokeWidth, opacity) {
  let color = "vec4(0.)";
  if (fillColor !== null) {
    color = fillColor;
  }
  if (strokeColor !== null && strokeWidth !== null) {
    const strokeFillRatio = `smoothstep(-${strokeWidth} + 0.63, -${strokeWidth} - 0.58, ${distanceField})`;
    color = `mix(${strokeColor}, ${color}, ${strokeFillRatio})`;
  }
  const shapeOpacity = `(1.0 - smoothstep(-0.63, 0.58, ${distanceField}))`;
  let result = `${color} * vec4(1.0, 1.0, 1.0, ${shapeOpacity})`;
  if (opacity !== null) {
    result = `${result} * vec4(1.0, 1.0, 1.0, ${opacity})`;
  }
  return result;
}
function parseImageProperties(style, builder, uniforms, prefix, textureId) {
  const image = new Image();
  image.crossOrigin = style[`${prefix}cross-origin`] === void 0 ? "anonymous" : style[`${prefix}cross-origin`];
  assert(
    typeof style[`${prefix}src`] === "string",
    `WebGL layers do not support expressions for the ${prefix}src style property`
  );
  image.src = /** @type {string} */
  style[`${prefix}src`];
  uniforms[`u_texture${textureId}_size`] = () => {
    return image.complete ? [image.width, image.height] : [0, 0];
  };
  builder.addUniform(`u_texture${textureId}_size`, "vec2");
  const size = `u_texture${textureId}_size`;
  uniforms[`u_texture${textureId}`] = image;
  builder.addUniform(`u_texture${textureId}`, "sampler2D");
  return size;
}
function parseImageOffsetProperties(style, prefix, context, imageSize, sampleSize) {
  let offsetExpression = expressionToGlsl(
    context,
    style[`${prefix}offset`],
    SizeType
  );
  if (`${prefix}offset-origin` in style) {
    switch (style[`${prefix}offset-origin`]) {
      case "top-right":
        offsetExpression = `vec2(${imageSize}.x, 0.) + ${sampleSize} * vec2(-1., 0.) + ${offsetExpression} * vec2(-1., 1.)`;
        break;
      case "bottom-left":
        offsetExpression = `vec2(0., ${imageSize}.y) + ${sampleSize} * vec2(0., -1.) + ${offsetExpression} * vec2(1., -1.)`;
        break;
      case "bottom-right":
        offsetExpression = `${imageSize} - ${sampleSize} - ${offsetExpression}`;
        break;
      default:
    }
  }
  return offsetExpression;
}
function parseCircleProperties(style, builder, uniforms, context) {
  context.functions["circleDistanceField"] = `float circleDistanceField(vec2 point, float radius) {
  return length(point) - radius;
}`;
  parseCommonSymbolProperties(style, builder, context, "circle-");
  let opacity = null;
  if ("circle-opacity" in style) {
    opacity = expressionToGlsl(context, style["circle-opacity"], NumberType);
  }
  let currentPoint = "coordsPx";
  if ("circle-scale" in style) {
    const scale2 = expressionToGlsl(context, style["circle-scale"], SizeType);
    currentPoint = `coordsPx / ${scale2}`;
  }
  let fillColor = null;
  if ("circle-fill-color" in style) {
    fillColor = expressionToGlsl(
      context,
      style["circle-fill-color"],
      ColorType
    );
  }
  let strokeColor = null;
  if ("circle-stroke-color" in style) {
    strokeColor = expressionToGlsl(
      context,
      style["circle-stroke-color"],
      ColorType
    );
  }
  let radius = expressionToGlsl(context, style["circle-radius"], NumberType);
  let strokeWidth = null;
  if ("circle-stroke-width" in style) {
    strokeWidth = expressionToGlsl(
      context,
      style["circle-stroke-width"],
      NumberType
    );
    radius = `(${radius} + ${strokeWidth} * 0.5)`;
  }
  const distanceField = `circleDistanceField(${currentPoint}, ${radius})`;
  const colorExpression = getColorFromDistanceField(
    distanceField,
    fillColor,
    strokeColor,
    strokeWidth,
    opacity
  );
  builder.setSymbolColorExpression(colorExpression);
}
function parseShapeProperties(style, builder, uniforms, context) {
  context.functions["round"] = `float round(float v) {
  return sign(v) * floor(abs(v) + 0.5);
}`;
  context.functions["starDistanceField"] = `float starDistanceField(vec2 point, float numPoints, float radius, float radius2, float angle) {
  float startAngle = -PI * 0.5 + angle; // tip starts upwards and rotates clockwise with angle
  float c = cos(startAngle);
  float s = sin(startAngle);
  vec2 pointRotated = vec2(c * point.x - s * point.y, s * point.x + c * point.y);
  float alpha = TWO_PI / numPoints; // the angle of one sector
  float beta = atan(pointRotated.y, pointRotated.x);
  float gamma = round(beta / alpha) * alpha; // angle in sector
  c = cos(-gamma);
  s = sin(-gamma);
  vec2 inSector = vec2(c * pointRotated.x - s * pointRotated.y, abs(s * pointRotated.x + c * pointRotated.y));
  vec2 tipToPoint = inSector + vec2(-radius, 0.);
  vec2 edgeNormal = vec2(radius2 * sin(alpha * 0.5), -radius2 * cos(alpha * 0.5) + radius);
  return dot(normalize(edgeNormal), tipToPoint);
}`;
  context.functions["regularDistanceField"] = `float regularDistanceField(vec2 point, float numPoints, float radius, float angle) {
  float startAngle = -PI * 0.5 + angle; // tip starts upwards and rotates clockwise with angle
  float c = cos(startAngle);
  float s = sin(startAngle);
  vec2 pointRotated = vec2(c * point.x - s * point.y, s * point.x + c * point.y);
  float alpha = TWO_PI / numPoints; // the angle of one sector
  float radiusIn = radius * cos(PI / numPoints);
  float beta = atan(pointRotated.y, pointRotated.x);
  float gamma = round((beta - alpha * 0.5) / alpha) * alpha + alpha * 0.5; // angle in sector from mid
  c = cos(-gamma);
  s = sin(-gamma);
  vec2 inSector = vec2(c * pointRotated.x - s * pointRotated.y, abs(s * pointRotated.x + c * pointRotated.y));
  return inSector.x - radiusIn;
}`;
  parseCommonSymbolProperties(style, builder, context, "shape-");
  let opacity = null;
  if ("shape-opacity" in style) {
    opacity = expressionToGlsl(context, style["shape-opacity"], NumberType);
  }
  let currentPoint = "coordsPx";
  if ("shape-scale" in style) {
    const scale2 = expressionToGlsl(context, style["shape-scale"], SizeType);
    currentPoint = `coordsPx / ${scale2}`;
  }
  let fillColor = null;
  if ("shape-fill-color" in style) {
    fillColor = expressionToGlsl(context, style["shape-fill-color"], ColorType);
  }
  let strokeColor = null;
  if ("shape-stroke-color" in style) {
    strokeColor = expressionToGlsl(
      context,
      style["shape-stroke-color"],
      ColorType
    );
  }
  let strokeWidth = null;
  if ("shape-stroke-width" in style) {
    strokeWidth = expressionToGlsl(
      context,
      style["shape-stroke-width"],
      NumberType
    );
  }
  const numPoints = expressionToGlsl(
    context,
    style["shape-points"],
    NumberType
  );
  let angle = "0.";
  if ("shape-angle" in style) {
    angle = expressionToGlsl(context, style["shape-angle"], NumberType);
  }
  let shapeField;
  let radius = expressionToGlsl(context, style["shape-radius"], NumberType);
  if (strokeWidth !== null) {
    radius = `${radius} + ${strokeWidth} * 0.5`;
  }
  if ("shape-radius2" in style) {
    let radius2 = expressionToGlsl(context, style["shape-radius2"], NumberType);
    if (strokeWidth !== null) {
      radius2 = `${radius2} + ${strokeWidth} * 0.5`;
    }
    shapeField = `starDistanceField(${currentPoint}, ${numPoints}, ${radius}, ${radius2}, ${angle})`;
  } else {
    shapeField = `regularDistanceField(${currentPoint}, ${numPoints}, ${radius}, ${angle})`;
  }
  const colorExpression = getColorFromDistanceField(
    shapeField,
    fillColor,
    strokeColor,
    strokeWidth,
    opacity
  );
  builder.setSymbolColorExpression(colorExpression);
}
function parseIconProperties(style, builder, uniforms, context) {
  let color = "vec4(1.0)";
  if ("icon-color" in style) {
    color = expressionToGlsl(context, style["icon-color"], ColorType);
  }
  if ("icon-opacity" in style) {
    color = `${color} * vec4(1.0, 1.0, 1.0, ${expressionToGlsl(
      context,
      style["icon-opacity"],
      NumberType
    )})`;
  }
  const textureId = computeHash(style["icon-src"]);
  const sizeExpression = parseImageProperties(
    style,
    builder,
    uniforms,
    "icon-",
    textureId
  );
  builder.setSymbolColorExpression(
    `${color} * texture2D(u_texture${textureId}, v_texCoord)`
  ).setSymbolSizeExpression(sizeExpression);
  if ("icon-width" in style && "icon-height" in style) {
    builder.setSymbolSizeExpression(
      `vec2(${expressionToGlsl(
        context,
        style["icon-width"],
        NumberType
      )}, ${expressionToGlsl(context, style["icon-height"], NumberType)})`
    );
  }
  if ("icon-offset" in style && "icon-size" in style) {
    const sampleSize = expressionToGlsl(
      context,
      style["icon-size"],
      NumberArrayType
    );
    const fullsize = builder.getSymbolSizeExpression();
    builder.setSymbolSizeExpression(sampleSize);
    const offset = parseImageOffsetProperties(
      style,
      "icon-",
      context,
      "v_quadSizePx",
      sampleSize
    );
    builder.setTextureCoordinateExpression(
      `(vec4((${offset}).xyxy) + vec4(0., 0., ${sampleSize})) / (${fullsize}).xyxy`
    );
  }
  parseCommonSymbolProperties(style, builder, context, "icon-");
  if ("icon-anchor" in style) {
    const anchor = expressionToGlsl(
      context,
      style["icon-anchor"],
      NumberArrayType
    );
    let scale2 = `1.0`;
    if (`icon-scale` in style) {
      scale2 = expressionToGlsl(context, style[`icon-scale`], SizeType);
    }
    let shiftPx;
    if (style["icon-anchor-x-units"] === "pixels" && style["icon-anchor-y-units"] === "pixels") {
      shiftPx = `${anchor} * ${scale2}`;
    } else if (style["icon-anchor-x-units"] === "pixels") {
      shiftPx = `${anchor} * vec2(vec2(${scale2}).x, v_quadSizePx.y)`;
    } else if (style["icon-anchor-y-units"] === "pixels") {
      shiftPx = `${anchor} * vec2(v_quadSizePx.x, vec2(${scale2}).x)`;
    } else {
      shiftPx = `${anchor} * v_quadSizePx`;
    }
    let offsetPx = `v_quadSizePx * vec2(0.5, -0.5) + ${shiftPx} * vec2(-1., 1.)`;
    if ("icon-anchor-origin" in style) {
      switch (style["icon-anchor-origin"]) {
        case "top-right":
          offsetPx = `v_quadSizePx * -0.5 + ${shiftPx}`;
          break;
        case "bottom-left":
          offsetPx = `v_quadSizePx * 0.5 - ${shiftPx}`;
          break;
        case "bottom-right":
          offsetPx = `v_quadSizePx * vec2(-0.5, 0.5) + ${shiftPx} * vec2(1., -1.)`;
          break;
        default:
      }
    }
    builder.setSymbolOffsetExpression(
      `${builder.getSymbolOffsetExpression()} + ${offsetPx}`
    );
  }
}
function parseStrokeProperties(style, builder, uniforms, context) {
  if ("stroke-color" in style) {
    builder.setStrokeColorExpression(
      expressionToGlsl(context, style["stroke-color"], ColorType)
    );
  }
  if ("stroke-pattern-src" in style) {
    const textureId = computeHash(style["stroke-pattern-src"]);
    const sizeExpression = parseImageProperties(
      style,
      builder,
      uniforms,
      "stroke-pattern-",
      textureId
    );
    let sampleSizeExpression = sizeExpression;
    let offsetExpression = "vec2(0.)";
    if ("stroke-pattern-offset" in style && "stroke-pattern-size" in style) {
      sampleSizeExpression = expressionToGlsl(
        context,
        style[`stroke-pattern-size`],
        NumberArrayType
      );
      offsetExpression = parseImageOffsetProperties(
        style,
        "stroke-pattern-",
        context,
        sizeExpression,
        sampleSizeExpression
      );
    }
    let spacingExpression = "0.";
    if ("stroke-pattern-spacing" in style) {
      spacingExpression = expressionToGlsl(
        context,
        style["stroke-pattern-spacing"],
        NumberType
      );
    }
    let startOffsetExpression = "0.";
    if ("stroke-pattern-start-offset" in style) {
      startOffsetExpression = expressionToGlsl(
        context,
        style["stroke-pattern-start-offset"],
        NumberType
      );
    }
    context.functions["sampleStrokePattern"] = `vec4 sampleStrokePattern(sampler2D texture, vec2 textureSize, vec2 textureOffset, vec2 sampleSize, float spacingPx, float startOffsetPx, float currentLengthPx, float currentRadiusRatio, float lineWidth) {
  float currentLengthScaled = (currentLengthPx - startOffsetPx) * sampleSize.y / lineWidth;
  float spacingScaled = spacingPx * sampleSize.y / lineWidth;
  float uCoordPx = mod(currentLengthScaled, (sampleSize.x + spacingScaled));
  float isInsideOfPattern = step(uCoordPx, sampleSize.x);
  float vCoordPx = (-currentRadiusRatio * 0.5 + 0.5) * sampleSize.y;
  // make sure that we're not sampling too close to the borders to avoid interpolation with outside pixels
  uCoordPx = clamp(uCoordPx, 0.5, sampleSize.x - 0.5);
  vCoordPx = clamp(vCoordPx, 0.5, sampleSize.y - 0.5);
  vec2 texCoord = (vec2(uCoordPx, vCoordPx) + textureOffset) / textureSize;
  return texture2D(texture, texCoord) * vec4(1.0, 1.0, 1.0, isInsideOfPattern);
}`;
    const textureName = `u_texture${textureId}`;
    let tintExpression = "1.";
    if ("stroke-color" in style) {
      tintExpression = builder.getStrokeColorExpression();
    }
    builder.setStrokeColorExpression(
      `${tintExpression} * sampleStrokePattern(${textureName}, ${sizeExpression}, ${offsetExpression}, ${sampleSizeExpression}, ${spacingExpression}, ${startOffsetExpression}, currentLengthPx, currentRadiusRatio, v_width)`
    );
    context.functions["computeStrokePatternLength"] = `float computeStrokePatternLength(vec2 sampleSize, float spacingPx, float lineWidth) {
  float patternLengthPx = sampleSize.x / sampleSize.y * lineWidth;
  return patternLengthPx + spacingPx;
}`;
    builder.setStrokePatternLengthExpression(
      `computeStrokePatternLength(${sampleSizeExpression}, ${spacingExpression}, v_width)`
    );
  }
  if ("stroke-width" in style) {
    builder.setStrokeWidthExpression(
      expressionToGlsl(context, style["stroke-width"], NumberType)
    );
  }
  if ("stroke-offset" in style) {
    builder.setStrokeOffsetExpression(
      expressionToGlsl(context, style["stroke-offset"], NumberType)
    );
  }
  if ("stroke-line-cap" in style) {
    builder.setStrokeCapExpression(
      expressionToGlsl(context, style["stroke-line-cap"], StringType)
    );
  }
  if ("stroke-line-join" in style) {
    builder.setStrokeJoinExpression(
      expressionToGlsl(context, style["stroke-line-join"], StringType)
    );
  }
  if ("stroke-miter-limit" in style) {
    builder.setStrokeMiterLimitExpression(
      expressionToGlsl(context, style["stroke-miter-limit"], NumberType)
    );
  }
  if ("stroke-line-dash" in style) {
    context.functions["getSingleDashDistance"] = `float getSingleDashDistance(float distance, float radius, float dashOffset, float dashLength, float dashLengthTotal, float capType, float lineWidth) {
  float localDistance = mod(distance, dashLengthTotal);
  float distanceSegment = abs(localDistance - dashOffset - dashLength * 0.5) - dashLength * 0.5;
  distanceSegment = min(distanceSegment, dashLengthTotal - localDistance);
  if (capType == ${stringToGlsl("square")}) {
    distanceSegment -= lineWidth * 0.5;
  } else if (capType == ${stringToGlsl("round")}) {
    distanceSegment = min(distanceSegment, sqrt(distanceSegment * distanceSegment + radius * radius) - lineWidth * 0.5);
  }
  return distanceSegment;
}`;
    let dashPattern = style["stroke-line-dash"].map(
      (v) => expressionToGlsl(context, v, NumberType)
    );
    if (dashPattern.length % 2 === 1) {
      dashPattern = [...dashPattern, ...dashPattern];
    }
    let offsetExpression = "0.";
    if ("stroke-line-dash-offset" in style) {
      offsetExpression = expressionToGlsl(
        context,
        style["stroke-line-dash-offset"],
        NumberType
      );
    }
    const uniqueDashKey = computeHash(style["stroke-line-dash"]);
    const dashFunctionName = `dashDistanceField_${uniqueDashKey}`;
    const dashLengthsParamsDef = dashPattern.map((v, i) => `float dashLength${i}`).join(", ");
    const totalLengthDef = dashPattern.map((v, i) => `dashLength${i}`).join(" + ");
    let currentDashOffset = "0.";
    let distanceExpression = `getSingleDashDistance(distance, radius, ${currentDashOffset}, dashLength0, totalDashLength, capType, lineWidth)`;
    for (let i = 2; i < dashPattern.length; i += 2) {
      currentDashOffset = `${currentDashOffset} + dashLength${i - 2} + dashLength${i - 1}`;
      distanceExpression = `min(${distanceExpression}, getSingleDashDistance(distance, radius, ${currentDashOffset}, dashLength${i}, totalDashLength, capType, lineWidth))`;
    }
    context.functions[dashFunctionName] = `float ${dashFunctionName}(float distance, float radius, float capType, float lineWidth, ${dashLengthsParamsDef}) {
  float totalDashLength = ${totalLengthDef};
  return ${distanceExpression};
}`;
    const dashLengthsCalls = dashPattern.map((v, i) => `${v}`).join(", ");
    builder.setStrokeDistanceFieldExpression(
      `${dashFunctionName}(currentLengthPx + ${offsetExpression}, currentRadiusPx, capType, v_width, ${dashLengthsCalls})`
    );
    let patternLength = dashPattern.join(" + ");
    if (builder.getStrokePatternLengthExpression()) {
      context.functions["combinePatternLengths"] = `float combinePatternLengths(float patternLength1, float patternLength2) {
  return patternLength1 * patternLength2;
}`;
      patternLength = `combinePatternLengths(${builder.getStrokePatternLengthExpression()}, ${patternLength})`;
    }
    builder.setStrokePatternLengthExpression(patternLength);
  }
}
function parseFillProperties(style, builder, uniforms, context) {
  if ("fill-color" in style) {
    builder.setFillColorExpression(
      expressionToGlsl(context, style["fill-color"], ColorType)
    );
  }
  if ("fill-pattern-src" in style) {
    const textureId = computeHash(style["fill-pattern-src"]);
    const sizeExpression = parseImageProperties(
      style,
      builder,
      uniforms,
      "fill-pattern-",
      textureId
    );
    let sampleSizeExpression = sizeExpression;
    let offsetExpression = "vec2(0.)";
    if ("fill-pattern-offset" in style && "fill-pattern-size" in style) {
      sampleSizeExpression = expressionToGlsl(
        context,
        style[`fill-pattern-size`],
        NumberArrayType
      );
      offsetExpression = parseImageOffsetProperties(
        style,
        "fill-pattern-",
        context,
        sizeExpression,
        sampleSizeExpression
      );
    }
    context.functions["sampleFillPattern"] = `vec4 sampleFillPattern(sampler2D texture, vec2 textureSize, vec2 textureOffset, vec2 sampleSize, vec2 pxOrigin, vec2 pxPosition) {
  float scaleRatio = pow(2., mod(u_zoom + 0.5, 1.) - 0.5);
  vec2 pxRelativePos = pxPosition - pxOrigin;
  // rotate the relative position from origin by the current view rotation
  pxRelativePos = vec2(pxRelativePos.x * cos(u_rotation) - pxRelativePos.y * sin(u_rotation), pxRelativePos.x * sin(u_rotation) + pxRelativePos.y * cos(u_rotation));
  // sample position is computed according to the sample offset & size
  vec2 samplePos = mod(pxRelativePos / scaleRatio, sampleSize);
  // also make sure that we're not sampling too close to the borders to avoid interpolation with outside pixels
  samplePos = clamp(samplePos, vec2(0.5), sampleSize - vec2(0.5));
  samplePos.y = sampleSize.y - samplePos.y; // invert y axis so that images appear upright
  return texture2D(texture, (samplePos + textureOffset) / textureSize);
}`;
    const textureName = `u_texture${textureId}`;
    let tintExpression = "1.";
    if ("fill-color" in style) {
      tintExpression = builder.getFillColorExpression();
    }
    builder.setFillColorExpression(
      `${tintExpression} * sampleFillPattern(${textureName}, ${sizeExpression}, ${offsetExpression}, ${sampleSizeExpression}, pxOrigin, pxPos)`
    );
  }
}
function parseLiteralStyle(style, variables, filter) {
  const context = newCompilationContext();
  const builder = new ShaderBuilder();
  const uniforms = {};
  if ("icon-src" in style) {
    parseIconProperties(style, builder, uniforms, context);
  } else if ("shape-points" in style) {
    parseShapeProperties(style, builder, uniforms, context);
  } else if ("circle-radius" in style) {
    parseCircleProperties(style, builder, uniforms, context);
  }
  parseStrokeProperties(style, builder, uniforms, context);
  parseFillProperties(style, builder, uniforms, context);
  if (filter) {
    const parsedFilter = expressionToGlsl(context, filter, BooleanType);
    builder.setFragmentDiscardExpression(`!${parsedFilter}`);
  }
  const attributes = {};
  function defineSpecialInput(contextPropName, glslPropName, type, callback) {
    if (!context[contextPropName]) {
      return;
    }
    const glslType = getGlslTypeFromType(type);
    const attrSize = getGlslSizeFromType(type);
    builder.addAttribute(`a_${glslPropName}`, glslType);
    attributes[glslPropName] = {
      size: attrSize,
      callback
    };
  }
  defineSpecialInput(
    "geometryType",
    GEOMETRY_TYPE_PROPERTY_NAME,
    StringType,
    (feature) => getStringNumberEquivalent(computeGeometryType(feature.getGeometry()))
  );
  defineSpecialInput(
    "featureId",
    FEATURE_ID_PROPERTY_NAME,
    StringType | NumberType,
    (feature) => {
      const id = feature.getId() ?? null;
      return typeof id === "string" ? getStringNumberEquivalent(id) : id;
    }
  );
  applyContextToBuilder(builder, context);
  return {
    builder,
    attributes: { ...attributes, ...generateAttributesFromContext(context) },
    uniforms: {
      ...uniforms,
      ...generateUniformsFromContext(context, variables)
    }
  };
}

// node_modules/ol/render/webgl/VectorStyleRenderer.js
var tmpColor = [];
var WEBGL_WORKER;
function getWebGLWorker() {
  if (!WEBGL_WORKER) {
    WEBGL_WORKER = create3();
  }
  return WEBGL_WORKER;
}
var workerMessageCounter = 0;
var Attributes2 = {
  POSITION: "a_position",
  LOCAL_POSITION: "a_localPosition",
  SEGMENT_START: "a_segmentStart",
  SEGMENT_END: "a_segmentEnd",
  MEASURE_START: "a_measureStart",
  MEASURE_END: "a_measureEnd",
  ANGLE_TANGENT_SUM: "a_angleTangentSum",
  JOIN_ANGLES: "a_joinAngles",
  DISTANCE_LOW: "a_distanceLow",
  DISTANCE_HIGH: "a_distanceHigh"
};
var VectorStyleRenderer = class {
  /**
   * @param {FlatStyleLike|StyleShaders|Array<StyleShaders>} styles Vector styles expressed as flat styles, flat style rules or style shaders
   * @param {import('../../style/flat.js').StyleVariables} variables Style variables
   * @param {import('../../webgl/Helper.js').default} helper Helper
   * @param {boolean} [enableHitDetection] Whether to enable the hit detection (needs compatible shader)
   */
  constructor(styles, variables, helper, enableHitDetection) {
    this.helper_;
    this.hitDetectionEnabled_ = !!enableHitDetection;
    this.styleShaders = convertStyleToShaders(styles, variables);
    this.customAttributes_ = {};
    this.uniforms_ = {};
    if (this.hitDetectionEnabled_) {
      this.customAttributes_["hitColor"] = {
        callback() {
          return colorEncodeIdAndPack(this.ref, tmpColor);
        },
        size: 2
      };
    }
    for (const styleShader of this.styleShaders) {
      for (const attributeName in styleShader.attributes) {
        if (attributeName in this.customAttributes_) {
          continue;
        }
        this.customAttributes_[attributeName] = styleShader.attributes[attributeName];
      }
      for (const uniformName in styleShader.uniforms) {
        if (uniformName in this.uniforms_) {
          continue;
        }
        this.uniforms_[uniformName] = styleShader.uniforms[uniformName];
      }
    }
    this.renderPasses_ = this.styleShaders.map((styleShader) => {
      const renderPass = {};
      const customAttributesDesc = Object.entries(this.customAttributes_).map(
        ([name, value]) => {
          const isUsed = name in styleShader.attributes || name === "hitColor";
          return {
            name: isUsed ? `a_${name}` : null,
            // giving a null name means this is only used for "spacing" in between attributes
            size: value.size || 1,
            type: AttributeType.FLOAT
          };
        }
      );
      if (styleShader.builder.getFillVertexShader()) {
        renderPass.fillRenderPass = {
          vertexShader: styleShader.builder.getFillVertexShader(),
          fragmentShader: styleShader.builder.getFillFragmentShader(),
          attributesDesc: [
            {
              name: Attributes2.POSITION,
              size: 2,
              type: AttributeType.FLOAT
            },
            ...customAttributesDesc
          ],
          instancedAttributesDesc: [],
          // no instanced rendering for polygons
          instancePrimitiveVertexCount: 3
        };
      }
      if (styleShader.builder.getStrokeVertexShader()) {
        renderPass.strokeRenderPass = {
          vertexShader: styleShader.builder.getStrokeVertexShader(),
          fragmentShader: styleShader.builder.getStrokeFragmentShader(),
          attributesDesc: [
            {
              name: Attributes2.LOCAL_POSITION,
              size: 2,
              type: AttributeType.FLOAT
            }
          ],
          instancedAttributesDesc: [
            {
              name: Attributes2.SEGMENT_START,
              size: 2,
              type: AttributeType.FLOAT
            },
            {
              name: Attributes2.MEASURE_START,
              size: 1,
              type: AttributeType.FLOAT
            },
            {
              name: Attributes2.SEGMENT_END,
              size: 2,
              type: AttributeType.FLOAT
            },
            {
              name: Attributes2.MEASURE_END,
              size: 1,
              type: AttributeType.FLOAT
            },
            {
              name: Attributes2.JOIN_ANGLES,
              size: 2,
              type: AttributeType.FLOAT
            },
            {
              name: Attributes2.DISTANCE_LOW,
              size: 1,
              type: AttributeType.FLOAT
            },
            {
              name: Attributes2.DISTANCE_HIGH,
              size: 1,
              type: AttributeType.FLOAT
            },
            {
              name: Attributes2.ANGLE_TANGENT_SUM,
              size: 1,
              type: AttributeType.FLOAT
            },
            ...customAttributesDesc
          ],
          instancePrimitiveVertexCount: 6
        };
      }
      if (styleShader.builder.getSymbolVertexShader()) {
        renderPass.symbolRenderPass = {
          vertexShader: styleShader.builder.getSymbolVertexShader(),
          fragmentShader: styleShader.builder.getSymbolFragmentShader(),
          attributesDesc: [
            {
              name: Attributes2.LOCAL_POSITION,
              size: 2,
              type: AttributeType.FLOAT
            }
          ],
          instancedAttributesDesc: [
            {
              name: Attributes2.POSITION,
              size: 2,
              type: AttributeType.FLOAT
            },
            ...customAttributesDesc
          ],
          instancePrimitiveVertexCount: 6
        };
      }
      return renderPass;
    });
    this.hasFill_ = this.renderPasses_.some((pass) => pass.fillRenderPass);
    this.hasStroke_ = this.renderPasses_.some((pass) => pass.strokeRenderPass);
    this.hasSymbol_ = this.renderPasses_.some((pass) => pass.symbolRenderPass);
    this.setHelper(helper);
  }
  /**
   * @param {import('./MixedGeometryBatch.js').default} geometryBatch Geometry batch
   * @param {import("../../transform.js").Transform} transform Transform to apply to coordinates
   * @return {Promise<WebGLBuffers|null>} A promise resolving to WebGL buffers; returns null if buffers are empty
   */
  async generateBuffers(geometryBatch, transform) {
    if (geometryBatch.isEmpty()) {
      return null;
    }
    const renderInstructions = this.generateRenderInstructions_(
      geometryBatch,
      transform
    );
    const [polygonBuffers, lineStringBuffers, pointBuffers] = await Promise.all(
      [
        this.generateBuffersForType_(
          renderInstructions.polygonInstructions,
          "Polygon",
          transform
        ),
        this.generateBuffersForType_(
          renderInstructions.lineStringInstructions,
          "LineString",
          transform
        ),
        this.generateBuffersForType_(
          renderInstructions.pointInstructions,
          "Point",
          transform
        )
      ]
    );
    const invertVerticesTransform = makeInverse(
      create(),
      transform
    );
    return {
      polygonBuffers,
      lineStringBuffers,
      pointBuffers,
      invertVerticesTransform
    };
  }
  /**
   * @param {import('./MixedGeometryBatch.js').default} geometryBatch Geometry batch
   * @param {import("../../transform.js").Transform} transform Transform to apply to coordinates
   * @return {RenderInstructions} Render instructions
   * @private
   */
  generateRenderInstructions_(geometryBatch, transform) {
    const polygonInstructions = this.hasFill_ ? generatePolygonRenderInstructions(
      geometryBatch.polygonBatch,
      new Float32Array(0),
      this.customAttributes_,
      transform
    ) : null;
    const lineStringInstructions = this.hasStroke_ ? generateLineStringRenderInstructions(
      geometryBatch.lineStringBatch,
      new Float32Array(0),
      this.customAttributes_,
      transform
    ) : null;
    const pointInstructions = this.hasSymbol_ ? generatePointRenderInstructions(
      geometryBatch.pointBatch,
      new Float32Array(0),
      this.customAttributes_,
      transform
    ) : null;
    return {
      polygonInstructions,
      lineStringInstructions,
      pointInstructions
    };
  }
  /**
   * @param {Float32Array|null} renderInstructions Render instructions
   * @param {import("../../geom/Geometry.js").Type} geometryType Geometry type
   * @param {import("../../transform.js").Transform} transform Transform to apply to coordinates
   * @return {Promise<WebGLArrayBufferSet>|null} Indices buffer and vertices buffer; null if nothing to render
   * @private
   */
  generateBuffersForType_(renderInstructions, geometryType, transform) {
    if (renderInstructions === null) {
      return null;
    }
    const messageId = workerMessageCounter++;
    let messageType;
    switch (geometryType) {
      case "Polygon":
        messageType = WebGLWorkerMessageType.GENERATE_POLYGON_BUFFERS;
        break;
      case "LineString":
        messageType = WebGLWorkerMessageType.GENERATE_LINE_STRING_BUFFERS;
        break;
      case "Point":
        messageType = WebGLWorkerMessageType.GENERATE_POINT_BUFFERS;
        break;
      default:
    }
    const message = {
      id: messageId,
      type: messageType,
      renderInstructions: renderInstructions.buffer,
      renderInstructionsTransform: transform,
      customAttributesSize: getCustomAttributesSize(this.customAttributes_)
    };
    const WEBGL_WORKER2 = getWebGLWorker();
    WEBGL_WORKER2.postMessage(message, [renderInstructions.buffer]);
    renderInstructions = null;
    return new Promise((resolve) => {
      const handleMessage = (event) => {
        const received = event.data;
        if (received.id !== messageId) {
          return;
        }
        WEBGL_WORKER2.removeEventListener("message", handleMessage);
        if (!this.helper_.getGL()) {
          return;
        }
        const indicesBuffer = new Buffer_default(
          ELEMENT_ARRAY_BUFFER,
          DYNAMIC_DRAW
        ).fromArrayBuffer(received.indicesBuffer);
        const vertexAttributesBuffer = new Buffer_default(
          ARRAY_BUFFER,
          DYNAMIC_DRAW
        ).fromArrayBuffer(received.vertexAttributesBuffer);
        const instanceAttributesBuffer = new Buffer_default(
          ARRAY_BUFFER,
          DYNAMIC_DRAW
        ).fromArrayBuffer(received.instanceAttributesBuffer);
        this.helper_.flushBufferData(indicesBuffer);
        this.helper_.flushBufferData(vertexAttributesBuffer);
        this.helper_.flushBufferData(instanceAttributesBuffer);
        resolve([
          indicesBuffer,
          vertexAttributesBuffer,
          instanceAttributesBuffer
        ]);
      };
      WEBGL_WORKER2.addEventListener("message", handleMessage);
    });
  }
  /**
   * Render the geometries in the given buffers.
   * @param {WebGLBuffers} buffers WebGL Buffers to draw
   * @param {import("../../Map.js").FrameState} frameState Frame state
   * @param {function(): void} preRenderCallback This callback will be called right before drawing, and can be used to set uniforms
   */
  render(buffers, frameState, preRenderCallback) {
    for (const renderPass of this.renderPasses_) {
      renderPass.fillRenderPass && this.renderInternal_(
        buffers.polygonBuffers[0],
        buffers.polygonBuffers[1],
        buffers.polygonBuffers[2],
        renderPass.fillRenderPass,
        frameState,
        preRenderCallback
      );
      renderPass.strokeRenderPass && this.renderInternal_(
        buffers.lineStringBuffers[0],
        buffers.lineStringBuffers[1],
        buffers.lineStringBuffers[2],
        renderPass.strokeRenderPass,
        frameState,
        preRenderCallback
      );
      renderPass.symbolRenderPass && this.renderInternal_(
        buffers.pointBuffers[0],
        buffers.pointBuffers[1],
        buffers.pointBuffers[2],
        renderPass.symbolRenderPass,
        frameState,
        preRenderCallback
      );
    }
  }
  /**
   * @param {WebGLArrayBuffer} indicesBuffer Indices buffer
   * @param {WebGLArrayBuffer} vertexAttributesBuffer Vertex attributes buffer
   * @param {WebGLArrayBuffer} instanceAttributesBuffer Instance attributes buffer
   * @param {SubRenderPass} subRenderPass Render pass (program, attributes, etc.) specific to one geometry type
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @param {function(): void} preRenderCallback This callback will be called right before drawing, and can be used to set uniforms
   * @private
   */
  renderInternal_(indicesBuffer, vertexAttributesBuffer, instanceAttributesBuffer, subRenderPass, frameState, preRenderCallback) {
    const renderCount = indicesBuffer.getSize();
    if (renderCount === 0) {
      return;
    }
    const usesInstancedRendering = subRenderPass.instancedAttributesDesc.length;
    this.helper_.useProgram(subRenderPass.program, frameState);
    this.helper_.bindBuffer(vertexAttributesBuffer);
    this.helper_.bindBuffer(indicesBuffer);
    this.helper_.enableAttributes(subRenderPass.attributesDesc);
    this.helper_.bindBuffer(instanceAttributesBuffer);
    this.helper_.enableAttributesInstanced(
      subRenderPass.instancedAttributesDesc
    );
    preRenderCallback();
    if (usesInstancedRendering) {
      const instanceAttributesStride = subRenderPass.instancedAttributesDesc.reduce(
        (prev, curr) => prev + (curr.size || 1),
        0
      );
      const instanceCount = instanceAttributesBuffer.getSize() / instanceAttributesStride;
      this.helper_.drawElementsInstanced(0, renderCount, instanceCount);
    } else {
      this.helper_.drawElements(0, renderCount);
    }
  }
  /**
   * @param {import('../../webgl/Helper.js').default} helper Helper
   * @param {WebGLBuffers} buffers WebGL Buffers to reload if any
   */
  setHelper(helper, buffers = null) {
    this.helper_ = helper;
    for (const renderPass of this.renderPasses_) {
      if (renderPass.fillRenderPass) {
        renderPass.fillRenderPass.program = this.helper_.getProgram(
          renderPass.fillRenderPass.fragmentShader,
          renderPass.fillRenderPass.vertexShader
        );
      }
      if (renderPass.strokeRenderPass) {
        renderPass.strokeRenderPass.program = this.helper_.getProgram(
          renderPass.strokeRenderPass.fragmentShader,
          renderPass.strokeRenderPass.vertexShader
        );
      }
      if (renderPass.symbolRenderPass) {
        renderPass.symbolRenderPass.program = this.helper_.getProgram(
          renderPass.symbolRenderPass.fragmentShader,
          renderPass.symbolRenderPass.vertexShader
        );
      }
    }
    this.helper_.addUniforms(this.uniforms_);
    if (buffers) {
      if (buffers.polygonBuffers) {
        this.helper_.flushBufferData(buffers.polygonBuffers[0]);
        this.helper_.flushBufferData(buffers.polygonBuffers[1]);
        this.helper_.flushBufferData(buffers.polygonBuffers[2]);
      }
      if (buffers.lineStringBuffers) {
        this.helper_.flushBufferData(buffers.lineStringBuffers[0]);
        this.helper_.flushBufferData(buffers.lineStringBuffers[1]);
        this.helper_.flushBufferData(buffers.lineStringBuffers[2]);
      }
      if (buffers.pointBuffers) {
        this.helper_.flushBufferData(buffers.pointBuffers[0]);
        this.helper_.flushBufferData(buffers.pointBuffers[1]);
        this.helper_.flushBufferData(buffers.pointBuffers[2]);
      }
    }
  }
};
var VectorStyleRenderer_default = VectorStyleRenderer;
function convertStyleToShaders(style, variables) {
  const asArray2 = Array.isArray(style) ? style : [style];
  if ("style" in asArray2[0]) {
    const shaders = [];
    const rules = (
      /** @type {Array<FlatStyleRule>} */
      asArray2
    );
    const previousFilters = [];
    for (const rule of rules) {
      const ruleStyles = Array.isArray(rule.style) ? rule.style : [rule.style];
      let currentFilter = rule.filter;
      if (rule.else && previousFilters.length) {
        currentFilter = [
          "all",
          ...previousFilters.map((filter) => ["!", filter])
        ];
        if (rule.filter) {
          currentFilter.push(rule.filter);
        }
        if (currentFilter.length < 3) {
          currentFilter = currentFilter[1];
        }
      }
      if (rule.filter) {
        previousFilters.push(rule.filter);
      }
      const styleShaders = ruleStyles.map(
        (style2) => parseLiteralStyle(style2, variables, currentFilter)
      );
      shaders.push(...styleShaders);
    }
    return shaders;
  }
  if ("builder" in asArray2[0]) {
    return (
      /** @type {Array<StyleShaders>} */
      asArray2
    );
  }
  return (
    /** @type {Array<FlatStyle>} */
    asArray2.map(
      (style2) => parseLiteralStyle(style2, variables, null)
    )
  );
}

// node_modules/ol/webgl/RenderTarget.js
var tmpArray4 = new Uint8Array(4);
var WebGLRenderTarget = class {
  /**
   * @param {import("./Helper.js").default} helper WebGL helper; mandatory.
   * @param {Array<number>} [size] Expected size of the render target texture; note: this can be changed later on.
   */
  constructor(helper, size) {
    this.helper_ = helper;
    const gl = helper.getGL();
    this.texture_ = gl.createTexture();
    this.framebuffer_ = gl.createFramebuffer();
    this.depthbuffer_ = gl.createRenderbuffer();
    this.size_ = size || [1, 1];
    this.data_ = new Uint8Array(0);
    this.dataCacheDirty_ = true;
    this.updateSize_();
  }
  /**
   * Changes the size of the render target texture. Note: will do nothing if the size
   * is already the same.
   * @param {Array<number>} size Expected size of the render target texture
   */
  setSize(size) {
    if (equals(size, this.size_)) {
      return;
    }
    this.size_[0] = size[0];
    this.size_[1] = size[1];
    this.updateSize_();
  }
  /**
   * Returns the size of the render target texture
   * @return {Array<number>} Size of the render target texture
   */
  getSize() {
    return this.size_;
  }
  /**
   * This will cause following calls to `#readAll` or `#readPixel` to download the content of the
   * render target into memory, which is an expensive operation.
   * This content will be kept in cache but should be cleared after each new render.
   */
  clearCachedData() {
    this.dataCacheDirty_ = true;
  }
  /**
   * Returns the full content of the frame buffer as a series of r, g, b, a components
   * in the 0-255 range (unsigned byte).
   * @return {Uint8Array} Integer array of color values
   */
  readAll() {
    if (this.dataCacheDirty_) {
      const size = this.size_;
      const gl = this.helper_.getGL();
      gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer_);
      gl.readPixels(
        0,
        0,
        size[0],
        size[1],
        gl.RGBA,
        gl.UNSIGNED_BYTE,
        this.data_
      );
      this.dataCacheDirty_ = false;
    }
    return this.data_;
  }
  /**
   * Reads one pixel of the frame buffer as an array of r, g, b, a components
   * in the 0-255 range (unsigned byte).
   * If x and/or y are outside of existing data, an array filled with 0 is returned.
   * @param {number} x Pixel coordinate
   * @param {number} y Pixel coordinate
   * @return {Uint8Array} Integer array with one color value (4 components)
   */
  readPixel(x, y) {
    if (x < 0 || y < 0 || x > this.size_[0] || y >= this.size_[1]) {
      tmpArray4[0] = 0;
      tmpArray4[1] = 0;
      tmpArray4[2] = 0;
      tmpArray4[3] = 0;
      return tmpArray4;
    }
    this.readAll();
    const index = Math.floor(x) + (this.size_[1] - Math.floor(y) - 1) * this.size_[0];
    tmpArray4[0] = this.data_[index * 4];
    tmpArray4[1] = this.data_[index * 4 + 1];
    tmpArray4[2] = this.data_[index * 4 + 2];
    tmpArray4[3] = this.data_[index * 4 + 3];
    return tmpArray4;
  }
  /**
   * @return {WebGLTexture} Texture to render to
   */
  getTexture() {
    return this.texture_;
  }
  /**
   * @return {WebGLFramebuffer} Frame buffer of the render target
   */
  getFramebuffer() {
    return this.framebuffer_;
  }
  /**
   * @return {WebGLRenderbuffer} Depth buffer of the render target
   */
  getDepthbuffer() {
    return this.depthbuffer_;
  }
  /**
   * @private
   */
  updateSize_() {
    const size = this.size_;
    const gl = this.helper_.getGL();
    this.texture_ = this.helper_.createTexture(size, null, this.texture_);
    gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer_);
    gl.viewport(0, 0, size[0], size[1]);
    gl.framebufferTexture2D(
      gl.FRAMEBUFFER,
      gl.COLOR_ATTACHMENT0,
      gl.TEXTURE_2D,
      this.texture_,
      0
    );
    gl.bindRenderbuffer(gl.RENDERBUFFER, this.depthbuffer_);
    gl.renderbufferStorage(
      gl.RENDERBUFFER,
      gl.DEPTH_COMPONENT16,
      size[0],
      size[1]
    );
    gl.framebufferRenderbuffer(
      gl.FRAMEBUFFER,
      gl.DEPTH_ATTACHMENT,
      gl.RENDERBUFFER,
      this.depthbuffer_
    );
    this.data_ = new Uint8Array(size[0] * size[1] * 4);
  }
};
var RenderTarget_default = WebGLRenderTarget;

// node_modules/ol/renderer/webgl/worldUtil.js
function getWorldParameters(frameState, layer) {
  const projection = frameState.viewState.projection;
  const vectorSource = layer.getSource();
  const multiWorld = vectorSource.getWrapX() && projection.canWrapX();
  const projectionExtent = projection.getExtent();
  const extent = frameState.extent;
  const worldWidth = multiWorld ? getWidth(projectionExtent) : null;
  const endWorld = multiWorld ? Math.ceil((extent[2] - projectionExtent[2]) / worldWidth) + 1 : 1;
  const startWorld = multiWorld ? Math.floor((extent[0] - projectionExtent[0]) / worldWidth) : 0;
  return [startWorld, endWorld, worldWidth];
}

// node_modules/ol/renderer/webgl/VectorLayer.js
var Uniforms3 = {
  ...DefaultUniform,
  RENDER_EXTENT: "u_renderExtent",
  // intersection of layer, source, and view extent
  PATTERN_ORIGIN: "u_patternOrigin",
  GLOBAL_ALPHA: "u_globalAlpha"
};
var WebGLVectorLayerRenderer = class extends Layer_default2 {
  /**
   * @param {import("../../layer/Layer.js").default} layer Layer.
   * @param {Options} options Options.
   */
  constructor(layer, options) {
    const uniforms = {
      [Uniforms3.RENDER_EXTENT]: [0, 0, 0, 0],
      [Uniforms3.PATTERN_ORIGIN]: [0, 0],
      [Uniforms3.GLOBAL_ALPHA]: 1
    };
    super(layer, {
      uniforms,
      postProcesses: options.postProcesses
    });
    this.hitDetectionEnabled_ = !options.disableHitDetection;
    this.hitRenderTarget_;
    this.sourceRevision_ = -1;
    this.previousExtent_ = createEmpty();
    this.currentTransform_ = create();
    this.tmpCoords_ = [0, 0];
    this.tmpTransform_ = create();
    this.tmpMat4_ = create2();
    this.currentFrameStateTransform_ = create();
    this.styleVariables_ = {};
    this.style_ = [];
    this.styleRenderer_ = null;
    this.buffers_ = null;
    this.applyOptions_(options);
    this.batch_ = new MixedGeometryBatch_default();
    this.initialFeaturesAdded_ = false;
    this.sourceListenKeys_ = null;
  }
  /**
   * @private
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   */
  addInitialFeatures_(frameState) {
    const source = this.getLayer().getSource();
    const userProjection = getUserProjection();
    let projectionTransform;
    if (userProjection) {
      projectionTransform = getTransformFromProjections(
        userProjection,
        frameState.viewState.projection
      );
    }
    this.batch_.addFeatures(source.getFeatures(), projectionTransform);
    this.sourceListenKeys_ = [
      listen(
        source,
        VectorEventType_default.ADDFEATURE,
        this.handleSourceFeatureAdded_.bind(this, projectionTransform)
      ),
      listen(
        source,
        VectorEventType_default.CHANGEFEATURE,
        this.handleSourceFeatureChanged_.bind(this, projectionTransform),
        this
      ),
      listen(
        source,
        VectorEventType_default.REMOVEFEATURE,
        this.handleSourceFeatureDelete_,
        this
      ),
      listen(
        source,
        VectorEventType_default.CLEAR,
        this.handleSourceFeatureClear_,
        this
      )
    ];
  }
  /**
   * @param {Options} options Options.
   * @private
   */
  applyOptions_(options) {
    this.styleVariables_ = options.variables;
    this.style_ = options.style;
  }
  /**
   * @private
   */
  createRenderers_() {
    this.buffers_ = null;
    this.styleRenderer_ = new VectorStyleRenderer_default(
      this.style_,
      this.styleVariables_,
      this.helper,
      this.hitDetectionEnabled_
    );
  }
  /**
   * @override
   */
  reset(options) {
    this.applyOptions_(options);
    if (this.helper) {
      this.createRenderers_();
    }
    super.reset(options);
  }
  /**
   * @override
   */
  afterHelperCreated() {
    if (this.styleRenderer_) {
      this.styleRenderer_.setHelper(this.helper, this.buffers_);
    } else {
      this.createRenderers_();
    }
    if (this.hitDetectionEnabled_) {
      this.hitRenderTarget_ = new RenderTarget_default(this.helper);
    }
  }
  /**
   * @param {import("../../proj.js").TransformFunction} projectionTransform Transform function.
   * @param {import("../../source/Vector.js").VectorSourceEvent} event Event.
   * @private
   */
  handleSourceFeatureAdded_(projectionTransform, event) {
    const feature = event.feature;
    this.batch_.addFeature(feature, projectionTransform);
  }
  /**
   * @param {import("../../proj.js").TransformFunction} projectionTransform Transform function.
   * @param {import("../../source/Vector.js").VectorSourceEvent} event Event.
   * @private
   */
  handleSourceFeatureChanged_(projectionTransform, event) {
    const feature = event.feature;
    this.batch_.changeFeature(feature, projectionTransform);
  }
  /**
   * @param {import("../../source/Vector.js").VectorSourceEvent} event Event.
   * @private
   */
  handleSourceFeatureDelete_(event) {
    const feature = event.feature;
    this.batch_.removeFeature(feature);
  }
  /**
   * @private
   */
  handleSourceFeatureClear_() {
    this.batch_.clear();
  }
  /**
   * @param {import("../../transform.js").Transform} batchInvertTransform Inverse of the transformation in which geometries are expressed
   * @private
   */
  applyUniforms_(batchInvertTransform) {
    setFromArray(this.tmpTransform_, this.currentFrameStateTransform_);
    multiply(this.tmpTransform_, batchInvertTransform);
    this.helper.setUniformMatrixValue(
      Uniforms3.PROJECTION_MATRIX,
      fromTransform(this.tmpMat4_, this.tmpTransform_)
    );
    makeInverse(this.tmpTransform_, this.tmpTransform_);
    this.helper.setUniformMatrixValue(
      Uniforms3.SCREEN_TO_WORLD_MATRIX,
      fromTransform(this.tmpMat4_, this.tmpTransform_)
    );
    this.tmpCoords_[0] = 0;
    this.tmpCoords_[1] = 0;
    makeInverse(this.tmpTransform_, batchInvertTransform);
    apply(this.tmpTransform_, this.tmpCoords_);
    this.helper.setUniformFloatVec2(Uniforms3.PATTERN_ORIGIN, this.tmpCoords_);
  }
  /**
   * Render the layer.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @return {HTMLElement} The rendered element.
   * @override
   */
  renderFrame(frameState) {
    const gl = this.helper.getGL();
    this.preRender(gl, frameState);
    const [startWorld, endWorld, worldWidth] = getWorldParameters(
      frameState,
      this.getLayer()
    );
    this.helper.prepareDraw(frameState);
    this.renderWorlds(frameState, false, startWorld, endWorld, worldWidth);
    this.helper.finalizeDraw(
      frameState,
      this.dispatchPreComposeEvent,
      this.dispatchPostComposeEvent
    );
    const canvas = this.helper.getCanvas();
    if (this.hitDetectionEnabled_) {
      this.renderWorlds(frameState, true, startWorld, endWorld, worldWidth);
      this.hitRenderTarget_.clearCachedData();
    }
    this.postRender(gl, frameState);
    return canvas;
  }
  /**
   * Determine whether renderFrame should be called.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @return {boolean} Layer is ready to be rendered.
   * @override
   */
  prepareFrameInternal(frameState) {
    if (!this.initialFeaturesAdded_) {
      this.addInitialFeatures_(frameState);
      this.initialFeaturesAdded_ = true;
    }
    const layer = this.getLayer();
    const vectorSource = layer.getSource();
    const viewState = frameState.viewState;
    const viewNotMoving = !frameState.viewHints[ViewHint_default.ANIMATING] && !frameState.viewHints[ViewHint_default.INTERACTING];
    const extentChanged = !equals2(this.previousExtent_, frameState.extent);
    const sourceChanged = this.sourceRevision_ < vectorSource.getRevision();
    if (sourceChanged) {
      this.sourceRevision_ = vectorSource.getRevision();
    }
    if (viewNotMoving && (extentChanged || sourceChanged)) {
      const projection = viewState.projection;
      const resolution = viewState.resolution;
      const renderBuffer = layer instanceof BaseVector_default ? layer.getRenderBuffer() : 0;
      const extent = buffer(frameState.extent, renderBuffer * resolution);
      const userProjection = getUserProjection();
      if (userProjection) {
        vectorSource.loadFeatures(
          toUserExtent(extent, userProjection),
          toUserResolution(resolution, projection),
          userProjection
        );
      } else {
        vectorSource.loadFeatures(extent, resolution, projection);
      }
      this.ready = false;
      const transform = this.helper.makeProjectionTransform(
        frameState,
        create()
      );
      this.styleRenderer_.generateBuffers(this.batch_, transform).then((buffers) => {
        if (this.buffers_) {
          this.disposeBuffers(this.buffers_);
        }
        this.buffers_ = buffers;
        this.ready = true;
        this.getLayer().changed();
      });
      this.previousExtent_ = frameState.extent.slice();
    }
    return true;
  }
  /**
   * Render the world, either to the main framebuffer or to the hit framebuffer
   * @param {import("../../Map.js").FrameState} frameState current frame state
   * @param {boolean} forHitDetection whether the rendering is for hit detection
   * @param {number} startWorld the world to render in the first iteration
   * @param {number} endWorld the last world to render
   * @param {number} worldWidth the width of the worlds being rendered
   */
  renderWorlds(frameState, forHitDetection, startWorld, endWorld, worldWidth) {
    let world = startWorld;
    if (forHitDetection) {
      this.hitRenderTarget_.setSize([
        Math.floor(frameState.size[0] / 2),
        Math.floor(frameState.size[1] / 2)
      ]);
      this.helper.prepareDrawToRenderTarget(
        frameState,
        this.hitRenderTarget_,
        true
      );
    }
    do {
      this.helper.makeProjectionTransform(
        frameState,
        this.currentFrameStateTransform_
      );
      translate(
        this.currentFrameStateTransform_,
        world * worldWidth,
        0
      );
      if (!this.buffers_) {
        continue;
      }
      this.styleRenderer_.render(this.buffers_, frameState, () => {
        this.applyUniforms_(this.buffers_.invertVerticesTransform);
        this.helper.applyHitDetectionUniform(forHitDetection);
      });
    } while (++world < endWorld);
  }
  /**
   * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate.
   * @param {import("../../Map.js").FrameState} frameState Frame state.
   * @param {number} hitTolerance Hit tolerance in pixels.
   * @param {import("../vector.js").FeatureCallback<T>} callback Feature callback.
   * @param {Array<import("../Map.js").HitMatch<T>>} matches The hit detected matches with tolerance.
   * @return {T|undefined} Callback result.
   * @template T
   * @override
   */
  forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, matches) {
    assert(
      this.hitDetectionEnabled_,
      "`forEachFeatureAtCoordinate` cannot be used on a WebGL layer if the hit detection logic has been disabled using the `disableHitDetection: true` option."
    );
    if (!this.styleRenderer_ || !this.hitDetectionEnabled_) {
      return void 0;
    }
    const pixel = apply(
      frameState.coordinateToPixelTransform,
      coordinate.slice()
    );
    const data = this.hitRenderTarget_.readPixel(pixel[0] / 2, pixel[1] / 2);
    const color = [data[0] / 255, data[1] / 255, data[2] / 255, data[3] / 255];
    const ref = colorDecodeId(color);
    const feature = this.batch_.getFeatureFromRef(ref);
    if (feature) {
      return callback(feature, this.getLayer(), null);
    }
    return void 0;
  }
  /**
   * Will release a set of Webgl buffers
   * @param {import('../../render/webgl/VectorStyleRenderer.js').WebGLBuffers} buffers Buffers
   */
  disposeBuffers(buffers) {
    const disposeBuffersOfType = (typeBuffers) => {
      for (const buffer2 of typeBuffers) {
        if (buffer2) {
          this.helper.deleteBuffer(buffer2);
        }
      }
    };
    if (buffers.pointBuffers) {
      disposeBuffersOfType(buffers.pointBuffers);
    }
    if (buffers.lineStringBuffers) {
      disposeBuffersOfType(buffers.lineStringBuffers);
    }
    if (buffers.polygonBuffers) {
      disposeBuffersOfType(buffers.polygonBuffers);
    }
  }
  /**
   * Clean up.
   * @override
   */
  disposeInternal() {
    if (this.buffers_) {
      this.disposeBuffers(this.buffers_);
    }
    if (this.sourceListenKeys_) {
      this.sourceListenKeys_.forEach(function(key) {
        unlistenByKey(key);
      });
      this.sourceListenKeys_ = null;
    }
    super.disposeInternal();
  }
  renderDeclutter() {
  }
};
var VectorLayer_default = WebGLVectorLayerRenderer;

// node_modules/ol/layer/Heatmap.js
var Property = {
  BLUR: "blur",
  GRADIENT: "gradient",
  RADIUS: "radius"
};
var DEFAULT_GRADIENT = ["#00f", "#0ff", "#0f0", "#ff0", "#f00"];
var Heatmap = class extends BaseVector_default {
  /**
   * @param {Options<FeatureType, VectorSourceType>} [options] Options.
   */
  constructor(options) {
    options = options ? options : {};
    const baseOptions = Object.assign({}, options);
    delete baseOptions.gradient;
    delete baseOptions.radius;
    delete baseOptions.blur;
    delete baseOptions.weight;
    super(baseOptions);
    this.filter_ = options.filter ?? true;
    this.styleVariables_ = options.variables || {};
    this.gradient_ = null;
    this.addChangeListener(Property.GRADIENT, this.handleGradientChanged_);
    this.setGradient(options.gradient ? options.gradient : DEFAULT_GRADIENT);
    this.setBlur(options.blur !== void 0 ? options.blur : 15);
    this.setRadius(options.radius !== void 0 ? options.radius : 8);
    const weight = options.weight ? options.weight : "weight";
    this.weight_ = weight;
    this.setRenderOrder(null);
  }
  /**
   * Return the blur size in pixels.
   * @return {import("../style/flat.js").NumberExpression} Blur size in pixels.
   * @api
   * @observable
   */
  getBlur() {
    return (
      /** @type {import("../style/flat.js").NumberExpression} */
      this.get(Property.BLUR)
    );
  }
  /**
   * Return the gradient colors as array of strings.
   * @return {Array<string>} Colors.
   * @api
   * @observable
   */
  getGradient() {
    return (
      /** @type {Array<string>} */
      this.get(Property.GRADIENT)
    );
  }
  /**
   * Return the size of the radius in pixels.
   * @return {import("../style/flat.js").NumberExpression} Radius size in pixel.
   * @api
   * @observable
   */
  getRadius() {
    return (
      /** @type {import("../style/flat.js").NumberExpression} */
      this.get(Property.RADIUS)
    );
  }
  /**
   * @private
   */
  handleGradientChanged_() {
    this.gradient_ = createGradient(this.getGradient());
  }
  /**
   * Set the blur size in pixels.
   * @param {import("../style/flat.js").NumberExpression} blur Blur size in pixels (supports expressions).
   * @api
   * @observable
   */
  setBlur(blur) {
    const previousValue = this.get(Property.BLUR);
    this.set(Property.BLUR, blur);
    if (typeof blur === "number" && typeof previousValue === "number") {
      this.changed();
      return;
    }
    this.clearRenderer();
  }
  /**
   * Set the gradient colors as array of strings.
   * @param {Array<string>} colors Gradient.
   * @api
   * @observable
   */
  setGradient(colors) {
    this.set(Property.GRADIENT, colors);
  }
  /**
   * Set the size of the radius in pixels.
   * @param {import("../style/flat.js").NumberExpression} radius Radius size in pixel (supports expressions).
   * @api
   * @observable
   */
  setRadius(radius) {
    const previousValue = this.get(Property.RADIUS);
    this.set(Property.RADIUS, radius);
    if (typeof radius === "number" && typeof previousValue === "number") {
      this.changed();
      return;
    }
    this.clearRenderer();
  }
  /**
   * Set the filter expression
   * @param {import("../style/flat.js").BooleanExpression} filter Filter expression
   * @api
   */
  setFilter(filter) {
    this.filter_ = filter;
    this.changed();
    this.clearRenderer();
  }
  /**
   * Set the weight expression
   * @param {WeightExpression} weight Weight expression
   * @api
   */
  setWeight(weight) {
    this.weight_ = weight;
    this.changed();
    this.clearRenderer();
  }
  /**
   * @override
   */
  createRenderer() {
    const builder = new ShaderBuilder();
    const context = newCompilationContext();
    const filterCompiled = expressionToGlsl(context, this.filter_, BooleanType);
    let radiusCompiled = expressionToGlsl(
      context,
      this.getRadius(),
      NumberType
    );
    let blurCompiled = expressionToGlsl(context, this.getBlur(), NumberType);
    const blurRadiusUniforms = {};
    if (typeof this.getBlur() === "number") {
      blurCompiled = "a_blur";
      blurRadiusUniforms["a_blur"] = () => this.getBlur();
      builder.addUniform("a_blur", "float");
    }
    if (typeof this.getRadius() === "number") {
      radiusCompiled = "a_radius";
      blurRadiusUniforms["a_radius"] = () => this.getRadius();
      builder.addUniform("a_radius", "float");
    }
    const weightAttribute = {};
    let weightExpression = null;
    if (typeof this.weight_ === "string" || typeof this.weight_ === "function") {
      const weightFunction = typeof this.weight_ === "string" ? (feature) => feature.get(this.weight_) : this.weight_;
      weightAttribute["prop_weight"] = {
        size: 1,
        callback: (feature) => {
          const weightValue = weightFunction(feature);
          return weightValue !== void 0 ? clamp(weightValue, 0, 1) : 1;
        }
      };
      weightExpression = "a_prop_weight";
      builder.addAttribute("a_prop_weight", "float");
    } else {
      const clampedWeight = ["clamp", this.weight_, 0, 1];
      weightExpression = expressionToGlsl(context, clampedWeight, NumberType);
    }
    builder.addFragmentShaderFunction(
      `float getBlurSlope() {
  float blur = max(1., ${blurCompiled});
  float radius = ${radiusCompiled};
  return radius / blur;
}`
    ).setSymbolSizeExpression(`vec2(${radiusCompiled} + ${blurCompiled}) * 2.`).setSymbolColorExpression(
      `vec4(smoothstep(0., 1., (1. - length(coordsPx * 2. / v_quadSizePx)) * getBlurSlope()) * ${weightExpression})`
    ).setStrokeColorExpression(
      `vec4(smoothstep(0., 1., (1. - length(currentRadiusPx * 2. / v_width)) * getBlurSlope()) * ${weightExpression})`
    ).setStrokeWidthExpression(`(${radiusCompiled} + ${blurCompiled}) * 2.`).setFillColorExpression(`vec4(${weightExpression})`).setFragmentDiscardExpression(`!${filterCompiled}`);
    applyContextToBuilder(builder, context);
    const attributes = generateAttributesFromContext(context);
    const uniforms = generateUniformsFromContext(context, this.styleVariables_);
    return new VectorLayer_default(this, {
      className: this.getClassName(),
      variables: this.styleVariables_,
      style: {
        builder,
        attributes: {
          ...attributes,
          ...weightAttribute
        },
        uniforms: {
          ...uniforms,
          ...blurRadiusUniforms
        }
      },
      disableHitDetection: false,
      postProcesses: [
        {
          fragmentShader: `
            precision mediump float;

            uniform sampler2D u_image;
            uniform sampler2D u_gradientTexture;
            uniform float u_opacity;

            varying vec2 v_texCoord;

            void main() {
              vec4 color = texture2D(u_image, v_texCoord);
              gl_FragColor.a = color.a * u_opacity;
              gl_FragColor.rgb = texture2D(u_gradientTexture, vec2(0.5, color.a)).rgb;
              gl_FragColor.rgb *= gl_FragColor.a;
            }`,
          uniforms: {
            u_gradientTexture: () => this.gradient_,
            u_opacity: () => this.getOpacity()
          }
        }
      ]
    });
  }
  /**
   * Update any variables used by the layer style and trigger a re-render.
   * @param {import('../style/flat.js').StyleVariables} variables Variables to update.
   */
  updateStyleVariables(variables) {
    Object.assign(this.styleVariables_, variables);
    this.changed();
  }
  /**
   * @override
   */
  renderDeclutter() {
  }
};
function createGradient(colors) {
  const width = 1;
  const height = 256;
  const context = createCanvasContext2D(width, height);
  const gradient = context.createLinearGradient(0, 0, width, height);
  const step = 1 / (colors.length - 1);
  for (let i = 0, ii = colors.length; i < ii; ++i) {
    gradient.addColorStop(i * step, colors[i]);
  }
  context.fillStyle = gradient;
  context.fillRect(0, 0, width, height);
  return context.canvas;
}
var Heatmap_default = Heatmap;

export {
  VectorTile_default,
  ARRAY_BUFFER,
  ELEMENT_ARRAY_BUFFER,
  DYNAMIC_DRAW,
  Buffer_default,
  DefaultUniform,
  AttributeType,
  Layer_default2 as Layer_default,
  Uniforms2 as Uniforms,
  Attributes,
  TileLayer_default2 as TileLayer_default,
  getStringNumberEquivalent,
  uniformNameForVariable,
  newCompilationContext,
  PALETTE_TEXTURE_ARRAY,
  expressionToGlsl,
  create3 as create,
  WebGLWorkerMessageType,
  colorEncodeIdAndPack,
  colorDecodeId,
  parseLiteralStyle,
  RenderTarget_default,
  getWorldParameters,
  VectorLayer_default,
  Heatmap_default
};
//# sourceMappingURL=chunk-YUMATXXX.js.map
