import {
  SubsetGeometry
} from "./chunk-NOXCCC7Y.js";
import "./chunk-JSBRDJBE.js";

// src/js-tools/three-utils/compute/compute-program.ts
import {
  Camera,
  Points,
  WebGLRenderer as WebGLRenderer2
} from "three";

// src/js-tools/three-utils/compute/compute-render-target.ts
import {
  ClampToEdgeWrapping,
  FloatType,
  NearestFilter,
  RGBAFormat,
  RGFormat,
  RedFormat,
  WebGLRenderTarget
} from "three";

// src/js-tools/three-utils/compute/utils.ts
function computeTextureDimensions(outputSize) {
  const width = Math.pow(2, Math.ceil(Math.log2(Math.sqrt(outputSize))));
  const height = Math.ceil(outputSize / width);
  return {
    width,
    height
  };
}

// src/js-tools/three-utils/compute/compute-render-target.ts
var pixelFormatMap = {
  [1]: RedFormat,
  [2]: RGFormat,
  [4]: RGBAFormat
};
var internalFormatMap = {
  [1]: {
    float: "R32F"
  },
  [2]: {
    float: "RG32F"
  },
  [4]: {
    float: "RGBA32F"
  }
};
var ComputeRenderTarget = class extends WebGLRenderTarget {
  constructor(outputCount, itemsPerPixel) {
    const rtDims = computeTextureDimensions(outputCount);
    super(rtDims.width, rtDims.height, {
      wrapS: ClampToEdgeWrapping,
      wrapT: ClampToEdgeWrapping,
      minFilter: NearestFilter,
      magFilter: NearestFilter,
      format: pixelFormatMap[itemsPerPixel],
      internalFormat: internalFormatMap[itemsPerPixel]["float"],
      type: FloatType
    });
    this.texture.needsUpdate = true;
    this._outputCount = outputCount;
    this._itemsPerPixel = itemsPerPixel;
    this._format = "float";
  }
  get outputCount() {
    return this._outputCount;
  }
  readData(renderer, start = 0, end = Infinity) {
    let readBuffer;
    switch (this._format) {
      case "float":
        readBuffer = new Float32Array(
          this.width * this.height * this._itemsPerPixel
        );
        break;
    }
    renderer.readRenderTargetPixels(
      this,
      0,
      0,
      this.width,
      this.height,
      readBuffer
    );
    if (end === Infinity) {
      return readBuffer.slice(
        start * this._itemsPerPixel,
        this._outputCount * this._itemsPerPixel
      );
    } else {
      return readBuffer.slice(
        start * this._itemsPerPixel,
        end * this._itemsPerPixel
      );
    }
  }
};
var compute_render_target_default = ComputeRenderTarget;

// src/js-tools/three-utils/compute/compute-program.ts
var dummyCamera = new Camera();
var ComputeProgram = class extends Points {
  constructor(geometry, material) {
    super(geometry, material);
    this.frustumCulled = false;
    this.material.onBeforeCompile = this._onBeforeMaterialCompile.bind(this);
    this._renderer = new WebGLRenderer2();
  }
  _onBeforeMaterialCompile(shader, renderer) {
    const renderTarget = renderer.getRenderTarget();
    if (renderTarget && renderTarget instanceof compute_render_target_default) {
      const versionLineVert = /#version \d+( es)?/.exec(shader.vertexShader)?.at(0);
      const versionLineFrag = /#version \d+( es)?/.exec(shader.fragmentShader)?.at(0);
      if (versionLineVert) {
        shader.vertexShader = shader.vertexShader.replace(
          versionLineVert,
          ""
        );
      }
      if (versionLineFrag) {
        shader.fragmentShader = shader.fragmentShader.replace(
          versionLineFrag,
          ""
        );
      }
      shader.uniforms = {
        ...shader.uniforms,
        _compute_rt_output_width: {
          value: renderTarget.width
        },
        _compute_rt_output_height: {
          value: renderTarget.height
        }
      };
    } else {
      throw new Error(
        "ComputeProgram should only be rendered to a ComputeRenderTarget"
      );
    }
  }
  async compute(renderTarget, start = 0, end = Infinity) {
    return await new Promise((resolve) => {
      requestAnimationFrame(() => {
        this.geometry.setDrawRange(start, end);
        this._renderer.setRenderTarget(renderTarget);
        this._renderer.setClearColor(0);
        this._renderer.clear();
        this._renderer.render(this, dummyCamera);
        resolve(renderTarget.readData(this._renderer, start, end));
      });
    });
  }
  dispose() {
    this.geometry.dispose();
    this.material.dispose();
  }
};
var compute_program_default = ComputeProgram;

// src/js-tools/three-utils/geojson.ts
import earcut, { flatten } from "earcut";
import { Color, Float32BufferAttribute } from "three";
var FeatureGeometry = class extends SubsetGeometry {
  constructor(attributes, featureInfos) {
    super(attributes, featureInfos);
    this._featureVertRanges = {};
    let offset = 0;
    for (const { id, vertCount } of featureInfos) {
      let ranges = this._featureVertRanges[id];
      if (!ranges) {
        ranges = [];
        this._featureVertRanges[id] = ranges;
      }
      ranges.push([offset, offset + vertCount]);
      offset += vertCount;
    }
    this.addAllIds();
  }
  getFeatureColor(id) {
    const ranges = this._featureVertRanges[id];
    if (ranges) {
      const colorAttrib = this.getAttribute("color");
      const color = new Color();
      const [start] = ranges[0];
      color.set(
        colorAttrib.array[start * 3],
        colorAttrib.array[start * 3 + 1],
        colorAttrib.array[start * 3 + 2]
      );
      return color;
    }
  }
  setFeatureColor(id, colRep) {
    const color = new Color(colRep);
    const ranges = this._featureVertRanges[id];
    if (ranges) {
      const colorAttrib = this.getAttribute("color");
      for (const [start, end] of ranges) {
        for (let i = start * 3; i < end * 3; i += 3) {
          colorAttrib.array[i] = color.r;
          colorAttrib.array[i + 1] = color.g;
          colorAttrib.array[i + 2] = color.b;
        }
        colorAttrib.addUpdateRange(start * 3, (end - start) * 3);
      }
      colorAttrib.needsUpdate = true;
    }
  }
};
var PolygonGeometry = class extends FeatureGeometry {
  constructor(polygons, {
    defaultColor = 0,
    projection,
    translate = [0, 0]
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < polygons.length; ++i) {
      const polygon = polygons[i];
      const data = flatten(polygon);
      const triangles = earcut(
        data.vertices,
        data.holes,
        data.dimensions
      );
      id.push(
        ...Array(data.vertices.length / data.dimensions).fill(i + 1)
      );
      let vertices = data.vertices;
      if (projection) {
        const beforeProj = vertices;
        vertices = [];
        for (let i2 = 0; i2 < beforeProj.length; i2 += data.dimensions) {
          const projected = projection.forward([
            beforeProj[i2],
            beforeProj[i2 + 1]
          ]);
          vertices.push(...projected);
        }
      }
      for (let j = 0; j < data.vertices.length; j += data.dimensions) {
        position.push(
          vertices[j] + translate[0],
          0,
          -vertices[j + 1] + translate[1]
        );
        color.push(col.r, col.g, col.b);
      }
      featureInfos.push({
        id: i + 1,
        vertCount: vertices.length / data.dimensions,
        indices: triangles
      });
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};
var PolygonEdgeGeometry = class extends FeatureGeometry {
  constructor(polygons, {
    defaultColor = 0,
    projection,
    translate = [0, 0]
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < polygons.length; ++i) {
      const polygon = polygons[i];
      for (let j = 0; j < polygon.length; ++j) {
        const ring = polygon[j];
        id.push(...Array(ring.length).fill(i + 1));
        let vertices = ring.reduce((flat, point) => {
          flat.push(...point);
          return flat;
        }, []);
        if (projection) {
          const beforeProj = vertices;
          vertices = [];
          for (let k = 0; k < beforeProj.length; k += 2) {
            const projected = projection.forward([
              beforeProj[k],
              beforeProj[k + 1]
            ]);
            vertices.push(...projected);
          }
        }
        for (let k = 0; k < vertices.length; k += 2) {
          position.push(
            vertices[k] + translate[0],
            0,
            -vertices[k + 1] + translate[1]
          );
          color.push(col.r, col.g, col.b);
        }
        const indices = Array();
        for (let k = 0; k < ring.length - 1; ++k) {
          indices.push(k, k + 1);
        }
        featureInfos.push({
          id: i + 1,
          vertCount: ring.length,
          indices
        });
      }
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};
var LineStringGeometry = class extends FeatureGeometry {
  constructor(lines, {
    defaultColor = 0,
    projection,
    translate = [0, 0]
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < lines.length; ++i) {
      const line = lines[i];
      id.push(...Array(line.length).fill(i + 1));
      let vertices = line.reduce((flat, point) => {
        flat.push(...point);
        return flat;
      }, []);
      if (projection) {
        const beforeProj = vertices;
        vertices = [];
        for (let k = 0; k < beforeProj.length; k += 2) {
          const projected = projection.forward([
            beforeProj[k],
            beforeProj[k + 1]
          ]);
          vertices.push(...projected);
        }
      }
      for (let k = 0; k < vertices.length; k += 2) {
        position.push(
          vertices[k] + translate[0],
          0,
          -vertices[k + 1] + translate[1]
        );
        color.push(col.r, col.g, col.b);
      }
      const indices = Array();
      for (let j = 0; j < line.length - 1; ++j) {
        indices.push(j, j + 1);
      }
      featureInfos.push({
        id: i + 1,
        vertCount: line.length,
        indices
      });
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};
var MultiPolygonGeometry = class extends FeatureGeometry {
  constructor(multiPolys, {
    defaultColor = 0,
    projection,
    translate = [0, 0]
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < multiPolys.length; ++i) {
      const multiPoly = multiPolys[i];
      for (let k = 0; k < multiPoly.length; ++k) {
        const polygon = multiPoly[k];
        const data = flatten(polygon);
        const triangles = earcut(
          data.vertices,
          data.holes,
          data.dimensions
        );
        id.push(
          ...Array(data.vertices.length / data.dimensions).fill(i + 1)
        );
        let vertices = data.vertices;
        if (projection) {
          const beforeProj = vertices;
          vertices = [];
          for (let i2 = 0; i2 < beforeProj.length; i2 += data.dimensions) {
            const projected = projection.forward([
              beforeProj[i2],
              beforeProj[i2 + 1]
            ]);
            vertices.push(...projected);
          }
        }
        for (let j = 0; j < data.vertices.length; j += data.dimensions) {
          position.push(
            vertices[j] + translate[0],
            0,
            -vertices[j + 1] + translate[1]
          );
          color.push(col.r, col.g, col.b);
        }
        featureInfos.push({
          id: i + 1,
          vertCount: vertices.length / data.dimensions,
          indices: triangles
        });
      }
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};
var MultiPolygonEdgeGeometry = class extends FeatureGeometry {
  constructor(multiPolys, {
    defaultColor = 0,
    projection,
    translate = [0, 0]
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < multiPolys.length; ++i) {
      const multiPoly = multiPolys[i];
      for (let k = 0; k < multiPoly.length; ++k) {
        const polygon = multiPoly[k];
        for (let j = 0; j < polygon.length; ++j) {
          const ring = polygon[j];
          id.push(...Array(ring.length).fill(i + 1));
          let vertices = ring.reduce((flat, point) => {
            flat.push(...point);
            return flat;
          }, []);
          if (projection) {
            const beforeProj = vertices;
            vertices = [];
            for (let k2 = 0; k2 < beforeProj.length; k2 += 2) {
              const projected = projection.forward([
                beforeProj[k2],
                beforeProj[k2 + 1]
              ]);
              vertices.push(...projected);
            }
          }
          for (let k2 = 0; k2 < vertices.length; k2 += 2) {
            position.push(
              vertices[k2] + translate[0],
              0,
              -vertices[k2 + 1] + translate[1]
            );
            color.push(col.r, col.g, col.b);
          }
          const indices = Array();
          for (let k2 = 0; k2 < ring.length - 1; ++k2) {
            indices.push(k2, k2 + 1);
          }
          featureInfos.push({
            id: i + 1,
            vertCount: ring.length,
            indices
          });
        }
      }
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};
var GeoJSONFillGeometry = class extends FeatureGeometry {
  constructor(features, {
    defaultColor = 0,
    projection,
    translate = [0, 0],
    getBaseHeight = () => 0
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < features.length; ++i) {
      const feature = features[i];
      const height = getBaseHeight(feature, i, features);
      const polygons = Array();
      switch (feature.geometry.type) {
        case "Polygon":
          polygons.push(feature.geometry.coordinates);
          break;
        case "MultiPolygon":
          for (const polygon of feature.geometry.coordinates) {
            polygons.push(polygon);
          }
          break;
        default:
          throw new Error("Invalid geometry type.");
      }
      for (let k = 0; k < polygons.length; ++k) {
        const polygon = polygons[k];
        const data = flatten(polygon);
        const triangles = earcut(
          data.vertices,
          data.holes,
          data.dimensions
        );
        id.push(
          ...Array(data.vertices.length / data.dimensions).fill(i + 1)
        );
        let vertices = data.vertices;
        if (projection) {
          const beforeProj = vertices;
          vertices = [];
          for (let i2 = 0; i2 < beforeProj.length; i2 += data.dimensions) {
            const projected = projection.forward([
              beforeProj[i2],
              beforeProj[i2 + 1]
            ]);
            vertices.push(...projected);
          }
        }
        for (let j = 0; j < data.vertices.length; j += data.dimensions) {
          position.push(
            vertices[j] + translate[0],
            height,
            -vertices[j + 1] + translate[1]
          );
          color.push(col.r, col.g, col.b);
        }
        featureInfos.push({
          id: i + 1,
          vertCount: vertices.length / data.dimensions,
          indices: triangles
        });
      }
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};
var GeoJSONEdgeGeometry = class extends FeatureGeometry {
  constructor(features, {
    defaultColor = 0,
    projection,
    translate = [0, 0],
    getBaseHeight = () => 0
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < features.length; ++i) {
      const feature = features[i];
      const height = getBaseHeight(feature, i, features);
      const polygons = Array();
      switch (feature.geometry.type) {
        case "Polygon":
          polygons.push(feature.geometry.coordinates);
          break;
        case "MultiPolygon":
          for (const polygon of feature.geometry.coordinates) {
            polygons.push(polygon);
          }
          break;
        default:
          throw new Error("Invalid geometry type.");
      }
      for (let k = 0; k < polygons.length; ++k) {
        const polygon = polygons[k];
        for (let j = 0; j < polygon.length; ++j) {
          const ring = polygon[j];
          id.push(...Array(ring.length).fill(i + 1));
          let vertices = ring.reduce((flat, point) => {
            flat.push(...point);
            return flat;
          }, []);
          if (projection) {
            const beforeProj = vertices;
            vertices = [];
            for (let k2 = 0; k2 < beforeProj.length; k2 += 2) {
              const projected = projection.forward([
                beforeProj[k2],
                beforeProj[k2 + 1]
              ]);
              vertices.push(...projected);
            }
          }
          for (let k2 = 0; k2 < vertices.length; k2 += 2) {
            position.push(
              vertices[k2] + translate[0],
              height,
              -vertices[k2 + 1] + translate[1]
            );
            color.push(col.r, col.g, col.b);
          }
          const indices = Array();
          for (let k2 = 0; k2 < ring.length - 1; ++k2) {
            indices.push(k2, k2 + 1);
          }
          featureInfos.push({
            id: i + 1,
            vertCount: ring.length,
            indices
          });
        }
      }
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};
var GeoJSONFillExtrudeGeometry = class extends FeatureGeometry {
  constructor(features, {
    defaultColor = 0,
    projection,
    translate = [0, 0],
    getBaseHeight = () => 0,
    getExtrudeHeight = () => 0
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < features.length; ++i) {
      const feature = features[i];
      const baseHeight = getBaseHeight(feature, i, features);
      const height = getExtrudeHeight(feature, i, features);
      const polygons = Array();
      switch (feature.geometry.type) {
        case "Polygon":
          polygons.push(feature.geometry.coordinates);
          break;
        case "MultiPolygon":
          for (const polygon of feature.geometry.coordinates) {
            polygons.push(polygon);
          }
          break;
        default:
          throw new Error("Invalid geometry type.");
      }
      for (let k = 0; k < polygons.length; ++k) {
        const polygon = polygons[k];
        const data = flatten(polygon);
        const triangles = earcut(
          data.vertices,
          data.holes,
          data.dimensions
        );
        const vertCount = data.vertices.length / data.dimensions;
        id.push(...Array(vertCount * 2).fill(i + 1));
        let vertices = data.vertices;
        if (projection) {
          const beforeProj = vertices;
          vertices = [];
          for (let j = 0; j < beforeProj.length; j += data.dimensions) {
            const projected = projection.forward([
              beforeProj[j],
              beforeProj[j + 1]
            ]);
            vertices.push(...projected);
          }
        }
        for (let j = 0; j < data.vertices.length; j += data.dimensions) {
          position.push(
            vertices[j] + translate[0],
            height,
            -vertices[j + 1] + translate[1]
          );
          color.push(col.r, col.g, col.b);
        }
        for (let j = 0; j < data.vertices.length; j += data.dimensions) {
          position.push(
            vertices[j] + translate[0],
            baseHeight,
            -vertices[j + 1] + translate[1]
          );
          color.push(col.r, col.g, col.b);
        }
        for (let j = 0; j < vertCount; ++j) {
          const next = (j + 1) % vertCount;
          triangles.push(
            j,
            next,
            next + vertCount,
            j,
            next + vertCount,
            j + vertCount
          );
        }
        featureInfos.push({
          id: i + 1,
          vertCount: vertCount * 2,
          indices: triangles
        });
      }
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};
var GeoJSONEdgeExtrudeGeometry = class extends FeatureGeometry {
  constructor(features, {
    defaultColor = 0,
    projection,
    translate = [0, 0],
    getBaseHeight = () => 0,
    getExtrudeHeight = () => 0
  } = {}) {
    const id = Array();
    const position = Array();
    const color = Array();
    const featureInfos = Array();
    const col = new Color(defaultColor);
    for (let i = 0; i < features.length; ++i) {
      const feature = features[i];
      const baseHeight = getBaseHeight(feature, i, features);
      const height = getExtrudeHeight(feature, i, features);
      const polygons = Array();
      switch (feature.geometry.type) {
        case "Polygon":
          polygons.push(feature.geometry.coordinates);
          break;
        case "MultiPolygon":
          for (const polygon of feature.geometry.coordinates) {
            polygons.push(polygon);
          }
          break;
        default:
          throw new Error("Invalid geometry type.");
      }
      for (let k = 0; k < polygons.length; ++k) {
        const polygon = polygons[k];
        for (let j = 0; j < polygon.length; ++j) {
          const ring = polygon[j];
          id.push(...Array(ring.length * 2).fill(i + 1));
          let vertices = ring.reduce((flat, point) => {
            flat.push(...point);
            return flat;
          }, []);
          if (projection) {
            const beforeProj = vertices;
            vertices = [];
            for (let k2 = 0; k2 < beforeProj.length; k2 += 2) {
              const projected = projection.forward([
                beforeProj[k2],
                beforeProj[k2 + 1]
              ]);
              vertices.push(...projected);
            }
          }
          for (let k2 = 0; k2 < vertices.length; k2 += 2) {
            position.push(
              vertices[k2] + translate[0],
              height,
              -vertices[k2 + 1] + translate[1]
            );
            color.push(col.r, col.g, col.b);
          }
          for (let k2 = 0; k2 < vertices.length; k2 += 2) {
            position.push(
              vertices[k2] + translate[0],
              baseHeight,
              -vertices[k2 + 1] + translate[1]
            );
            color.push(col.r, col.g, col.b);
          }
          const indices = Array();
          for (let k2 = 0; k2 < ring.length - 1; ++k2) {
            indices.push(k2, k2 + 1, k2, k2 + ring.length);
          }
          featureInfos.push({
            id: i + 1,
            vertCount: ring.length * 2,
            indices
          });
        }
      }
    }
    super(
      {
        id: new Float32BufferAttribute(id, 1, false),
        position: new Float32BufferAttribute(position, 3, false),
        color: new Float32BufferAttribute(color, 3, false)
      },
      featureInfos
    );
  }
};

// src/js-tools/three-utils/id-picker.ts
import uniqueId from "lodash-es/uniqueId";
import {
  Color as Color2,
  EventDispatcher,
  Matrix4,
  Scene,
  ShaderMaterial,
  Vector2,
  WebGLRenderTarget as WebGLRenderTarget2
} from "three";

// src/js-tools/three-utils/shaders/id-shader.ts
var IdShader = {
  vertexShader: `
        precision highp float;
        varying float PICKER_ID_OUTPUT;

    #ifndef THREE
        uniform mat4 modelViewMatrix;
        uniform mat4 projectionMatrix;
        attribute vec3 position;
    #endif
    `,
  fragmentShader: `
        precision highp float;

        uniform float PICKER_OBJECT_ID_UNIFORM;
        varying float PICKER_ID_OUTPUT;

        void main() {
            float r = mod(floor(PICKER_ID_OUTPUT / float(0x10000)), 256.0) / 255.0;
            float g = mod(floor(PICKER_ID_OUTPUT / float(0x100)), 256.0) / 255.0;
            float b = mod(PICKER_ID_OUTPUT, 256.0) / 255.0;

            float a1 = mod(floor(PICKER_ID_OUTPUT / float(0x1000000)), 16.0);
            float a2 = mod(PICKER_OBJECT_ID_UNIFORM, 16.0);

            float a = (a1 * 16.0 + a2) / 255.0;

            gl_FragColor = vec4(r, g, b, a);
        }
    `
};

// src/js-tools/three-utils/id-picker.ts
var screenPosMatrix = new Matrix4().identity().multiply(new Matrix4().makeScale(0.5, 0.5, 1)).multiply(new Matrix4().makeTranslation(1, 1, 0));
var screenPosMatrixInv = new Matrix4().identity().multiply(new Matrix4().makeTranslation(-1, -1, 0)).multiply(new Matrix4().makeScale(2, 2, 1));
var ShaderIdOutVarName = uniqueId("vPickerId");
var ShaderObjectIdUniformName = uniqueId("uObjectId");
var IdPicker = class extends EventDispatcher {
  constructor() {
    super();
    this._domElement = null;
    this._mousePosition = new Vector2();
    this._hasClicked = false;
    this._hasDblClicked = false;
    this._disposed = false;
    this._currentId = 0;
    this._currentObject = null;
    this._availableIds = Array(15).fill(0).map((_, i) => i + 1);
    this._scene = new Scene();
    this._objects = [];
    this._objectMap = {};
    this._renderTarget = new WebGLRenderTarget2(256, 256);
    this._readBuffer = new Uint8Array(
      this._renderTarget.width * this._renderTarget.height * 4
    );
    this._onMouseMove = this._onMouseMove.bind(this);
    this._onClick = this._onClick.bind(this);
    this._onDblClick = this._onDblClick.bind(this);
  }
  setDomElement(elem) {
    if (this._domElement) {
      this._domElement.removeEventListener(
        "mousemove",
        this._onMouseMove
      );
      this._domElement.removeEventListener("click", this._onClick);
      this._domElement.removeEventListener("dblclick", this._onDblClick);
      this._domElement = null;
    }
    if (elem) {
      elem.addEventListener("mousemove", this._onMouseMove);
      elem.addEventListener("click", this._onClick);
      elem.addEventListener("dblclick", this._onDblClick);
      this._domElement = elem;
    }
  }
  triggerEvent(type, e) {
    switch (type) {
      case "mouseover":
        this._onMouseMove(e);
        break;
      case "click":
        this._onClick(e);
        break;
      case "dblclick":
        this._onDblClick(e);
        break;
    }
  }
  add(target, {
    uniforms,
    vertexSource = "",
    idAttrName = "id",
    withObject = true
  } = {}) {
    let id;
    if (withObject) {
      const nextId = this._availableIds.pop();
      if (!nextId) {
        throw new Error("IdPicker can only add up to 16 objects.");
      }
      id = nextId;
    } else {
      id = 0;
    }
    if (!vertexSource) {
      vertexSource = `
                attribute float ${idAttrName};

                void main() {
                    PICKER_ID_OUTPUT = ${idAttrName};
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                }
            `;
    }
    const material = new ShaderMaterial({
      defines: {
        THREE: "",
        PICKER_ID_OUTPUT: ShaderIdOutVarName,
        PICKER_OBJECT_ID_UNIFORM: ShaderObjectIdUniformName
      },
      uniforms: {
        ...uniforms,
        [ShaderObjectIdUniformName]: {
          value: id
        }
      },
      vertexShader: IdShader.vertexShader + vertexSource,
      fragmentShader: IdShader.fragmentShader
    });
    this._objects.push({
      id,
      material,
      object: target
    });
    if (id) {
      this._objectMap[id] = {
        id,
        material,
        object: target
      };
    }
  }
  remove(target) {
    const idx = this._objects.findIndex(({ object }) => object === target);
    if (idx >= 0) {
      const { id, material } = this._objects[idx];
      this._objects.splice(idx, 1);
      material.dispose();
      if (id > 0) {
        this._availableIds.push(id);
      }
      if (id) {
        delete this._objectMap[id];
      }
    }
  }
  update(renderer, camera) {
    const { x, y } = this._mousePosition;
    if (this._disposed || 0 > x || x > 1 || 0 > y || y > 1) {
      this._updateId({
        id: 0,
        object: null
      });
      this._processEvents({ inBounds: false });
    } else {
      const savedRenderTarget = renderer.getRenderTarget();
      const savedClearColor = renderer.getClearColor(new Color2());
      const unModCamera = this._modifyCamera(renderer, camera);
      renderer.setRenderTarget(this._renderTarget);
      renderer.setClearColor(new Color2().setRGB(0, 0, 0), 0);
      renderer.clear();
      for (const { object, material } of this._objects) {
        const savedParent = object.parent;
        object.removeFromParent();
        this._scene.add(object);
        this._scene.overrideMaterial = material;
        renderer.render(this._scene, camera);
        this._scene.remove(object);
        if (savedParent) savedParent.add(object);
      }
      renderer.setClearColor(savedClearColor);
      renderer.setRenderTarget(savedRenderTarget);
      unModCamera();
      renderer.readRenderTargetPixels(
        this._renderTarget,
        0,
        0,
        this._renderTarget.width,
        this._renderTarget.height,
        this._readBuffer
      );
      const centerIndex = Math.floor(
        (Math.floor(this._renderTarget.height / 2) + 0.5) * this._renderTarget.width
      ) * 4;
      const pixel = this._readBuffer.slice(centerIndex, centerIndex + 4);
      const objectId = pixel[3] & 15;
      const id = (pixel[3] >> 4 << 24) + (pixel[0] << 16) + (pixel[1] << 8) + pixel[2];
      this._updateId({
        id,
        object: this._objectMap[objectId]?.object
      });
      this._processEvents({ inBounds: true });
    }
  }
  _onMouseMove(e) {
    const { left, bottom, width, height } = e.currentTarget.getBoundingClientRect();
    this._mousePosition.set(
      (e.clientX - left) / width,
      (bottom - e.clientY) / height
    );
  }
  _onClick(e) {
    this._onMouseMove(e);
    this._hasClicked = true;
  }
  _onDblClick(e) {
    this._onMouseMove(e);
    this._hasDblClicked = true;
  }
  _modifyCamera(renderer, camera) {
    const savedProjectionMatrix = camera.projectionMatrix.clone();
    camera.projectionMatrix = new Matrix4().identity().multiply(screenPosMatrixInv).multiply(
      new Matrix4().makeScale(
        renderer.domElement.width / this._renderTarget.width,
        renderer.domElement.height / this._renderTarget.height,
        1
      )
    ).multiply(
      new Matrix4().makeTranslation(
        -(this._mousePosition.x - this._renderTarget.width / renderer.domElement.width / 2),
        -(this._mousePosition.y - this._renderTarget.height / renderer.domElement.height / 2),
        0
      )
    ).multiply(screenPosMatrix).multiply(savedProjectionMatrix);
    return () => {
      camera.projectionMatrix = savedProjectionMatrix;
    };
  }
  _updateId({
    id,
    object
  }) {
    if (id !== this._currentId || object !== this._currentObject) {
      if (this._currentId > 0) {
        this.dispatchEvent({
          type: "mouseleave",
          id: this._currentId,
          object: this._currentObject
        });
      }
      this._currentId = id;
      this._currentObject = object;
      if (this._currentId > 0) {
        this.dispatchEvent({
          type: "mouseenter",
          id: this._currentId,
          object: this._currentObject
        });
      }
    }
  }
  _processEvents({ inBounds }) {
    if (inBounds) {
      if (this._currentId > 0) {
        this.dispatchEvent({
          type: "mouseover",
          id: this._currentId,
          object: this._currentObject
        });
      }
      if (this._hasClicked) {
        this._hasClicked = false;
        this.dispatchEvent({
          type: "click",
          id: this._currentId,
          object: this._currentObject
        });
      }
      if (this._hasDblClicked) {
        this._hasDblClicked = false;
        this.dispatchEvent({
          type: "dblclick",
          id: this._currentId,
          object: this._currentObject
        });
      }
    } else {
      this._hasClicked = false;
      this._hasDblClicked = false;
    }
  }
  dispose() {
    if (!this._disposed) {
      this.setDomElement(null);
      this._disposed = true;
      this._renderTarget.dispose();
      this._objects.forEach(({ material }) => {
        material.dispose();
      });
    } else {
      throw new Error("Object has already been disposed previously.");
    }
  }
};

// src/js-tools/three-utils/instanced.ts
import {
  InstancedBufferAttribute,
  InstancedBufferGeometry,
  ShaderMaterial as ShaderMaterial2
} from "three";

// src/js-tools/three-utils/shaders/instanced.ts
var Instanced = {
  vertexShader: `
        precision highp float;

        #ifndef THREE 
        uniform mat4 projectionMatrix;
        attribute vec3 position;
        #endif

        attribute mat4 instanceMatrix;

        void main() {
            gl_Position = projectionMatrix * instanceMatrix * vec4(position, 1.0);
        }
    `,
  fragmentShader: `
        precision highp float;

        uniform vec3 color;
        uniform float opacity;

        void main() {
            gl_FragColor = vec4(color, opacity);
            gl_FragColor = linearToOutputTexel(gl_FragColor);
        }
    `
};

// src/js-tools/three-utils/instanced.ts
var InstancedGeometry = class extends InstancedBufferGeometry {
  constructor(baseGeometry, instanceCount) {
    super();
    this.setAttribute("position", baseGeometry.getAttribute("position"));
    this.setIndex(baseGeometry.index);
    this.instanceCount = instanceCount;
    this.computeBoundingBox();
    this.computeBoundingSphere();
    const instanceMatrix = new Float32Array(instanceCount * 16);
    this.setAttribute(
      "instanceMatrix",
      new InstancedBufferAttribute(instanceMatrix, 16, false)
    );
  }
  setInstanceMatrix(i, mat) {
    const attr = this.getAttribute("instanceMatrix");
    mat.toArray(attr.array, i * 16);
    attr.needsUpdate = true;
  }
};
var StandardInstancedMaterial = class extends ShaderMaterial2 {
  constructor(params) {
    super({
      vertexShader: Instanced.vertexShader,
      fragmentShader: Instanced.fragmentShader,
      ...params,
      defines: {
        THREE: "",
        ...params?.defines
      }
    });
  }
};

// src/js-tools/three-utils/utils.ts
function mergeIndexArrays(arrays, offsets) {
  if (arrays.length !== offsets.length) {
    throw new Error(
      "The number of buffer attributes must match the number of offsets."
    );
  }
  let length = 0;
  for (let i = 0; i < arrays.length; ++i) {
    length += arrays[i].length;
  }
  const mergedArray = new Uint32Array(length);
  let offset = 0;
  let arrayOffset = 0;
  for (let i = 0; i < arrays.length; ++i) {
    const array = arrays[i];
    for (let j = 0; j < array.length; ++j) {
      mergedArray[arrayOffset + j] = offset + array[j];
    }
    offset += offsets[i];
    arrayOffset += array.length;
  }
  return mergedArray;
}
function mergeTypedArraysInternal(arrays, output) {
  let arrayOffset = 0;
  for (let i = 0; i < arrays.length; ++i) {
    const array = arrays[i];
    output.set(array, arrayOffset);
    arrayOffset += array.length;
  }
}
function mergeTypedArrays(arrays) {
  if (arrays.length === 0) {
    throw new Error("Must have at least one array.");
  }
  let length = 0;
  for (let i = 0; i < arrays.length; ++i) {
    length += arrays[i].length;
  }
  let mergedArray;
  const a = arrays[0];
  if (a instanceof Float32Array) {
    mergedArray = new Float32Array(length);
  } else if (a instanceof Float64Array) {
    mergedArray = new Float64Array(length);
  } else if (a instanceof Int8Array) {
    mergedArray = new Int8Array(length);
  } else if (a instanceof Int16Array) {
    mergedArray = new Int16Array(length);
  } else if (a instanceof Int32Array) {
    mergedArray = new Int32Array(length);
  } else if (a instanceof Uint8Array) {
    mergedArray = new Uint8Array(length);
  } else if (a instanceof Uint8ClampedArray) {
    mergedArray = new Uint8ClampedArray(length);
  } else if (a instanceof Uint16Array) {
    mergedArray = new Uint16Array(length);
  } else if (a instanceof Uint32Array) {
    mergedArray = new Uint32Array(length);
  }
  if (mergedArray) {
    mergeTypedArraysInternal(arrays, mergedArray);
    return mergedArray;
  }
}
export {
  compute_program_default as ComputeProgram,
  compute_render_target_default as ComputeRenderTarget,
  FeatureGeometry,
  GeoJSONEdgeExtrudeGeometry,
  GeoJSONEdgeGeometry,
  GeoJSONFillExtrudeGeometry,
  GeoJSONFillGeometry,
  IdPicker,
  InstancedGeometry,
  LineStringGeometry,
  MultiPolygonEdgeGeometry,
  MultiPolygonGeometry,
  PolygonEdgeGeometry,
  PolygonGeometry,
  ShaderIdOutVarName,
  StandardInstancedMaterial,
  SubsetGeometry,
  mergeIndexArrays,
  mergeTypedArrays
};
