Mapbox或Maplibre加载风场(格式为风场格式数据)

1. Mapbox或Maplibre加载风场

所需的文件 mapbox-wind.js、wind-core.js、wind-gl-core.js 放在同一目录下

mapbox-wind.js

// mapbox-wind.js
import { WindCore, defaultOptions, isArray, formatData, assign } from './wind-core';
export { Field } from './wind-core';
import * as maplibregl from 'maplibre-gl';
import { ScalarFill as ScalarFill$1, getEye, fp64LowPart, WindParticles } from './wind-gl-core';

function removeDomNode(node) {
  if (!node) {
    return null;
  }
  if (node.parentNode) {
    node.parentNode.removeChild(node);
  }
  return node;
}
class Overlay {
  constructor(id, options = {}) {
    if (!id) {
      throw Error("layer id must be specified");
    }
    this.id = id;
    this.options = options;
    this.canvas = null;
    this.canvas2 = null;
    this.devicePixelRatio = this.options.devicePixelRatio || (window.devicePixelRatio || window.screen.deviceXDPI / window.screen.logicalXDPI);
    this.render = this.render.bind(this);
    this.type = "custom";
    this.renderingMode = "2d";
  }
  onAdd(map) {
    this.setMap(map);
    this.canvas = this.initialize();
    if (this.options.doubleBuffer) {
      this.canvas2 = this.initialize();
    }
  }
  resizeCanvas(canvas) {
    const mapboxCanvas = this.map.getCanvas();
    const { width, height } = this.map.transform;
    const pixel = this.devicePixelRatio;
    canvas.width = width * pixel;
    canvas.height = height * pixel;
    canvas.style.width = mapboxCanvas.style.width;
    canvas.style.height = mapboxCanvas.style.height;
  }
  initialize() {
    const canvasContainer = this.map.getCanvasContainer();
    const mapboxCanvas = this.map.getCanvas();
    const canvasOverlay = document.createElement("canvas");
    const { width, height } = this.map.transform;
    const pixel = this.devicePixelRatio;
    canvasOverlay.width = width * pixel;
    canvasOverlay.height = height * pixel;
    canvasOverlay.style.position = "absolute";
    canvasOverlay.className = "mapbox-overlay-canvas";
    canvasOverlay.style.width = mapboxCanvas.style.width;
    canvasOverlay.style.height = mapboxCanvas.style.height;
    canvasContainer.appendChild(canvasOverlay);
    return canvasOverlay;
  }
  render() {
  }
  project(coordinates) {
    if (this.map !== void 0) {
      const lnglat = this.map.project(new maplibregl.LngLat(coordinates[0], coordinates[1]));
      const x = lnglat.x;
      const y = lnglat.y;
      return [
        x * this.devicePixelRatio,
        y * this.devicePixelRatio
      ];
    }
    return coordinates;
  }
  unproject(pixel) {
    if (this.map !== void 0) {
      const lnglat = this.map.unproject(new maplibregl.Point(pixel[0], pixel[1]));
      return [lnglat.lng, lnglat.lat];
    }
    return pixel;
  }
  intersectsCoordinate(coordinate) {
    var _a, _b;
    const bounds = this.map.getBounds();
    const latRange = (_b = (_a = this.map) == null ? void 0 : _a.transform) == null ? void 0 : _b.latRange;
    if (latRange) {
      if (coordinate[1] > latRange[1] || coordinate[1] < latRange[0])
        return false;
    }
    return bounds.contains(new maplibregl.LngLat(coordinate[0], coordinate[1]));
  }
  clear() {
    if (this.canvas) {
      const ctx = this.canvas.getContext("2d");
      ctx && ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }
    if (this.canvas2) {
      const ctx = this.canvas2.getContext("2d");
      ctx && ctx.clearRect(0, 0, this.canvas2.width, this.canvas2.height);
    }
  }
  setMap(map) {
    this.map = map;
    return this;
  }
  getMap() {
    return this.map;
  }
  addTo(map) {
    this.onAdd(map);
  }
  remove() {
    if (this.canvas) {
      removeDomNode(this.canvas);
      this.canvas = null;
    }
    if (this.canvas2) {
      removeDomNode(this.canvas2);
      this.canvas2 = null;
    }
  }
}

function getCoords$1([lng, lat]) {
  const mercatorCoordinate = maplibregl.MercatorCoordinate.fromLngLat({
    lng,
    lat
  });
  return [mercatorCoordinate.x, mercatorCoordinate.y];
}
class ScalarFill {
  constructor(id, data, options) {
    this.id = id;
    this.type = "custom";
    this.renderingMode = "3d";
    this.options = {
      ...options || {}
    };
    this.data = data;
    this.handleZoom = this.handleZoom.bind(this);
  }
  handleZoom() {
    if (this.scalarFill) {
      this.scalarFill.handleZoom();
    }
  }
  initialize() {
    if (!this.scalarFill && this.gl) {
      this.scalarFill = new ScalarFill$1(this.gl, {
        opacity: this.options.opacity,
        renderForm: this.options.renderForm,
        styleSpec: this.options.styleSpec,
        displayRange: this.options.displayRange,
        mappingRange: this.options.mappingRange,
        widthSegments: this.options.widthSegments,
        heightSegments: this.options.heightSegments,
        wireframe: this.options.wireframe,
        createPlaneBuffer: this.options.createPlaneBuffer,
        getZoom: () => this.map.getZoom(),
        triggerRepaint: () => {
          this.map.triggerRepaint();
        },
        injectShaderModules: {
          "#modules-transformZ": `
const float MATH_PI = 3.141592653589793;
const float earthRadius = 6371008.8;
const float earthCircumfrence = 2.0 * MATH_PI * earthRadius;

            float latFromMercatorY(float y) {
  float y2 = 180.0 - y * 360.0;
  return 360.0 / MATH_PI * atan(exp(y2 * MATH_PI / 180.0)) - 90.0;
}

float circumferenceAtLatitude(float latitude) {
  return earthCircumfrence * cos(latitude * MATH_PI / 180.0);
}

float mercatorScale(float lat) {
  return 1.0 / cos(lat * MATH_PI / 180.0);
}

float transformZ(float value, vec3 pos) {
  float mercatorY = pos.y;
  //  float scale = circumferenceAtLatitude(latFromMercatorY(mercatorY));
  float scale = earthCircumfrence * mercatorScale(latFromMercatorY(mercatorY));

  return value / scale;
}
          `,
          "#modules-project": `
gl_Position = u_matrix * vec4(pos.xy + vec2(u_offset, 0.0), pos.z + z, pos.w);
gl_Position.w += u_cameraEye.w;
    `
        }
      });
      this.scalarFill.getMercatorCoordinate = getCoords$1;
      this.map.on("zoom", this.handleZoom);
    }
    if (this.data) {
      this.setData(this.data);
    }
  }
  updateOptions(options) {
    this.options = {
      ...this.options,
      ...options || {}
    };
    if (this.scalarFill) {
      this.scalarFill.updateOptions(options);
    }
  }
  onAdd(map, gl) {
    this.gl = gl;
    this.map = map;
    if (this.map) {
      this.initialize();
    }
  }
  setData(data) {
    return new Promise((resolve, reject) => {
      this.data = data;
      if (this.data && this.scalarFill) {
        this.scalarFill.setData(this.data, (status) => {
          if (status) {
            resolve(true);
          } else {
            reject(false);
          }
        });
      } else {
        resolve(false);
      }
    });
  }
  onRemove(map) {
    if (this.scalarFill) {
      this.scalarFill.destroyed();
      this.scalarFill = null;
    }
    delete this.gl;
    delete this.map;
    map.off("zoom", this.handleZoom);
  }
  getWrappedWorlds() {
    const result = [0];
    if (this.options.wrapX) {
      const { width, height } = this.map.transform;
      const utl = this.map.transform.pointCoordinate(new maplibregl.Point(0, 0));
      const utr = this.map.transform.pointCoordinate(
        new maplibregl.Point(width, 0)
      );
      const ubl = this.map.transform.pointCoordinate(
        new maplibregl.Point(width, height)
      );
      const ubr = this.map.transform.pointCoordinate(
        new maplibregl.Point(0, height)
      );
      const w0 = Math.floor(Math.min(utl.x, utr.x, ubl.x, ubr.x));
      const w1 = Math.floor(Math.max(utl.x, utr.x, ubl.x, ubr.x));
      const extraWorldCopy = 1;
      for (let w = w0 - extraWorldCopy; w <= w1 + extraWorldCopy; w++) {
        if (w === 0) {
          continue;
        }
        result.push(w);
      }
    }
    return result;
  }
  render(gl, matrix) {
    const cameraEye = getEye(matrix);
    const cameraEye64Low = cameraEye.map((item) => fp64LowPart(item));
    if (this.data && this.scalarFill) {
      const worlds = this.getWrappedWorlds();
      for (let i = 0; i < worlds.length; i++) {
        this.scalarFill.render(matrix, worlds[i], {
          cameraEye,
          cameraEye64Low
        });
      }
    }
  }
}

function getCoords([lng, lat]) {
  const mercatorCoordinate = maplibregl.MercatorCoordinate.fromLngLat({
    lng,
    lat
  });
  return [mercatorCoordinate.x, mercatorCoordinate.y];
}
class Particles {
  constructor(id, data, options) {
    this.id = id;
    this.type = "custom";
    this.renderingMode = "2d";
    this.options = {
      ...options || {}
    };
    this.data = data;
    this.resize = this.resize.bind(this);
    this.handleZoom = this.handleZoom.bind(this);
    this.handleMovestart = this.handleMovestart.bind(this);
    this.handleMoveend = this.handleMoveend.bind(this);
  }
  updateOptions(options) {
    this.options = {
      ...this.options,
      ...options || {}
    };
    if (this.layer) {
      this.layer.updateOptions(options);
    }
  }
  handleZoom() {
    if (this.layer) {
      this.layer.handleZoom();
    }
  }
  resize() {
    if (this.layer) {
      this.layer.resize();
    }
  }
  handleMovestart() {
    if (this.layer) {
      this.layer.handleMovestart();
    }
  }
  handleMoveend() {
    if (this.layer) {
      this.layer.handleMoveend();
    }
  }
  initialize() {
    if (!this.layer && this.gl) {
      this.layer = new WindParticles(this.gl, {
        getZoom: () => this.map.getZoom(),
        triggerRepaint: () => {
          this.map.triggerRepaint();
        },
        getExtent: () => {
          const bounds = this.map.getBounds().toArray();
          let xmin = bounds[0][0];
          const ymin = bounds[0][1];
          let xmax = bounds[1][0];
          const ymax = bounds[1][1];
          const worlds = this.getWrappedWorlds();
          if (worlds.length > 1) {
            xmin = -180;
            xmax = 180;
          } else {
            if (xmin < -180) {
              xmin = -180;
            }
            if (xmax > 180) {
              xmax = 180;
            }
          }
          const p0 = maplibregl.MercatorCoordinate.fromLngLat(
            new maplibregl.LngLat(xmin, ymax)
          );
          const p1 = maplibregl.MercatorCoordinate.fromLngLat(
            new maplibregl.LngLat(xmax, ymin)
          );
          return [p0.x, p0.y, p1.x, p1.y];
        },
        getSize: () => {
          return [
            this.map.transform.size.x,
            this.map.transform.size.y
          ];
        },
        interacting: () => {
          return !this.map.painter.options.moving && !this.map.painter.options.rotating && !this.map.painter.options.zooming;
        },
        getWorlds: () => this.getWrappedWorlds(),
        ...this.options
      });
      this.layer.getMercatorCoordinate = getCoords;
      this.map.on("zoom", this.handleZoom);
      this.map.on("movestart", this.handleMovestart);
      this.map.on("resize", this.resize);
      this.map.on("moveend", this.handleMoveend);
    }
    if (this.data) {
      this.setData(this.data);
    }
  }
  onAdd(map, gl) {
    this.gl = gl;
    this.map = map;
    if (this.map) {
      this.initialize();
    }
  }
  setData(data) {
    return new Promise((resolve, reject) => {
      this.data = data;
      if (this.data && this.layer) {
        this.layer.setData(this.data, (status) => {
          if (status) {
            resolve(true);
          } else {
            reject(false);
          }
        });
      } else {
        resolve(false);
      }
    });
  }
  onRemove(map) {
    if (this.layer) {
      this.layer.destroyed();
      this.layer = null;
    }
    map.off("zoom", this.handleZoom);
    map.off("movestart", this.handleMovestart);
    map.off("resize", this.resize);
    map.off("moveend", this.handleMoveend);
    delete this.gl;
    delete this.map;
  }
  getWrappedWorlds() {
    const result = [0];
    if (this.options.wrapX) {
      const { width, height } = this.map.transform;
      const utl = this.map.transform.pointCoordinate(new maplibregl.Point(0, 0));
      const utr = this.map.transform.pointCoordinate(
        new maplibregl.Point(width, 0)
      );
      const ubl = this.map.transform.pointCoordinate(
        new maplibregl.Point(width, height)
      );
      const ubr = this.map.transform.pointCoordinate(
        new maplibregl.Point(0, height)
      );
      const w0 = Math.floor(Math.min(utl.x, utr.x, ubl.x, ubr.x));
      const w1 = Math.floor(Math.max(utl.x, utr.x, ubl.x, ubr.x));
      const extraWorldCopy = 0;
      for (let w = w0 - extraWorldCopy; w <= w1 + extraWorldCopy; w++) {
        if (w === 0) {
          continue;
        }
        result.push(w);
      }
    }
    return result;
  }
  prerender(gl, matrix) {
    if (this.data && this.layer) {
      this.layer.prerender(matrix);
    }
  }
  render(gl, matrix) {
    if (this.data && this.layer) {
      this.layer.render(matrix);
    }
  }
}

const defaultConfig = {
  doubleBuffer: false,
  windOptions: defaultOptions
};
class WindLayer extends Overlay {
  constructor(id, data, options = {}) {
    super(id, { ...defaultConfig, ...options });
    this.pickWindOptions();
    if (data) {
      this.setData(data, options.fieldOptions);
    }
    this.stop = this.stop.bind(this);
    this.render = this.render.bind(this);
    this.handleResize = this.handleResize.bind(this);
  }
  onAdd(map) {
    super.onAdd(map);
    if (!this.map) {
      throw new Error("map is null");
    }
    if (this.canvas !== null) {
      this.render();
      this.registerEvents();
    }
  }
  handleResize() {
    if (this.canvas) {
      this.resizeCanvas(this.canvas);
    }
    this.render();
  }
  registerEvents() {
    this.map.on("resize", this.handleResize);
    this.map.on("movestart", this.stop);
    this.map.on("moveend", this.render);
    this.map.on("zoomstart", this.stop);
    this.map.on("zoomend", this.render);
    this.map.on("rotatestart", this.stop);
    this.map.on("rotateend", this.render);
    this.map.on("pitchstart", this.stop);
    this.map.on("pitchend", this.render);
  }
  unregisterEvents() {
    this.map.off("resize", this.handleResize);
    this.map.off("movestart", this.stop);
    this.map.off("moveend", this.render);
    this.map.off("zoomstart", this.stop);
    this.map.off("zoomend", this.render);
    this.map.off("rotatestart", this.stop);
    this.map.off("rotateend", this.render);
    this.map.off("pitchstart", this.stop);
    this.map.off("pitchend", this.render);
  }
  stop() {
    if (this.wind) {
      this.wind.clearCanvas();
    }
  }
  render() {
    if (!this.map) {
      return;
    }
    const opt = this.getWindOptions();
    if (!this.wind && this.map && this.canvas !== null) {
      const ctx = this.canvas.getContext("2d");
      if (!ctx) {
        console.error("create canvas context failed");
        return;
      }
      const data = this.getData();
      this.wind = new WindCore(ctx, opt, data);
      this.wind.project = this.project.bind(this);
      this.wind.unproject = this.unproject.bind(this);
      this.wind.intersectsCoordinate = this.intersectsCoordinate.bind(this);
      this.wind.postrender = () => {
      };
    }
    this.wind.prerender();
    this.wind.render();
  }
  remove() {
    super.remove();
    if (this.wind) {
      this.wind.stop();
    }
    this.unregisterEvents();
  }
  pickWindOptions() {
    Object.keys(defaultOptions).forEach((key) => {
      if (this.options && key in this.options) {
        if (this.options.windOptions === void 0) {
          this.options.windOptions = {};
        }
        this.options.windOptions[key] = this.options[key];
      }
    });
  }
  getData() {
    return this.field;
  }
  setData(data, options = {}) {
    var _a;
    if (data && data.checkFields && data.checkFields()) {
      this.field = data;
    } else if (isArray(data)) {
      this.field = formatData(data, options);
    } else {
      console.error("Illegal data");
    }
    if (this.field) {
      (_a = this == null ? void 0 : this.wind) == null ? void 0 : _a.updateData(this.field);
    }
    return this;
  }
  setWindOptions(options) {
    const beforeOptions = this.options.windOptions || {};
    this.options = assign(this.options, {
      windOptions: assign(beforeOptions, options || {})
    });
    if (this.wind) {
      const windOptions = this.options.windOptions;
      this.wind.setOptions(windOptions);
      this.wind.prerender();
    }
  }
  getWindOptions() {
    return this.options.windOptions || {};
  }
}

export { Particles, ScalarFill, WindLayer, WindLayer as default };
//# sourceMappingURL=mapbox-wind.esm.js.map

wind-core.js

// wind-core.js
const hasOwnProperty = Object.prototype.hasOwnProperty;
const symToStringTag = typeof Symbol !== "undefined" ? Symbol.toStringTag : void 0;
function baseGetTag(value) {
  if (value === null) {
    return value === void 0 ? "[object Undefined]" : "[object Null]";
  }
  if (!(symToStringTag && symToStringTag in Object(value))) {
    return toString.call(value);
  }
  const isOwn = hasOwnProperty.call(value, symToStringTag);
  const tag = value[symToStringTag];
  let unmasked = false;
  try {
    value[symToStringTag] = void 0;
    unmasked = true;
  } catch (e) {
  }
  const result = Object.prototype.toString.call(value);
  if (unmasked) {
    if (isOwn) {
      value[symToStringTag] = tag;
    } else {
      delete value[symToStringTag];
    }
  }
  return result;
}
function TypeOf(value) {
  return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}
function isFunction(value) {
  if (!isObject(value)) {
    return false;
  }
  const tag = baseGetTag(value);
  return tag === "[object Function]" || tag === "[object AsyncFunction]" || tag === "[object GeneratorFunction]" || tag === "[object Proxy]";
}
function isObject(value) {
  const type = typeof value;
  return value !== null && (type === "object" || type === "function");
}
function isDate(val) {
  return Object.prototype.toString.call(val) === "[object Date]";
}
function isArrayBuffer(val) {
  return Object.prototype.toString.call(val) === "[object ArrayBuffer]";
}
function isString(value) {
  if (value == null) {
    return false;
  }
  return typeof value === "string" || value.constructor !== null && value.constructor === String;
}
function isNumber(value) {
  return Object.prototype.toString.call(value) === "[object Number]" && !isNaN(value);
}
function isEmpty(object) {
  let property;
  for (property in object) {
    return false;
  }
  return !property;
}
function isNull(obj) {
  return obj == null;
}
function isArray(arr) {
  return Array.isArray(arr);
}
function assign(target, ...sources) {
  return Object.assign(target, ...sources);
}
function warnLog(msg, n) {
  console.warn(`${n || "wind-layer"}: ${msg}`);
}
const warnings = {};
function warnOnce(namespaces, msg) {
  if (!warnings[msg]) {
    warnLog(msg, namespaces);
    warnings[msg] = true;
  }
}
function floorMod(a, n) {
  return a - n * Math.floor(a / n);
}
function isValide(val) {
  return val !== void 0 && val !== null && !isNaN(val);
}
function formatData(data, options = {}) {
  let uComp = void 0;
  let vComp = void 0;
  data.forEach(function(record) {
    switch (record.header.parameterCategory + "," + record.header.parameterNumber) {
      case "1,2":
      case "2,2":
        uComp = record;
        break;
      case "1,3":
      case "2,3":
        vComp = record;
        break;
    }
  });
  if (!vComp || !uComp) {
    return void 0;
  }
  const header = uComp.header;
  const vectorField = new Field({
    xmin: header.lo1,
    ymin: header.la1,
    xmax: header.lo2,
    ymax: header.la2,
    deltaX: header.dx,
    deltaY: header.dy,
    cols: header.nx,
    rows: header.ny,
    us: uComp.data,
    vs: vComp.data,
    ...options
  });
  return vectorField;
}
function createCanvas(width, height, retina, Canvas) {
  if (typeof document !== "undefined") {
    const canvas = document.createElement("canvas");
    canvas.width = width * retina;
    canvas.height = height * retina;
    return canvas;
  } else {
    return new Canvas(width * retina, height * retina);
  }
}
function removeDomNode(node) {
  if (!node) {
    return null;
  }
  if (node.parentNode) {
    node.parentNode.removeChild(node);
  }
  return node;
}
const keyword = /(\D+)/;
const hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i;
const rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/;
const colorNames = {
  aliceblue: [240, 248, 255],
  antiquewhite: [250, 235, 215],
  aqua: [0, 255, 255],
  aquamarine: [127, 255, 212],
  azure: [240, 255, 255],
  beige: [245, 245, 220],
  bisque: [255, 228, 196],
  black: [0, 0, 0],
  blanchedalmond: [255, 235, 205],
  blue: [0, 0, 255],
  blueviolet: [138, 43, 226],
  brown: [165, 42, 42],
  burlywood: [222, 184, 135],
  cadetblue: [95, 158, 160],
  chartreuse: [127, 255, 0],
  chocolate: [210, 105, 30],
  coral: [255, 127, 80],
  cornflowerblue: [100, 149, 237],
  cornsilk: [255, 248, 220],
  crimson: [220, 20, 60],
  cyan: [0, 255, 255],
  darkblue: [0, 0, 139],
  darkcyan: [0, 139, 139],
  darkgoldenrod: [184, 134, 11],
  darkgray: [169, 169, 169],
  darkgreen: [0, 100, 0],
  darkgrey: [169, 169, 169],
  darkkhaki: [189, 183, 107],
  darkmagenta: [139, 0, 139],
  darkolivegreen: [85, 107, 47],
  darkorange: [255, 140, 0],
  darkorchid: [153, 50, 204],
  darkred: [139, 0, 0],
  darksalmon: [233, 150, 122],
  darkseagreen: [143, 188, 143],
  darkslateblue: [72, 61, 139],
  darkslategray: [47, 79, 79],
  darkslategrey: [47, 79, 79],
  darkturquoise: [0, 206, 209],
  darkviolet: [148, 0, 211],
  deeppink: [255, 20, 147],
  deepskyblue: [0, 191, 255],
  dimgray: [105, 105, 105],
  dimgrey: [105, 105, 105],
  dodgerblue: [30, 144, 255],
  firebrick: [178, 34, 34],
  floralwhite: [255, 250, 240],
  forestgreen: [34, 139, 34],
  fuchsia: [255, 0, 255],
  gainsboro: [220, 220, 220],
  ghostwhite: [248, 248, 255],
  gold: [255, 215, 0],
  goldenrod: [218, 165, 32],
  gray: [128, 128, 128],
  green: [0, 128, 0],
  greenyellow: [173, 255, 47],
  grey: [128, 128, 128],
  honeydew: [240, 255, 240],
  hotpink: [255, 105, 180],
  indianred: [205, 92, 92],
  indigo: [75, 0, 130],
  ivory: [255, 255, 240],
  khaki: [240, 230, 140],
  lavender: [230, 230, 250],
  lavenderblush: [255, 240, 245],
  lawngreen: [124, 252, 0],
  lemonchiffon: [255, 250, 205],
  lightblue: [173, 216, 230],
  lightcoral: [240, 128, 128],
  lightcyan: [224, 255, 255],
  lightgoldenrodyellow: [250, 250, 210],
  lightgray: [211, 211, 211],
  lightgreen: [144, 238, 144],
  lightgrey: [211, 211, 211],
  lightpink: [255, 182, 193],
  lightsalmon: [255, 160, 122],
  lightseagreen: [32, 178, 170],
  lightskyblue: [135, 206, 250],
  lightslategray: [119, 136, 153],
  lightslategrey: [119, 136, 153],
  lightsteelblue: [176, 196, 222],
  lightyellow: [255, 255, 224],
  lime: [0, 255, 0],
  limegreen: [50, 205, 50],
  linen: [250, 240, 230],
  magenta: [255, 0, 255],
  maroon: [128, 0, 0],
  mediumaquamarine: [102, 205, 170],
  mediumblue: [0, 0, 205],
  mediumorchid: [186, 85, 211],
  mediumpurple: [147, 112, 219],
  mediumseagreen: [60, 179, 113],
  mediumslateblue: [123, 104, 238],
  mediumspringgreen: [0, 250, 154],
  mediumturquoise: [72, 209, 204],
  mediumvioletred: [199, 21, 133],
  midnightblue: [25, 25, 112],
  mintcream: [245, 255, 250],
  mistyrose: [255, 228, 225],
  moccasin: [255, 228, 181],
  navajowhite: [255, 222, 173],
  navy: [0, 0, 128],
  oldlace: [253, 245, 230],
  olive: [128, 128, 0],
  olivedrab: [107, 142, 35],
  orange: [255, 165, 0],
  orangered: [255, 69, 0],
  orchid: [218, 112, 214],
  palegoldenrod: [238, 232, 170],
  palegreen: [152, 251, 152],
  paleturquoise: [175, 238, 238],
  palevioletred: [219, 112, 147],
  papayawhip: [255, 239, 213],
  peachpuff: [255, 218, 185],
  peru: [205, 133, 63],
  pink: [255, 192, 203],
  plum: [221, 160, 221],
  powderblue: [176, 224, 230],
  purple: [128, 0, 128],
  rebeccapurple: [102, 51, 153],
  red: [255, 0, 0],
  rosybrown: [188, 143, 143],
  royalblue: [65, 105, 225],
  saddlebrown: [139, 69, 19],
  salmon: [250, 128, 114],
  sandybrown: [244, 164, 96],
  seagreen: [46, 139, 87],
  seashell: [255, 245, 238],
  sienna: [160, 82, 45],
  silver: [192, 192, 192],
  skyblue: [135, 206, 235],
  slateblue: [106, 90, 205],
  slategray: [112, 128, 144],
  slategrey: [112, 128, 144],
  snow: [255, 250, 250],
  springgreen: [0, 255, 127],
  steelblue: [70, 130, 180],
  tan: [210, 180, 140],
  teal: [0, 128, 128],
  thistle: [216, 191, 216],
  tomato: [255, 99, 71],
  turquoise: [64, 224, 208],
  violet: [238, 130, 238],
  wheat: [245, 222, 179],
  white: [255, 255, 255],
  whitesmoke: [245, 245, 245],
  yellow: [255, 255, 0],
  yellowgreen: [154, 205, 50]
};
function getColor(string) {
  let rgb = [];
  if (string.match(hex)) {
    let match = string.match(hex);
    if (match !== null) {
      match = match[1];
      for (let i = 0; i < 3; i++) {
        const i2 = i * 2;
        rgb[i] = parseInt(match.slice(i2, i2 + 2), 16);
      }
      rgb[3] = 1;
    }
  } else if (string.match(rgba)) {
    const match = string.match(rgba);
    for (let i = 0; i < 3; i++) {
      rgb[i] = parseInt(match[i + 1], 0);
    }
    if (match[4]) {
      rgb[3] = parseFloat(match[4]);
    } else {
      rgb[3] = 1;
    }
  } else if (string.match(keyword)) {
    const match = string.match(keyword);
    if (match[1] === "transparent") {
      return [0, 0, 0, 0];
    }
    rgb = colorNames[match[1]];
    if (!rgb) {
      return null;
    }
    rgb[3] = 1;
    return rgb;
  } else {
    return null;
  }
  return rgb;
}

class Vector {
  constructor(u, v) {
    this.u = u;
    this.v = v;
    this.m = this.magnitude();
  }
  magnitude() {
    return Math.sqrt(this.u ** 2 + this.v ** 2);
  }
  directionTo() {
    const verticalAngle = Math.atan2(this.u, this.v);
    let inDegrees = verticalAngle * (180 / Math.PI);
    if (inDegrees < 0) {
      inDegrees += 360;
    }
    return inDegrees;
  }
  directionFrom() {
    const a = this.directionTo();
    return (a + 180) % 360;
  }
}

class Field {
  constructor(params) {
    this.grid = [];
    this.xmin = params.xmin;
    this.xmax = params.xmax;
    this.ymin = params.ymin;
    this.ymax = params.ymax;
    this.cols = params.cols;
    this.rows = params.rows;
    this.us = params.us;
    this.vs = params.vs;
    this.deltaX = params.deltaX;
    this.deltaY = params.deltaY;
    this.flipY = Boolean(params.flipY);
    this.ymin = Math.min(params.ymax, params.ymin);
    this.ymax = Math.max(params.ymax, params.ymin);
    if (!(this.deltaY < 0 && this.ymin < this.ymax)) {
      if (params.flipY === void 0) {
        this.flipY = true;
      }
      console.warn("[wind-core]: The data is flipY");
    }
    this.isFields = true;
    const cols = Math.ceil((this.xmax - this.xmin) / params.deltaX);
    const rows = Math.ceil((this.ymax - this.ymin) / params.deltaY);
    if (cols !== this.cols || rows !== this.rows) {
      console.warn("[wind-core]: The data grid not equal");
    }
    this.isContinuous = Math.floor(this.cols * params.deltaX) >= 360;
    this.translateX = "translateX" in params ? params.translateX : this.xmax > 180;
    if ("wrappedX" in params) {
      warnOnce("[wind-core]: ", "`wrappedX` namespace will deprecated please use `translateX` instead\uFF01");
    }
    this.wrapX = Boolean(params.wrapX);
    this.grid = this.buildGrid();
    this.range = this.calculateRange();
  }
  buildGrid() {
    let grid = [];
    let p = 0;
    const { rows, cols, us, vs } = this;
    for (let j = 0; j < rows; j++) {
      const row = [];
      for (let i = 0; i < cols; i++, p++) {
        let u = us[p];
        let v = vs[p];
        let valid = this.isValid(u) && this.isValid(v);
        row[i] = valid ? new Vector(u, v) : null;
      }
      if (this.isContinuous) {
        row.push(row[0]);
      }
      grid[j] = row;
    }
    return grid;
  }
  release() {
    this.grid = [];
  }
  extent() {
    return [
      this.xmin,
      this.ymin,
      this.xmax,
      this.ymax
    ];
  }
  bilinearInterpolateVector(x, y, g00, g10, g01, g11) {
    const rx = 1 - x;
    const ry = 1 - y;
    const a = rx * ry;
    const b = x * ry;
    const c = rx * y;
    const d = x * y;
    const u = g00.u * a + g10.u * b + g01.u * c + g11.u * d;
    const v = g00.v * a + g10.v * b + g01.v * c + g11.v * d;
    return new Vector(u, v);
  }
  calculateRange() {
    if (!this.grid || !this.grid[0])
      return;
    const rows = this.grid.length;
    const cols = this.grid[0].length;
    let min;
    let max;
    for (let j = 0; j < rows; j++) {
      for (let i = 0; i < cols; i++) {
        const vec = this.grid[j][i];
        if (vec !== null) {
          const val = vec.m || vec.magnitude();
          if (min === void 0) {
            min = val;
          } else if (max === void 0) {
            max = val;
            min = Math.min(min, max);
            max = Math.max(min, max);
          } else {
            min = Math.min(val, min);
            max = Math.max(val, max);
          }
        }
      }
    }
    return [min, max];
  }
  isValid(x) {
    return x !== null && x !== void 0;
  }
  getWrappedLongitudes() {
    let xmin = this.xmin;
    let xmax = this.xmax;
    if (this.translateX) {
      if (this.isContinuous) {
        xmin = -180;
        xmax = 180;
      } else {
        xmax = this.xmax - 360;
        xmin = this.xmin - 360;
      }
    }
    return [xmin, xmax];
  }
  contains(lon, lat) {
    const [xmin, xmax] = this.getWrappedLongitudes();
    let longitudeIn = lon >= xmin && lon <= xmax;
    let latitudeIn;
    if (this.deltaY >= 0) {
      latitudeIn = lat >= this.ymin && lat <= this.ymax;
    } else {
      latitudeIn = lat >= this.ymax && lat <= this.ymin;
    }
    return longitudeIn && latitudeIn;
  }
  getDecimalIndexes(lon, lat) {
    const i = floorMod(lon - this.xmin, 360) / this.deltaX;
    if (this.flipY) {
      const j = (this.ymax - lat) / this.deltaY;
      return [i, j];
    } else {
      const j = (this.ymin + lat) / this.deltaY;
      return [i, j];
    }
  }
  valueAt(lon, lat) {
    let flag = false;
    if (this.wrapX) {
      flag = true;
    } else if (this.contains(lon, lat)) {
      flag = true;
    }
    if (!flag)
      return null;
    const indexes = this.getDecimalIndexes(lon, lat);
    let ii = Math.floor(indexes[0]);
    let jj = Math.floor(indexes[1]);
    const ci = this.clampColumnIndex(ii);
    const cj = this.clampRowIndex(jj);
    return this.valueAtIndexes(ci, cj);
  }
  interpolatedValueAt(lon, lat) {
    let flag = false;
    if (this.wrapX) {
      flag = true;
    } else if (this.contains(lon, lat)) {
      flag = true;
    }
    if (!flag)
      return null;
    let [i, j] = this.getDecimalIndexes(lon, lat);
    return this.interpolatePoint(i, j);
  }
  hasValueAt(lon, lat) {
    let value = this.valueAt(lon, lat);
    return value !== null;
  }
  interpolatePoint(i, j) {
    const indexes = this.getFourSurroundingIndexes(i, j);
    const [fi, ci, fj, cj] = indexes;
    let values = this.getFourSurroundingValues(fi, ci, fj, cj);
    if (values) {
      const [g00, g10, g01, g11] = values;
      return this.bilinearInterpolateVector(i - fi, j - fj, g00, g10, g01, g11);
    }
    return null;
  }
  clampColumnIndex(ii) {
    let i = ii;
    if (ii < 0) {
      i = 0;
    }
    let maxCol = this.cols - 1;
    if (ii > maxCol) {
      i = maxCol;
    }
    return i;
  }
  clampRowIndex(jj) {
    let j = jj;
    if (jj < 0) {
      j = 0;
    }
    let maxRow = this.rows - 1;
    if (jj > maxRow) {
      j = maxRow;
    }
    return j;
  }
  getFourSurroundingIndexes(i, j) {
    let fi = Math.floor(i);
    let ci = fi + 1;
    if (this.isContinuous && ci >= this.cols) {
      ci = 0;
    }
    ci = this.clampColumnIndex(ci);
    let fj = this.clampRowIndex(Math.floor(j));
    let cj = this.clampRowIndex(fj + 1);
    return [fi, ci, fj, cj];
  }
  getFourSurroundingValues(fi, ci, fj, cj) {
    let row;
    if (row = this.grid[fj]) {
      const g00 = row[fi];
      const g10 = row[ci];
      if (this.isValid(g00) && this.isValid(g10) && (row = this.grid[cj])) {
        const g01 = row[fi];
        const g11 = row[ci];
        if (this.isValid(g01) && this.isValid(g11)) {
          return [g00, g10, g01, g11];
        }
      }
    }
    return null;
  }
  valueAtIndexes(i, j) {
    return this.grid[j][i];
  }
  lonLatAtIndexes(i, j) {
    let lon = this.longitudeAtX(i);
    let lat = this.latitudeAtY(j);
    return [lon, lat];
  }
  longitudeAtX(i) {
    let halfXPixel = this.deltaX / 2;
    let lon = this.xmin + halfXPixel + i * this.deltaX;
    if (this.translateX) {
      lon = lon > 180 ? lon - 360 : lon;
    }
    return lon;
  }
  latitudeAtY(j) {
    let halfYPixel = this.deltaY / 2;
    return this.ymax - halfYPixel - j * this.deltaY;
  }
  randomize(o = {}, width, height, unproject) {
    let i = Math.random() * (width || this.cols) | 0;
    let j = Math.random() * (height || this.rows) | 0;
    const coords = unproject([i, j]);
    if (coords !== null) {
      o.x = coords[0];
      o.y = coords[1];
    } else {
      o.x = this.longitudeAtX(i);
      o.y = this.latitudeAtY(j);
    }
    return o;
  }
  checkFields() {
    return this.isFields;
  }
}

const defaultOptions = {
  globalAlpha: 0.9,
  lineWidth: 1,
  colorScale: "#fff",
  velocityScale: 1 / 25,
  maxAge: 90,
  paths: 800,
  frameRate: 20,
  useCoordsDraw: true,
  gpet: true
};
function indexFor(m, min, max, colorScale) {
  return Math.max(
    0,
    Math.min(
      colorScale.length - 1,
      Math.round((m - min) / (max - min) * (colorScale.length - 1))
    )
  );
}
class WindCore {
  constructor(ctx, options, field) {
    this.particles = [];
    this.generated = false;
    this.ctx = ctx;
    if (!this.ctx) {
      throw new Error("ctx error");
    }
    this.animate = this.animate.bind(this);
    this.setOptions(options);
    if (field) {
      this.updateData(field);
    }
  }
  setOptions(options) {
    this.options = { ...defaultOptions, ...options };
    const { width, height } = this.ctx.canvas;
    if ("particleAge" in options && !("maxAge" in options) && isNumber(this.options.particleAge)) {
      this.options.maxAge = this.options.particleAge;
    }
    if ("particleMultiplier" in options && !("paths" in options) && isNumber(this.options.particleMultiplier)) {
      this.options.paths = Math.round(
        width * height * this.options.particleMultiplier
      );
    }
    this.prerender();
  }
  getOptions() {
    return this.options;
  }
  updateData(field) {
    this.field = field;
    if (!this.generated) {
      return;
    }
    this.particles = this.prepareParticlePaths();
  }
  project(...args) {
    throw new Error("project must be overriden");
  }
  unproject(...args) {
    throw new Error("unproject must be overriden");
  }
  intersectsCoordinate(coordinates) {
    throw new Error("must be overriden");
  }
  clearCanvas() {
    this.stop();
    this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
    this.forceStop = false;
  }
  start() {
    this.starting = true;
    this.forceStop = false;
    this.then = Date.now();
    this.animate();
  }
  stop() {
    cancelAnimationFrame(this.animationLoop);
    this.starting = false;
    this.forceStop = true;
  }
  animate() {
    if (this.animationLoop) {
      cancelAnimationFrame(this.animationLoop);
    }
    this.animationLoop = requestAnimationFrame(this.animate);
    const now = Date.now();
    const delta = now - this.then;
    if (delta > this.options.frameRate) {
      this.then = now - delta % this.options.frameRate;
      this.render();
    }
  }
  prerender() {
    this.generated = false;
    if (!this.field) {
      return;
    }
    this.particles = this.prepareParticlePaths();
    this.generated = true;
    if (!this.starting && !this.forceStop) {
      this.starting = true;
      this.then = Date.now();
      this.animate();
    }
  }
  render() {
    this.moveParticles();
    this.drawParticles();
    this.postrender();
  }
  postrender() {
  }
  moveParticles() {
    const { width, height } = this.ctx.canvas;
    const particles = this.particles;
    const maxAge = this.options.maxAge;
    const velocityScale = isFunction(this.options.velocityScale) ? this.options.velocityScale() : this.options.velocityScale;
    let i = 0;
    const len = particles.length;
    for (; i < len; i++) {
      const particle = particles[i];
      if (particle.age > maxAge) {
        particle.age = 0;
        this.field.randomize(particle, width, height, this.unproject);
      }
      const x = particle.x;
      const y = particle.y;
      const vector = this.field.interpolatedValueAt(x, y);
      if (vector === null) {
        particle.age = maxAge;
      } else {
        const xt = x + vector.u * velocityScale;
        const yt = y + vector.v * velocityScale;
        if (this.field.hasValueAt(xt, yt)) {
          particle.xt = xt;
          particle.yt = yt;
          particle.m = vector.m;
        } else {
          particle.x = xt;
          particle.y = yt;
          particle.age = maxAge;
        }
      }
      particle.age++;
    }
  }
  fadeIn() {
    const prev = this.ctx.globalCompositeOperation;
    this.ctx.globalCompositeOperation = "destination-in";
    this.ctx.fillRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
    this.ctx.globalCompositeOperation = prev;
  }
  drawParticles() {
    const particles = this.particles;
    this.fadeIn();
    this.ctx.globalAlpha = this.options.globalAlpha;
    this.ctx.fillStyle = `rgba(0, 0, 0, ${this.options.globalAlpha})`;
    this.ctx.lineWidth = isNumber(this.options.lineWidth) ? this.options.lineWidth : 1;
    this.ctx.strokeStyle = isString(this.options.colorScale) ? this.options.colorScale : "#fff";
    let i = 0;
    const len = particles.length;
    if (this.field && len > 0) {
      let min;
      let max;
      if (isValide(this.options.minVelocity) && isValide(this.options.maxVelocity)) {
        min = this.options.minVelocity;
        max = this.options.maxVelocity;
      } else {
        [min, max] = this.field.range;
      }
      for (; i < len; i++) {
        this[this.options.useCoordsDraw ? "drawCoordsParticle" : "drawPixelParticle"](particles[i], min, max);
      }
    }
  }
  drawPixelParticle(particle, min, max) {
    const pointPrev = [particle.x, particle.y];
    const pointNext = [particle.xt, particle.yt];
    if (pointNext && pointPrev && isValide(pointNext[0]) && isValide(pointNext[1]) && isValide(pointPrev[0]) && isValide(pointPrev[1]) && particle.age <= this.options.maxAge) {
      this.ctx.beginPath();
      this.ctx.moveTo(pointPrev[0], pointPrev[1]);
      this.ctx.lineTo(pointNext[0], pointNext[1]);
      if (isFunction(this.options.colorScale)) {
        this.ctx.strokeStyle = this.options.colorScale(particle.m);
      } else if (Array.isArray(this.options.colorScale)) {
        const colorIdx = indexFor(
          particle.m,
          min,
          max,
          this.options.colorScale
        );
        this.ctx.strokeStyle = this.options.colorScale[colorIdx];
      }
      if (isFunction(this.options.lineWidth)) {
        this.ctx.lineWidth = this.options.lineWidth(particle.m);
      }
      particle.x = particle.xt;
      particle.y = particle.yt;
      this.ctx.stroke();
    }
  }
  drawCoordsParticle(particle, min, max) {
    const source = [particle.x, particle.y];
    const target = [particle.xt, particle.yt];
    if (target && source && isValide(target[0]) && isValide(target[1]) && isValide(source[0]) && isValide(source[1]) && this.intersectsCoordinate(target) && particle.age <= this.options.maxAge) {
      const pointPrev = this.project(source);
      const pointNext = this.project(target);
      if (pointPrev && pointNext) {
        this.ctx.beginPath();
        this.ctx.moveTo(pointPrev[0], pointPrev[1]);
        this.ctx.lineTo(pointNext[0], pointNext[1]);
        particle.x = particle.xt;
        particle.y = particle.yt;
        if (isFunction(this.options.colorScale)) {
          this.ctx.strokeStyle = this.options.colorScale(particle.m);
        } else if (Array.isArray(this.options.colorScale)) {
          const colorIdx = indexFor(
            particle.m,
            min,
            max,
            this.options.colorScale
          );
          this.ctx.strokeStyle = this.options.colorScale[colorIdx];
        }
        if (isFunction(this.options.lineWidth)) {
          this.ctx.lineWidth = this.options.lineWidth(particle.m);
        }
        this.ctx.stroke();
      }
    }
  }
  prepareParticlePaths() {
    const { width, height } = this.ctx.canvas;
    const particleCount = typeof this.options.paths === "function" ? this.options.paths(this) : this.options.paths;
    const particles = [];
    if (!this.field) {
      return [];
    }
    let i = 0;
    for (; i < particleCount; i++) {
      particles.push(
        this.field.randomize(
          {
            age: this.randomize()
          },
          width,
          height,
          this.unproject
        )
      );
    }
    return particles;
  }
  randomize() {
    return Math.floor(Math.random() * this.options.maxAge);
  }
}
WindCore.Field = Field;

export { Field, TypeOf, Vector, WindCore, assign, createCanvas, defaultOptions, floorMod, formatData, getColor, isArray, isArrayBuffer, isDate, isEmpty, isFunction, isNull, isNumber, isObject, isString, isValide, removeDomNode, warnLog, warnOnce };
//# sourceMappingURL=wind-core.esm.js.map

wind-gl-core.js

// wind-gl-core.js
var WorkerClass = null;

try {
    var WorkerThreads =
        typeof module !== 'undefined' && typeof module.require === 'function' && module.require('worker_threads') ||
        typeof __non_webpack_require__ === 'function' && __non_webpack_require__('worker_threads') ||
        typeof require === 'function' && require('worker_threads');
    WorkerClass = WorkerThreads.Worker;
} catch(e) {} // eslint-disable-line

function decodeBase64$1(base64, enableUnicode) {
    return Buffer.from(base64, 'base64').toString(enableUnicode ? 'utf16' : 'utf8');
}

function createBase64WorkerFactory$2(base64, sourcemapArg, enableUnicodeArg) {
    var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
    var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
    var source = decodeBase64$1(base64, enableUnicode);
    var start = source.indexOf('\n', 10) + 1;
    var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
    return function WorkerFactory(options) {
        return new WorkerClass(body, Object.assign({}, options, { eval: true }));
    };
}

function decodeBase64(base64, enableUnicode) {
    var binaryString = atob(base64);
    if (enableUnicode) {
        var binaryView = new Uint8Array(binaryString.length);
        for (var i = 0, n = binaryString.length; i < n; ++i) {
            binaryView[i] = binaryString.charCodeAt(i);
        }
        return String.fromCharCode.apply(null, new Uint16Array(binaryView.buffer));
    }
    return binaryString;
}

function createURL(base64, sourcemapArg, enableUnicodeArg) {
    var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
    var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
    var source = decodeBase64(base64, enableUnicode);
    var start = source.indexOf('\n', 10) + 1;
    var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
    var blob = new Blob([body], { type: 'application/javascript' });
    return URL.createObjectURL(blob);
}

function createBase64WorkerFactory$1(base64, sourcemapArg, enableUnicodeArg) {
    var url;
    return function WorkerFactory(options) {
        url = url || createURL(base64, sourcemapArg, enableUnicodeArg);
        return new Worker(url, options);
    };
}

var kIsNodeJS = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';

function isNodeJS() {
    return kIsNodeJS;
}

function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
    if (isNodeJS()) {
        return createBase64WorkerFactory$2(base64, sourcemapArg, enableUnicodeArg);
    }
    return createBase64WorkerFactory$1(base64, sourcemapArg, enableUnicodeArg);
}

var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgZnVuY3Rpb24gY2FsY01pbk1heChhcnJheSkgewogICAgbGV0IG1pbiA9IEluZmluaXR5OwogICAgbGV0IG1heCA9IEluZmluaXR5OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykgewogICAgICBjb25zdCB2YWwgPSBhcnJheVtpXTsKICAgICAgaWYgKG1pbiA9PT0gSW5maW5pdHkpIHsKICAgICAgICBtaW4gPSB2YWw7CiAgICAgIH0gZWxzZSBpZiAobWF4ID09PSBJbmZpbml0eSkgewogICAgICAgIG1heCA9IHZhbDsKICAgICAgICBtaW4gPSBNYXRoLm1pbihtaW4sIG1heCk7CiAgICAgICAgbWF4ID0gTWF0aC5tYXgobWluLCBtYXgpOwogICAgICB9IGVsc2UgewogICAgICAgIG1pbiA9IE1hdGgubWluKHZhbCwgbWluKTsKICAgICAgICBtYXggPSBNYXRoLm1heCh2YWwsIG1heCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBbbWluLCBtYXhdOwogIH0KCiAgY29uc3QgY3R4ID0gc2VsZjsKICBjdHguYWRkRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsIGFzeW5jICh7IGRhdGE6IHBheWxvYWQgfSkgPT4gewogICAgY29uc3QgcmVuZGVyRm9ybSA9IHBheWxvYWRbMF07CiAgICBpZiAocmVuZGVyRm9ybSA9PT0gInJnIikgewogICAgICBjb25zdCB1RGF0YSA9IHBheWxvYWRbMV07CiAgICAgIGNvbnN0IHZEYXRhID0gcGF5bG9hZFsyXTsKICAgICAgY29uc3QgW3VNaW4sIHVNYXhdID0gY2FsY01pbk1heCh1RGF0YSk7CiAgICAgIGNvbnN0IFt2TWluLCB2TWF4XSA9IGNhbGNNaW5NYXgodkRhdGEpOwogICAgICBjb25zdCB2ZWxvY2l0eURhdGEgPSBuZXcgVWludDhBcnJheSh1RGF0YS5sZW5ndGggKiA0KTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB1RGF0YS5sZW5ndGg7IGkrKykgewogICAgICAgIGNvbnN0IHIgPSAyNTUgKiAodURhdGFbaV0gLSB1TWluKSAvICh1TWF4IC0gdU1pbik7CiAgICAgICAgY29uc3QgZyA9IDI1NSAqICh2RGF0YVtpXSAtIHZNaW4pIC8gKHZNYXggLSB2TWluKTsKICAgICAgICB2ZWxvY2l0eURhdGEuc2V0KFtyLCBnLCAwLCAyNTVdLCBpICogNCk7CiAgICAgIH0KICAgICAgY3R4LnBvc3RNZXNzYWdlKFt2ZWxvY2l0eURhdGEuYnVmZmVyLCB1TWluLCB1TWF4LCB2TWluLCB2TWF4XSwgW3ZlbG9jaXR5RGF0YS5idWZmZXJdKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHNpbmdsZURhdGEgPSBwYXlsb2FkWzFdOwogICAgICBjb25zdCBbbWluLCBtYXhdID0gY2FsY01pbk1heChzaW5nbGVEYXRhKTsKICAgICAgY29uc3QgdmVsb2NpdHlEYXRhID0gbmV3IFVpbnQ4QXJyYXkoc2luZ2xlRGF0YS5sZW5ndGggKiA0KTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaW5nbGVEYXRhLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgY29uc3QgciA9IDI1NSAqIChzaW5nbGVEYXRhW2ldIC0gbWluKSAvIChtYXggLSBtaW4pOwogICAgICAgIHZlbG9jaXR5RGF0YS5zZXQoW3IsIDAsIDAsIDI1NV0sIGkgKiA0KTsKICAgICAgfQogICAgICBjdHgucG9zdE1lc3NhZ2UoW3ZlbG9jaXR5RGF0YS5idWZmZXIsIG1pbiwgbWF4XSwgW3ZlbG9jaXR5RGF0YS5idWZmZXJdKTsKICAgIH0KICB9KTsKCn0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPURhdGFQcm9jZXNzZS5qcy5tYXAKCg==', 'data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGF0YVByb2Nlc3NlLmpzIiwic291cmNlcyI6WyJ3b3JrZXI6Ly93ZWItd29ya2VyL3V0aWxzL2NvbW1vbi50cyIsIndvcmtlcjovL3dlYi13b3JrZXIvd29ya2Vycy9EYXRhUHJvY2Vzc2UudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIGNhbGNNaW5NYXgoYXJyYXk6IG51bWJlcltdKTogW251bWJlciwgbnVtYmVyXSB7XG4gIGxldCBtaW4gPSBJbmZpbml0eTtcbiAgbGV0IG1heCA9IEluZmluaXR5O1xuICAvLyBAZnJvbTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTM1NDQ0NzYvaG93LXRvLWZpbmQtbWF4LWFuZC1taW4taW4tYXJyYXktdXNpbmctbWluaW11bS1jb21wYXJpc29uc1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgY29uc3QgdmFsID0gYXJyYXlbaV07XG5cbiAgICBpZiAobWluID09PSBJbmZpbml0eSkge1xuICAgICAgbWluID0gdmFsO1xuICAgIH0gZWxzZSBpZiAobWF4ID09PSBJbmZpbml0eSkge1xuICAgICAgbWF4ID0gdmFsO1xuICAgICAgLy8gdXBkYXRlIG1pbiBtYXhcbiAgICAgIC8vIDEuIFBpY2sgMiBlbGVtZW50cyhhLCBiKSwgY29tcGFyZSB0aGVtLiAoc2F5IGEgPiBiKVxuICAgICAgbWluID0gTWF0aC5taW4obWluLCBtYXgpO1xuICAgICAgbWF4ID0gTWF0aC5tYXgobWluLCBtYXgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyAyLiBVcGRhdGUgbWluIGJ5IGNvbXBhcmluZyAobWluLCBiKVxuICAgICAgLy8gMy4gVXBkYXRlIG1heCBieSBjb21wYXJpbmcgKG1heCwgYSlcbiAgICAgIG1pbiA9IE1hdGgubWluKHZhbCwgbWluKTtcbiAgICAgIG1heCA9IE1hdGgubWF4KHZhbCwgbWF4KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIFttaW4sIG1heF07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc051bWJlcih2YWw6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ251bWJlcicgJiYgIWlzTmFOKHZhbCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkZSh2YWw6IGFueSk6IGJvb2xlYW4ge1xuICByZXR1cm4gdmFsICE9PSB1bmRlZmluZWQgJiYgdmFsICE9PSBudWxsICYmICFpc05hTih2YWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmluZFN0b3BMZXNzVGhhbk9yRXF1YWxUbyhzdG9wczogbnVtYmVyW10sIGlucHV0OiBudW1iZXIpIHtcbiAgY29uc3QgbGFzdEluZGV4ID0gc3RvcHMubGVuZ3RoIC0gMTtcbiAgbGV0IGxvd2VySW5kZXggPSAwO1xuICBsZXQgdXBwZXJJbmRleCA9IGxhc3RJbmRleDtcbiAgbGV0IGN1cnJlbnRJbmRleCA9IDA7XG4gIGxldCBjdXJyZW50VmFsdWU7XG4gIGxldCBuZXh0VmFsdWU7XG5cbiAgd2hpbGUgKGxvd2VySW5kZXggPD0gdXBwZXJJbmRleCkge1xuICAgIGN1cnJlbnRJbmRleCA9IE1hdGguZmxvb3IoKGxvd2VySW5kZXggKyB1cHBlckluZGV4KSAvIDIpO1xuICAgIGN1cnJlbnRWYWx1ZSA9IHN0b3BzW2N1cnJlbnRJbmRleF07XG4gICAgbmV4dFZhbHVlID0gc3RvcHNbY3VycmVudEluZGV4ICsgMV07XG5cbiAgICBpZiAoY3VycmVudFZhbHVlIDw9IGlucHV0KSB7XG4gICAgICBpZiAoY3VycmVudEluZGV4ID09PSBsYXN0SW5kZXggfHwgaW5wdXQgPCBuZXh0VmFsdWUpIHtcbiAgICAgICAgLy8gU2VhcmNoIGNvbXBsZXRlXG4gICAgICAgIHJldHVybiBjdXJyZW50SW5kZXg7XG4gICAgICB9XG5cbiAgICAgIGxvd2VySW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgIH0gZWxzZSBpZiAoY3VycmVudFZhbHVlID4gaW5wdXQpIHtcbiAgICAgIHVwcGVySW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGlzIG5vdCBhIG51bWJlci4nKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZwNjRMb3dQYXJ0KHg6IG51bWJlcikge1xuICByZXR1cm4geCAtIE1hdGguZnJvdW5kKHgpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0NEludmVydChvdXQ6IG51bWJlcltdLCBhOiBudW1iZXJbXSkge1xuICBjb25zdCBhMDAgPSBhWzBdO1xuICBjb25zdCBhMDEgPSBhWzFdO1xuICBjb25zdCBhMDIgPSBhWzJdO1xuICBjb25zdCBhMDMgPSBhWzNdO1xuICBjb25zdCBhMTAgPSBhWzRdO1xuICBjb25zdCBhMTEgPSBhWzVdO1xuICBjb25zdCBhMTIgPSBhWzZdO1xuICBjb25zdCBhMTMgPSBhWzddO1xuICBjb25zdCBhMjAgPSBhWzhdO1xuICBjb25zdCBhMjEgPSBhWzldO1xuICBjb25zdCBhMjIgPSBhWzEwXTtcbiAgY29uc3QgYTIzID0gYVsxMV07XG4gIGNvbnN0IGEzMCA9IGFbMTJdO1xuICBjb25zdCBhMzEgPSBhWzEzXTtcbiAgY29uc3QgYTMyID0gYVsxNF07XG4gIGNvbnN0IGEzMyA9IGFbMTVdO1xuXG4gIGNvbnN0IGIwMCA9IGEwMCAqIGExMSAtIGEwMSAqIGExMDtcbiAgY29uc3QgYjAxID0gYTAwICogYTEyIC0gYTAyICogYTEwO1xuICBjb25zdCBiMDIgPSBhMDAgKiBhMTMgLSBhMDMgKiBhMTA7XG4gIGNvbnN0IGIwMyA9IGEwMSAqIGExMiAtIGEwMiAqIGExMTtcbiAgY29uc3QgYjA0ID0gYTAxICogYTEzIC0gYTAzICogYTExO1xuICBjb25zdCBiMDUgPSBhMDIgKiBhMTMgLSBhMDMgKiBhMTI7XG4gIGNvbnN0IGIwNiA9IGEyMCAqIGEzMSAtIGEyMSAqIGEzMDtcbiAgY29uc3QgYjA3ID0gYTIwICogYTMyIC0gYTIyICogYTMwO1xuICBjb25zdCBiMDggPSBhMjAgKiBhMzMgLSBhMjMgKiBhMzA7XG4gIGNvbnN0IGIwOSA9IGEyMSAqIGEzMiAtIGEyMiAqIGEzMTtcbiAgY29uc3QgYjEwID0gYTIxICogYTMzIC0gYTIzICogYTMxO1xuICBjb25zdCBiMTEgPSBhMjIgKiBhMzMgLSBhMjMgKiBhMzI7XG5cbiAgLy8gQ2FsY3VsYXRlIHRoZSBkZXRlcm1pbmFudFxuICBsZXQgZGV0ID1cbiAgICBiMDAgKiBiMTEgLSBiMDEgKiBiMTAgKyBiMDIgKiBiMDkgKyBiMDMgKiBiMDggLSBiMDQgKiBiMDcgKyBiMDUgKiBiMDY7XG5cbiAgaWYgKCFkZXQpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBkZXQgPSAxLjAgLyBkZXQ7XG5cbiAgb3V0WzBdID0gKGExMSAqIGIxMSAtIGExMiAqIGIxMCArIGExMyAqIGIwOSkgKiBkZXQ7XG4gIG91dFsxXSA9IChhMDIgKiBiMTAgLSBhMDEgKiBiMTEgLSBhMDMgKiBiMDkpICogZGV0O1xuICBvdXRbMl0gPSAoYTMxICogYjA1IC0gYTMyICogYjA0ICsgYTMzICogYjAzKSAqIGRldDtcbiAgb3V0WzNdID0gKGEyMiAqIGIwNCAtIGEyMSAqIGIwNSAtIGEyMyAqIGIwMykgKiBkZXQ7XG4gIG91dFs0XSA9IChhMTIgKiBiMDggLSBhMTAgKiBiMTEgLSBhMTMgKiBiMDcpICogZGV0O1xuICBvdXRbNV0gPSAoYTAwICogYjExIC0gYTAyICogYjA4ICsgYTAzICogYjA3KSAqIGRldDtcbiAgb3V0WzZdID0gKGEzMiAqIGIwMiAtIGEzMCAqIGIwNSAtIGEzMyAqIGIwMSkgKiBkZXQ7XG4gIG91dFs3XSA9IChhMjAgKiBiMDUgLSBhMjIgKiBiMDIgKyBhMjMgKiBiMDEpICogZGV0O1xuICBvdXRbOF0gPSAoYTEwICogYjEwIC0gYTExICogYjA4ICsgYTEzICogYjA2KSAqIGRldDtcbiAgb3V0WzldID0gKGEwMSAqIGIwOCAtIGEwMCAqIGIxMCAtIGEwMyAqIGIwNikgKiBkZXQ7XG4gIG91dFsxMF0gPSAoYTMwICogYjA0IC0gYTMxICogYjAyICsgYTMzICogYjAwKSAqIGRldDtcbiAgb3V0WzExXSA9IChhMjEgKiBiMDIgLSBhMjAgKiBiMDQgLSBhMjMgKiBiMDApICogZGV0O1xuICBvdXRbMTJdID0gKGExMSAqIGIwNyAtIGExMCAqIGIwOSAtIGExMiAqIGIwNikgKiBkZXQ7XG4gIG91dFsxM10gPSAoYTAwICogYjA5IC0gYTAxICogYjA3ICsgYTAyICogYjA2KSAqIGRldDtcbiAgb3V0WzE0XSA9IChhMzEgKiBiMDEgLSBhMzAgKiBiMDMgLSBhMzIgKiBiMDApICogZGV0O1xuICBvdXRbMTVdID0gKGEyMCAqIGIwMyAtIGEyMSAqIGIwMSArIGEyMiAqIGIwMCkgKiBkZXQ7XG5cbiAgcmV0dXJuIG91dDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zZm9ybU1hdDQob3V0OiBudW1iZXJbXSwgYTogbnVtYmVyW10sIG06IG51bWJlcltdKSB7XG4gIGNvbnN0IHggPSBhWzBdO1xuICBjb25zdCB5ID0gYVsxXTtcbiAgY29uc3QgeiA9IGFbMl07XG4gIGNvbnN0IHcgPSBhWzNdO1xuICBvdXRbMF0gPSBtWzBdICogeCArIG1bNF0gKiB5ICsgbVs4XSAqIHogKyBtWzEyXSAqIHc7IC8vIDBcbiAgb3V0WzFdID0gbVsxXSAqIHggKyBtWzVdICogeSArIG1bOV0gKiB6ICsgbVsxM10gKiB3OyAvLyAwXG4gIG91dFsyXSA9IG1bMl0gKiB4ICsgbVs2XSAqIHkgKyBtWzEwXSAqIHogKyBtWzE0XSAqIHc7IC8vIDBcbiAgb3V0WzNdID0gbVszXSAqIHggKyBtWzddICogeSArIG1bMTFdICogeiArIG1bMTVdICogdzsgLy8gMVxuICByZXR1cm4gb3V0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RXllKG1hdHJpeDogbnVtYmVyW10pIHtcbiAgY29uc3QgZGVmYXVsdE1hdDQgPSBbMSwgMCwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMCwgMV07IC8vIGluc3RlZCBvZiBtYXQ0LmNyZWF0ZSgpXG4gIGxldCBleWUgPSB0cmFuc2Zvcm1NYXQ0KFxuICAgIFtdLFxuICAgIFswLCAwLCAwLCAxXSxcbiAgICBtYXQ0SW52ZXJ0KGRlZmF1bHRNYXQ0LCBtYXRyaXgpIGFzIG51bWJlcltdLFxuICApO1xuICBjb25zdCBjbGlwVyA9IDEuMCAvIGV5ZVszXTtcbiAgZXllID0gZXllLm1hcCgoaXRlbTogbnVtYmVyKSA9PiBpdGVtIC8gZXllWzNdKTtcbiAgZXllWzNdID0gY2xpcFc7XG4gIHJldHVybiBleWU7XG59XG4iLCJpbXBvcnQgeyBjYWxjTWluTWF4IH0gZnJvbSAnLi4vdXRpbHMvY29tbW9uJztcblxuY29uc3QgY3R4OiBXb3JrZXIgPSBzZWxmIGFzIGFueTtcblxuY3R4LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBhc3luYyAoeyBkYXRhOiBwYXlsb2FkIH0pID0+IHtcbiAgY29uc3QgcmVuZGVyRm9ybSA9IHBheWxvYWRbMF07XG4gIGlmIChyZW5kZXJGb3JtID09PSAncmcnKSB7XG4gICAgY29uc3QgdURhdGEgPSBwYXlsb2FkWzFdO1xuICAgIGNvbnN0IHZEYXRhID0gcGF5bG9hZFsyXTtcbiAgICBjb25zdCBbdU1pbiwgdU1heF0gPSBjYWxjTWluTWF4KHVEYXRhKTtcbiAgICBjb25zdCBbdk1pbiwgdk1heF0gPSBjYWxjTWluTWF4KHZEYXRhKTtcbiAgICBjb25zdCB2ZWxvY2l0eURhdGEgPSBuZXcgVWludDhBcnJheSh1RGF0YS5sZW5ndGggKiA0KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHVEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCByID0gMjU1ICogKHVEYXRhW2ldIC0gdU1pbikgLyAodU1heCAtIHVNaW4pO1xuICAgICAgY29uc3QgZyA9IDI1NSAqICh2RGF0YVtpXSAtIHZNaW4pIC8gKHZNYXggLSB2TWluKTtcbiAgICAgIHZlbG9jaXR5RGF0YS5zZXQoW3IsIGcsIDAsIDI1NV0sIGkgKiA0KTtcbiAgICB9XG5cbiAgICBjdHgucG9zdE1lc3NhZ2UoW3ZlbG9jaXR5RGF0YS5idWZmZXIsIHVNaW4sIHVNYXgsIHZNaW4sIHZNYXhdLCBbdmVsb2NpdHlEYXRhLmJ1ZmZlcl0pO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHNpbmdsZURhdGEgPSBwYXlsb2FkWzFdO1xuICAgIGNvbnN0IFttaW4sIG1heF0gPSBjYWxjTWluTWF4KHNpbmdsZURhdGEpO1xuICAgIGNvbnN0IHZlbG9jaXR5RGF0YSA9IG5ldyBVaW50OEFycmF5KHNpbmdsZURhdGEubGVuZ3RoICogNCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaW5nbGVEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCByID0gMjU1ICogKHNpbmdsZURhdGFbaV0gLSBtaW4pIC8gKG1heCAtIG1pbik7XG4gICAgICB2ZWxvY2l0eURhdGEuc2V0KFtyLCAwLCAwLCAyNTVdLCBpICogNCk7XG4gICAgfVxuXG4gICAgY3R4LnBvc3RNZXNzYWdlKFt2ZWxvY2l0eURhdGEuYnVmZmVyLCBtaW4sIG1heF0sIFt2ZWxvY2l0eURhdGEuYnVmZmVyXSk7XG4gIH1cbn0pO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztFQUFPLFNBQVMsV0FBVyxLQUFtQyxFQUFBO0VBQzVELEVBQUEsSUFBSSxHQUFNLEdBQUEsUUFBQSxDQUFBO0VBQ1YsRUFBQSxJQUFJLEdBQU0sR0FBQSxRQUFBLENBQUE7RUFFVixFQUFBLEtBQUEsSUFBUyxDQUFJLEdBQUEsQ0FBQSxFQUFHLENBQUksR0FBQSxLQUFBLENBQU0sUUFBUSxDQUFLLEVBQUEsRUFBQTtFQUNyQyxJQUFBLE1BQU0sTUFBTSxLQUFNLENBQUEsQ0FBQSxDQUFBLENBQUE7RUFFbEIsSUFBQSxJQUFJLFFBQVEsUUFBVSxFQUFBO0VBQ3BCLE1BQU0sR0FBQSxHQUFBLEdBQUEsQ0FBQTtFQUFBLEtBQ1IsTUFBQSxJQUFXLFFBQVEsUUFBVSxFQUFBO0VBQzNCLE1BQU0sR0FBQSxHQUFBLEdBQUEsQ0FBQTtFQUdOLE1BQU0sR0FBQSxHQUFBLElBQUEsQ0FBSyxHQUFJLENBQUEsR0FBQSxFQUFLLEdBQUcsQ0FBQSxDQUFBO0VBQ3ZCLE1BQU0sR0FBQSxHQUFBLElBQUEsQ0FBSyxHQUFJLENBQUEsR0FBQSxFQUFLLEdBQUcsQ0FBQSxDQUFBO0VBQUEsS0FDbEIsTUFBQTtFQUdMLE1BQU0sR0FBQSxHQUFBLElBQUEsQ0FBSyxHQUFJLENBQUEsR0FBQSxFQUFLLEdBQUcsQ0FBQSxDQUFBO0VBQ3ZCLE1BQU0sR0FBQSxHQUFBLElBQUEsQ0FBSyxHQUFJLENBQUEsR0FBQSxFQUFLLEdBQUcsQ0FBQSxDQUFBO0VBQUEsS0FDekI7RUFBQSxHQUNGO0VBQ0EsRUFBTyxPQUFBLENBQUMsS0FBSyxHQUFHLENBQUEsQ0FBQTtFQUNsQjs7RUNyQkEsTUFBTSxHQUFjLEdBQUEsSUFBQSxDQUFBO0VBRXBCLEdBQUEsQ0FBSSxpQkFBaUIsU0FBVyxFQUFBLE9BQU8sRUFBRSxJQUFBLEVBQU0sU0FBYyxLQUFBO0VBQzNELEVBQUEsTUFBTSxhQUFhLE9BQVEsQ0FBQSxDQUFBLENBQUEsQ0FBQTtFQUMzQixFQUFBLElBQUksZUFBZSxJQUFNLEVBQUE7RUFDdkIsSUFBQSxNQUFNLFFBQVEsT0FBUSxDQUFBLENBQUEsQ0FBQSxDQUFBO0VBQ3RCLElBQUEsTUFBTSxRQUFRLE9BQVEsQ0FBQSxDQUFBLENBQUEsQ0FBQTtFQUN0QixJQUFBLE1BQU0sQ0FBQyxJQUFBLEVBQU0sSUFBSSxDQUFBLEdBQUksV0FBVyxLQUFLLENBQUEsQ0FBQTtFQUNyQyxJQUFBLE1BQU0sQ0FBQyxJQUFBLEVBQU0sSUFBSSxDQUFBLEdBQUksV0FBVyxLQUFLLENBQUEsQ0FBQTtFQUNyQyxJQUFBLE1BQU0sWUFBZSxHQUFBLElBQUksVUFBVyxDQUFBLEtBQUEsQ0FBTSxTQUFTLENBQUMsQ0FBQSxDQUFBO0VBQ3BELElBQUEsS0FBQSxJQUFTLENBQUksR0FBQSxDQUFBLEVBQUcsQ0FBSSxHQUFBLEtBQUEsQ0FBTSxRQUFRLENBQUssRUFBQSxFQUFBO0VBQ3JDLE1BQUEsTUFBTSxDQUFJLEdBQUEsR0FBQSxJQUFPLEtBQU0sQ0FBQSxDQUFBLENBQUEsR0FBSyxTQUFTLElBQU8sR0FBQSxJQUFBLENBQUEsQ0FBQTtFQUM1QyxNQUFBLE1BQU0sQ0FBSSxHQUFBLEdBQUEsSUFBTyxLQUFNLENBQUEsQ0FBQSxDQUFBLEdBQUssU0FBUyxJQUFPLEdBQUEsSUFBQSxDQUFBLENBQUE7RUFDNUMsTUFBYSxZQUFBLENBQUEsR0FBQSxDQUFJLENBQUMsQ0FBRyxFQUFBLENBQUEsRUFBRyxHQUFHLEdBQUcsQ0FBQSxFQUFHLElBQUksQ0FBQyxDQUFBLENBQUE7RUFBQSxLQUN4QztFQUVBLElBQUEsR0FBQSxDQUFJLFdBQVksQ0FBQSxDQUFDLFlBQWEsQ0FBQSxNQUFBLEVBQVEsSUFBTSxFQUFBLElBQUEsRUFBTSxJQUFNLEVBQUEsSUFBSSxDQUFHLEVBQUEsQ0FBQyxZQUFhLENBQUEsTUFBTSxDQUFDLENBQUEsQ0FBQTtFQUFBLEdBQy9FLE1BQUE7RUFDTCxJQUFBLE1BQU0sYUFBYSxPQUFRLENBQUEsQ0FBQSxDQUFBLENBQUE7RUFDM0IsSUFBQSxNQUFNLENBQUMsR0FBQSxFQUFLLEdBQUcsQ0FBQSxHQUFJLFdBQVcsVUFBVSxDQUFBLENBQUE7RUFDeEMsSUFBQSxNQUFNLFlBQWUsR0FBQSxJQUFJLFVBQVcsQ0FBQSxVQUFBLENBQVcsU0FBUyxDQUFDLENBQUEsQ0FBQTtFQUN6RCxJQUFBLEtBQUEsSUFBUyxDQUFJLEdBQUEsQ0FBQSxFQUFHLENBQUksR0FBQSxVQUFBLENBQVcsUUFBUSxDQUFLLEVBQUEsRUFBQTtFQUMxQyxNQUFBLE1BQU0sQ0FBSSxHQUFBLEdBQUEsSUFBTyxVQUFXLENBQUEsQ0FBQSxDQUFBLEdBQUssUUFBUSxHQUFNLEdBQUEsR0FBQSxDQUFBLENBQUE7RUFDL0MsTUFBYSxZQUFBLENBQUEsR0FBQSxDQUFJLENBQUMsQ0FBRyxFQUFBLENBQUEsRUFBRyxHQUFHLEdBQUcsQ0FBQSxFQUFHLElBQUksQ0FBQyxDQUFBLENBQUE7RUFBQSxLQUN4QztFQUVBLElBQUksR0FBQSxDQUFBLFdBQUEsQ0FBWSxDQUFDLFlBQUEsQ0FBYSxNQUFRLEVBQUEsR0FBQSxFQUFLLEdBQUcsQ0FBRyxFQUFBLENBQUMsWUFBYSxDQUFBLE1BQU0sQ0FBQyxDQUFBLENBQUE7RUFBQSxHQUN4RTtFQUNGLENBQUMsQ0FBQTs7Ozs7OyJ9', false);
/* eslint-enable */

function calcMinMax(array) {
  let min = Infinity;
  let max = Infinity;
  for (let i = 0; i < array.length; i++) {
    const val = array[i];
    if (min === Infinity) {
      min = val;
    } else if (max === Infinity) {
      max = val;
      min = Math.min(min, max);
      max = Math.max(min, max);
    } else {
      min = Math.min(val, min);
      max = Math.max(val, max);
    }
  }
  return [min, max];
}
function isNumber(val) {
  return typeof val === "number" && !isNaN(val);
}
function isValide(val) {
  return val !== void 0 && val !== null && !isNaN(val);
}
function findStopLessThanOrEqualTo(stops, input) {
  const lastIndex = stops.length - 1;
  let lowerIndex = 0;
  let upperIndex = lastIndex;
  let currentIndex = 0;
  let currentValue;
  let nextValue;
  while (lowerIndex <= upperIndex) {
    currentIndex = Math.floor((lowerIndex + upperIndex) / 2);
    currentValue = stops[currentIndex];
    nextValue = stops[currentIndex + 1];
    if (currentValue <= input) {
      if (currentIndex === lastIndex || input < nextValue) {
        return currentIndex;
      }
      lowerIndex = currentIndex + 1;
    } else if (currentValue > input) {
      upperIndex = currentIndex - 1;
    } else {
      throw new Error("Input is not a number.");
    }
  }
  return 0;
}
function fp64LowPart(x) {
  return x - Math.fround(x);
}
function mat4Invert(out, a) {
  const a00 = a[0];
  const a01 = a[1];
  const a02 = a[2];
  const a03 = a[3];
  const a10 = a[4];
  const a11 = a[5];
  const a12 = a[6];
  const a13 = a[7];
  const a20 = a[8];
  const a21 = a[9];
  const a22 = a[10];
  const a23 = a[11];
  const a30 = a[12];
  const a31 = a[13];
  const a32 = a[14];
  const a33 = a[15];
  const b00 = a00 * a11 - a01 * a10;
  const b01 = a00 * a12 - a02 * a10;
  const b02 = a00 * a13 - a03 * a10;
  const b03 = a01 * a12 - a02 * a11;
  const b04 = a01 * a13 - a03 * a11;
  const b05 = a02 * a13 - a03 * a12;
  const b06 = a20 * a31 - a21 * a30;
  const b07 = a20 * a32 - a22 * a30;
  const b08 = a20 * a33 - a23 * a30;
  const b09 = a21 * a32 - a22 * a31;
  const b10 = a21 * a33 - a23 * a31;
  const b11 = a22 * a33 - a23 * a32;
  let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
  if (!det) {
    return null;
  }
  det = 1 / det;
  out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
  out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
  out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
  out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
  out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
  out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
  out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
  out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
  out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
  out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
  out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
  out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
  out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
  out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
  out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
  out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  return out;
}
function transformMat4(out, a, m) {
  const x = a[0];
  const y = a[1];
  const z = a[2];
  const w = a[3];
  out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
  out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
  out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
  out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
  return out;
}
function getEye(matrix) {
  const defaultMat4 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
  let eye = transformMat4(
    [],
    [0, 0, 0, 1],
    mat4Invert(defaultMat4, matrix)
  );
  const clipW = 1 / eye[3];
  eye = eye.map((item) => item / eye[3]);
  eye[3] = clipW;
  return eye;
}

function getDevicePixelRatio() {
  return devicePixelRatio || 1;
}
function resizeCanvasSize(canvas, pixelRatio) {
  if (!canvas) {
    return false;
  }
  pixelRatio = pixelRatio || getDevicePixelRatio();
  if (canvas instanceof HTMLCanvasElement) {
    const width = canvas.clientWidth * pixelRatio;
    const height = canvas.clientHeight * pixelRatio;
    if (width <= 0 || height <= 0) {
      return false;
    } else if (canvas.width !== width || canvas.height !== height) {
      canvas.width = width;
      canvas.height = height;
      return true;
    }
  }
  return false;
}
function getGlContext(canvas, glOptions = {}) {
  const names = ["webgl", "experimental-webgl"];
  let context = null;
  function onContextCreationError(error) {
    console.error(error.statusMessage);
  }
  canvas.addEventListener(
    "webglcontextcreationerror",
    onContextCreationError,
    false
  );
  for (let ii = 0; ii < names.length; ++ii) {
    try {
      context = canvas.getContext(
        names[ii],
        glOptions
      );
    } catch (e) {
    }
    if (context) {
      break;
    }
  }
  canvas.removeEventListener(
    "webglcontextcreationerror",
    onContextCreationError,
    false
  );
  if (!context || !context.getExtension("OES_texture_float")) {
    return null;
  }
  return context;
}
function defineShader(shader, defines) {
  return Object.keys(defines).reduce((str, key) => {
    return defines[key] ? str + `#define ${key} ${defines[key]}
` : "";
  }, "");
}
function injectShaderModule(shader, modules = {}) {
  Object.keys(modules).map((key) => {
    if (modules[key]) {
      shader = shader.replace(new RegExp(key, "g"), `${modules[key]} 
`);
    }
  });
  return shader;
}
function createShader(gl, type, source) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    const log = gl.getShaderInfoLog(shader) || "";
    gl.deleteShader(shader);
    throw new Error(log);
  }
  return shader;
}
function createProgram(gl, vertexShaderSource, fragmentShaderSource) {
  const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
  const fragmentShader = createShader(
    gl,
    gl.FRAGMENT_SHADER,
    fragmentShaderSource
  );
  const program = gl.createProgram();
  if (program !== null) {
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
      throw new Error(gl.getProgramInfoLog(program) || "");
    }
  }
  return program;
}
function createTexture(gl, filter, data, width, height) {
  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, filter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
  if (data instanceof Uint8Array) {
    gl.texImage2D(
      gl.TEXTURE_2D,
      0,
      gl.RGBA,
      width,
      height,
      0,
      gl.RGBA,
      gl.UNSIGNED_BYTE,
      data
    );
  } else {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
  }
  gl.bindTexture(gl.TEXTURE_2D, null);
  return texture;
}
function resizeTexture(gl, texture, width, height, data) {
  gl.bindTexture(gl.TEXTURE_2D, texture);
  if (data instanceof Uint8Array) {
    gl.texImage2D(
      gl.TEXTURE_2D,
      0,
      gl.RGBA,
      width,
      height,
      0,
      gl.RGBA,
      gl.UNSIGNED_BYTE,
      data
    );
  } else {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
  }
  gl.bindTexture(gl.TEXTURE_2D, null);
}
function bindTexture(gl, texture, unit) {
  gl.activeTexture(gl.TEXTURE0 + unit);
  gl.bindTexture(gl.TEXTURE_2D, texture);
}
function destroyTexture(gl, texture) {
  gl.deleteTexture(texture);
}
function createBuffer(gl, data) {
  const buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  if (data) {
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  }
  return buffer;
}
function updateBufferData(gl, buffer, data) {
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  if (data) {
    gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
  }
  return buffer;
}
function bindAttribute(gl, buffer, attribute, numComponents) {
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.enableVertexAttribArray(attribute);
  gl.vertexAttribPointer(attribute, numComponents, gl.FLOAT, false, 0, 0);
}
function bindFramebuffer(gl, framebuffer, texture) {
  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
  if (texture) {
    gl.framebufferTexture2D(
      gl.FRAMEBUFFER,
      gl.COLOR_ATTACHMENT0,
      gl.TEXTURE_2D,
      texture,
      0
    );
  }
}
function resizeFramebuffer(gl, framebuffer, width, height, texture) {
  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
  if (texture) {
    gl.framebufferTexture2D(
      gl.FRAMEBUFFER,
      gl.COLOR_ATTACHMENT0,
      gl.TEXTURE_2D,
      texture,
      0
    );
  }
}
function clearScene(gl, color, depth = 1, stencil = 0, fbo) {
  const [r, g, b, a] = color;
  let clearFlags = 0;
  gl.clearColor(r, g, b, a);
  clearFlags |= gl.COLOR_BUFFER_BIT;
  if (depth !== void 0) {
    gl.clearDepth(depth);
    clearFlags |= gl.DEPTH_BUFFER_BIT;
  }
  if (stencil !== void 0) {
    gl.clearStencil(stencil | 0);
    clearFlags |= gl.STENCIL_BUFFER_BIT;
  }
  gl.clear(clearFlags);
}
function loadImage(src) {
  return new Promise((resolve, reject) => {
    if (!src) {
      reject(new Event("url is null"));
    }
    const image = new Image();
    image.crossOrigin = "anonymous";
    image.onload = () => resolve(image);
    image.onerror = reject;
    image.src = src;
    if (image.complete) {
      resolve(image);
    }
  });
}
function getPlaneBuffer(startX, endX, startY, endY, widthSegments, heightSegments) {
  const width = endX - startX;
  const height = endY - startY;
  const widthHalf = width / 2;
  const heightHalf = height / 2;
  const gridX = Math.floor(widthSegments);
  const gridY = Math.floor(heightSegments);
  const gridX1 = gridX + 1;
  const gridY1 = gridY + 1;
  const segmentWidth = width / gridX;
  const segmentHeight = height / gridY;
  const indices = [];
  const wireframeIndexes = [];
  const vertices = [];
  const verticesLow = [];
  const uvs = [];
  for (let iy = 0; iy < gridY1; iy++) {
    const y = iy * segmentHeight;
    for (let ix = 0; ix < gridX1; ix++) {
      const x = ix * segmentWidth;
      const vx = startX + x / widthHalf / 2 * width;
      const vy = startY + y / heightHalf / 2 * height;
      vertices.push(vx, vy, 0);
      verticesLow.push(fp64LowPart(vx), fp64LowPart(vy), 0);
      uvs.push(ix / gridX, iy / gridY);
    }
  }
  for (let iy = 0; iy < gridY; iy++) {
    for (let ix = 0; ix < gridX; ix++) {
      const a = ix + gridX1 * iy;
      const b = ix + gridX1 * (iy + 1);
      const c = ix + 1 + gridX1 * (iy + 1);
      const d = ix + 1 + gridX1 * iy;
      indices.push(a, b, d);
      indices.push(b, c, d);
    }
  }
  for (let i = 0, l = indices.length; i < l; i += 3) {
    const a = indices[i];
    const b = indices[i + 1];
    const c = indices[i + 2];
    wireframeIndexes.push(a, b, b, c, c, a);
  }
  return {
    uvs: {
      data: uvs,
      size: 2
    },
    elements: {
      data: indices,
      count: indices.length
    },
    wireframeElements: {
      data: wireframeIndexes,
      count: wireframeIndexes.length
    },
    position: {
      data: vertices,
      size: 3
    },
    positionLow: {
      data: verticesLow,
      size: 3
    }
  };
}

class Base {
  constructor(gl, vShader, fShader, modules) {
    this.vertShader = "";
    this.fragShader = "";
    if (vShader) {
      this.vertShader = vShader;
    }
    if (fShader) {
      this.fragShader = fShader;
    }
    this.program = createProgram(
      gl,
      injectShaderModule(this.vertShader, modules),
      this.fragShader
    );
    this.gl = gl;
    this.textureUnit = 0;
    this.uniformSetters = this.createUniformSetters();
    this.attribSetters = this.createAttributeSetters();
    this.transfromStack = [];
  }
  active() {
    this.gl.useProgram(this.program);
    return this;
  }
  deactive() {
    this.gl.deleteProgram(this.program);
    return this;
  }
  getBindPointForSamplerType(gl, type) {
    if (type === gl.SAMPLER_2D) {
      return gl.TEXTURE_2D;
    }
    if (type === gl.SAMPLER_CUBE) {
      return gl.TEXTURE_CUBE_MAP;
    }
    return void 0;
  }
  createUniformSetter(program, uniformInfo) {
    const { gl } = this;
    const location = gl.getUniformLocation(program, uniformInfo.name);
    const type = uniformInfo.type;
    const isArray = uniformInfo.size > 1 && uniformInfo.name.substr(-3) === "[0]";
    if (type === gl.FLOAT && isArray) {
      return function(v) {
        gl.uniform1fv(location, v);
      };
    }
    if (type === gl.FLOAT) {
      return function(v) {
        gl.uniform1f(location, v);
      };
    }
    if (type === gl.FLOAT_VEC2) {
      return function(v) {
        gl.uniform2fv(location, v);
      };
    }
    if (type === gl.FLOAT_VEC3) {
      return function(v) {
        gl.uniform3fv(location, v);
      };
    }
    if (type === gl.FLOAT_VEC4) {
      return function(v) {
        gl.uniform4fv(location, v);
      };
    }
    if (type === gl.INT && isArray) {
      return function(v) {
        gl.uniform1iv(location, v);
      };
    }
    if (type === gl.INT) {
      return function(v) {
        gl.uniform1i(location, v);
      };
    }
    if (type === gl.INT_VEC2) {
      return function(v) {
        gl.uniform2iv(location, v);
      };
    }
    if (type === gl.INT_VEC3) {
      return function(v) {
        gl.uniform3iv(location, v);
      };
    }
    if (type === gl.INT_VEC4) {
      return function(v) {
        gl.uniform4iv(location, v);
      };
    }
    if (type === gl.BOOL) {
      return function(v) {
        gl.uniform1iv(location, v);
      };
    }
    if (type === gl.BOOL_VEC2) {
      return function(v) {
        gl.uniform2iv(location, v);
      };
    }
    if (type === gl.BOOL_VEC3) {
      return function(v) {
        gl.uniform3iv(location, v);
      };
    }
    if (type === gl.BOOL_VEC4) {
      return function(v) {
        gl.uniform4iv(location, v);
      };
    }
    if (type === gl.FLOAT_MAT2) {
      return function(v) {
        gl.uniformMatrix2fv(location, false, v);
      };
    }
    if (type === gl.FLOAT_MAT3) {
      return function(v) {
        gl.uniformMatrix3fv(location, false, v);
      };
    }
    if (type === gl.FLOAT_MAT4) {
      return function(v) {
        gl.uniformMatrix4fv(location, false, v);
      };
    }
    if ((type === gl.SAMPLER_2D || type === gl.SAMPLER_CUBE) && isArray) {
      const units = [];
      for (let ii = 0; ii < uniformInfo.size; ++ii) {
        units.push(this.textureUnit++);
      }
      return function(bindPoint, units2) {
        return function(textures) {
          gl.uniform1iv(location, units2);
          textures.forEach(function(texture, index) {
            gl.activeTexture(gl.TEXTURE0 + units2[index]);
            if (bindPoint !== void 0) {
              gl.bindTexture(bindPoint, texture);
            }
          });
        };
      }(this.getBindPointForSamplerType(gl, type), units);
    }
    if (type === gl.SAMPLER_2D || type === gl.SAMPLER_CUBE) {
      return function(bindPoint, unit) {
        return function(texture) {
          gl.uniform1i(location, unit);
          gl.activeTexture(gl.TEXTURE0 + unit);
          if (bindPoint !== void 0) {
            gl.bindTexture(bindPoint, texture);
          }
        };
      }(this.getBindPointForSamplerType(gl, type), this.textureUnit++);
    }
    throw new Error("unknown type: 0x" + type.toString(16));
  }
  createUniformSetters() {
    const { gl } = this;
    this.textureUnit = 0;
    const uniformSetters = {};
    if (this.program !== null) {
      const numUniforms = gl.getProgramParameter(
        this.program,
        gl.ACTIVE_UNIFORMS
      );
      for (let ii = 0; ii < numUniforms; ++ii) {
        const uniformInfo = gl.getActiveUniform(
          this.program,
          ii
        );
        if (!uniformInfo) {
          break;
        }
        let name = uniformInfo.name;
        if (name.substr(-3) === "[0]") {
          name = name.substr(0, name.length - 3);
        }
        const setter = this.createUniformSetter(this.program, uniformInfo);
        uniformSetters[name] = setter;
      }
    }
    return uniformSetters;
  }
  createAttribSetter(index) {
    const { gl } = this;
    return function(b) {
      gl.bindBuffer(gl.ARRAY_BUFFER, b.buffer);
      gl.enableVertexAttribArray(index);
      if (b.numComponents !== void 0 || b.size !== void 0) {
        gl.vertexAttribPointer(
          index,
          b.numComponents || b.size,
          b.type || gl.FLOAT,
          b.normalize || false,
          b.stride || 0,
          b.offset || 0
        );
      }
    };
  }
  createAttributeSetters() {
    const { gl } = this;
    const attribSetters = {};
    if (this.program !== null) {
      const numAttribs = gl.getProgramParameter(
        this.program,
        gl.ACTIVE_ATTRIBUTES
      );
      for (let ii = 0; ii < numAttribs; ++ii) {
        const attribInfo = gl.getActiveAttrib(
          this.program,
          ii
        );
        if (!attribInfo) {
          break;
        }
        const index = gl.getAttribLocation(this.program, attribInfo.name);
        attribSetters[attribInfo.name] = this.createAttribSetter(index);
      }
    }
    return attribSetters;
  }
  setAttributes(attribs, setters) {
    if (setters) {
      setters = setters.attribSetters || setters;
    } else {
      setters = this.attribSetters;
    }
    Object.keys(attribs).forEach(function(name) {
      const setter = setters[name];
      if (setter) {
        setter(attribs[name]);
      }
    });
    return this;
  }
  setUniforms(values, setters) {
    if (setters) {
      setters = setters.uniformSetters || setters;
    } else {
      setters = this.uniformSetters;
    }
    Object.keys(values).forEach(function(name) {
      const setter = setters[name];
      if (setter) {
        setter(values[name]);
      }
    });
    return this;
  }
  elements(element) {
    if (!this.elementsBuffer) {
      this.elementsBuffer = this.gl.createBuffer();
    }
    this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.elementsBuffer);
    if (element.data) {
      this.gl.bufferData(
        this.gl.ELEMENT_ARRAY_BUFFER,
        element.data,
        element.usage || this.gl.STATIC_DRAW
      );
    }
    if (element.count !== void 0) {
      this.runTimes(element.count);
    }
    if (element.primitive) {
      this.setPrimitive(element.primitive);
    }
    return this;
  }
  clear(color) {
    clearScene(this.gl, color);
    this.transfromStack = [];
    return this;
  }
  runTimes(count) {
    this.count = count || 0;
    return this;
  }
  setPrimitive(primitive) {
    this.primitive = primitive || this.gl.TRIANGLES;
    return this;
  }
  resize(width, height) {
    if (width === void 0 || height === void 0) {
      resizeCanvasSize(this.gl.canvas);
      this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height);
    } else {
      this.gl.viewport(0, 0, width, height);
    }
    return this;
  }
  draw() {
    throw new Error("should override");
  }
  translate() {
    throw new Error("should override");
  }
  rotate() {
    throw new Error("should override");
  }
  scale() {
    throw new Error("should override");
  }
  destroyed() {
    throw new Error("should override");
  }
}

var FillFrag$1 = "precision highp float;\n#define GLSLIFY 1\nuniform sampler2D u_image;uniform sampler2D u_color_ramp;uniform vec2 u_image_res;uniform vec2 u_range;uniform vec2 u_color_range;uniform vec2 u_display_range;uniform float u_opacity;varying vec2 v_tex_pos;float calcTexture(const vec2 uv){return texture2D(u_image,uv).r;}float bilinear(const vec2 uv){vec2 px=1.0/u_image_res;vec2 vc=(floor(uv*u_image_res))*px;vec2 f=fract(uv*u_image_res);float tl=calcTexture(vc);float tr=calcTexture(vc+vec2(px.x,0));float bl=calcTexture(vc+vec2(0,px.y));float br=calcTexture(vc+px);return mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);}float getValue(const vec2 uv){float min=u_range.x;float max=u_range.y;float r=bilinear(uv);return r*(max-min)+min;}const float PI=3.14159265359;vec2 mercatorToWGS84(vec2 xy){float y=radians(180.0-xy.y*360.0);y=360.0/PI*atan(exp(y))-90.0;y=y/-180.0+0.5;return vec2(xy.x,y);}void main(){vec2 globalWGS84=mercatorToWGS84(v_tex_pos);float value=getValue(globalWGS84);float value_t=(value-u_color_range.x)/(u_color_range.y-u_color_range.x);vec2 ramp_pos=vec2(fract(16.0*value_t),floor(16.0*value_t)/16.0);vec4 color=texture2D(u_color_ramp,ramp_pos);bool display=value<u_display_range.y&&value>u_display_range.x;if(display){gl_FragColor=vec4(floor(255.0*color*u_opacity)/255.0);}else{gl_FragColor=vec4(0.0,0.0,0.0,0.0);}}"; // eslint-disable-line

var FillVert$1 = "#define GLSLIFY 1\nattribute vec3 instancePositions;attribute vec3 instancePositions64Low;attribute vec2 a_texCoord;uniform mat4 u_matrix;uniform vec4 u_cameraEye;uniform vec4 u_cameraEye64Low;uniform float u_offset;uniform sampler2D u_image;uniform vec2 u_image_res;uniform vec2 u_range;uniform vec2 u_mapping_range;varying vec2 v_tex_pos;varying float v_value;float calcTexture(const vec2 uv){return texture2D(u_image,uv).r;}float bilinear(const vec2 uv){vec2 px=1.0/u_image_res;vec2 vc=(floor(uv*u_image_res))*px;vec2 f=fract(uv*u_image_res);float tl=calcTexture(vc);float tr=calcTexture(vc+vec2(px.x,0));float bl=calcTexture(vc+vec2(0,px.y));float br=calcTexture(vc+px);return mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);}float getValue(const vec2 uv){float min=u_mapping_range.x;float max=u_mapping_range.y;float r=bilinear(uv);return r*(max-min)+min;}const float PI=3.14159265359;vec2 mercatorToWGS84(vec2 xy){float y=radians(180.0-xy.y*360.0);y=360.0/PI*atan(exp(y))-90.0;y=y/-180.0+0.5;return vec2(xy.x,y);}\n#modules-transformZ\nvoid main(){v_tex_pos=a_texCoord;vec2 globalWGS84=mercatorToWGS84(v_tex_pos);float value=getValue(globalWGS84);float z=transformZ(value,instancePositions);vec4 pos=vec4(instancePositions-u_cameraEye.xyz,0.0);pos+=vec4(instancePositions64Low-u_cameraEye64Low.xyz,0.0);\n#modules-project\n}"; // eslint-disable-line

class Fill extends Base {
  constructor(gl, vShader, fShader, modules) {
    super(gl, vShader || FillVert$1, fShader || FillFrag$1, modules || {});
    this.vertShader = FillVert$1;
    this.fragShader = FillFrag$1;
  }
  draw() {
    if (this.checkExt !== void 0) {
      const primitiveType = this.primitive || this.gl.TRIANGLES;
      if (this.checkExt) {
        this.gl.drawElements(
          primitiveType,
          this.count,
          this.gl.UNSIGNED_INT,
          0
        );
      } else {
        this.gl.drawElements(
          primitiveType,
          this.count,
          this.gl.UNSIGNED_SHORT,
          0
        );
      }
    } else {
      this.checkExt = this.gl.getExtension("OES_element_index_uint");
    }
    return this;
  }
  translate() {
    return this;
  }
  rotate() {
    return this;
  }
  scale() {
    return this;
  }
}

function parseColorStyle(styleAttrField) {
  if (Array.isArray(styleAttrField) && styleAttrField.length > 3) {
    const type = styleAttrField[0];
    const action = styleAttrField[1];
    const interpolateColor = [];
    for (let i = 3; i < styleAttrField.length; i += 2) {
      const val = styleAttrField[i];
      const color = styleAttrField[i + 1];
      interpolateColor.push({
        key: val,
        value: color
      });
    }
    return {
      operator: type,
      interpolation: {
        name: action[0],
        base: action[1]
      },
      input: interpolateColor
    };
  } else {
    console.warn("[wind-core]: style-parser style config invalid");
    return {};
  }
}
function parseZoomStyle(styleAttrField) {
  if (Array.isArray(styleAttrField) && styleAttrField.length > 3) {
    const type = styleAttrField[0];
    const action = styleAttrField[1];
    const interpolateZoom = [];
    for (let i = 3; i < styleAttrField.length; i += 2) {
      const val = styleAttrField[i];
      const color = styleAttrField[i + 1];
      interpolateZoom.push({
        key: val,
        value: color
      });
    }
    return {
      operator: type,
      interpolation: {
        name: action[0],
        base: action[1]
      },
      input: interpolateZoom
    };
  } else {
    console.warn("[wind-core]: style-parser style config invalid");
    return {};
  }
}
function createLinearGradient(range, styleAttrField) {
  const canvas = document.createElement("canvas");
  const ctx = canvas.getContext("2d");
  canvas.width = 256;
  canvas.height = 1;
  const { input: interpolateColor } = parseColorStyle(styleAttrField);
  if (ctx && interpolateColor && Array.isArray(interpolateColor)) {
    const keys = interpolateColor.map((d) => parseFloat(d.key));
    const colorRange = [Math.min(...keys), Math.max(...keys)];
    const [min, max] = [range[0] || colorRange[0], range[1] || colorRange[1]];
    const gradient = ctx.createLinearGradient(0, 0, 256, 0);
    for (let i = 0; i < interpolateColor.length; i += 1) {
      const key = interpolateColor[i].key;
      const color = interpolateColor[i].value;
      gradient.addColorStop((key - min) / (max - min), color);
    }
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, 256, 1);
    return {
      data: new Uint8Array(ctx.getImageData(0, 0, 256, 1).data),
      colorRange
    };
  } else {
    return {};
  }
}
function exponentialInterpolation(input, base, lowerValue, upperValue) {
  const difference = upperValue - lowerValue;
  const progress = input - lowerValue;
  if (difference === 0) {
    return 0;
  } else if (base === 1) {
    return progress / difference;
  } else {
    return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);
  }
}
function interpolationFactor(interpolation, input, lower, upper) {
  let t = 0;
  if (interpolation.name === "exponential") {
    t = exponentialInterpolation(input, interpolation.base, lower, upper);
  } else if (interpolation.name === "linear") {
    t = exponentialInterpolation(input, 1, lower, upper);
  } else if (interpolation.name === "cubic-bezier") {
    console.warn("interpolationFactor");
  }
  return t;
}
function interpolateNumber(a, b, t) {
  return a * (1 - t) + b * t;
}
const cachedStyle = {};
function createZoom(uid, zoom, key, styles, clearCache) {
  const ukey = `${uid}_${key}`;
  const styleAttrField = styles[key];
  if (isNumber(styleAttrField)) {
    if (cachedStyle[ukey]) {
      delete cachedStyle[ukey];
    }
    return styleAttrField;
  }
  if (styleAttrField && Array.isArray(styleAttrField) && (!cachedStyle[ukey] || clearCache)) {
    cachedStyle[ukey] = parseZoomStyle(styleAttrField);
  }
  if (cachedStyle[ukey]) {
    const { input: interpolateZoom, interpolation } = cachedStyle[ukey] || {};
    if (interpolateZoom && Array.isArray(interpolateZoom)) {
      const labels = interpolateZoom.map((i) => i.key);
      const outputs = interpolateZoom.map((i) => i.value);
      if (zoom <= labels[0]) {
        return outputs[0];
      }
      const stopCount = labels.length;
      if (zoom >= labels[stopCount - 1]) {
        return outputs[stopCount - 1];
      }
      const index = findStopLessThanOrEqualTo(labels, zoom);
      const idx = labels.length - 1;
      const lower = labels[index];
      const upper = labels[index >= idx ? idx : index + 1];
      const t = interpolationFactor(interpolation, zoom, lower, upper);
      const outputLower = outputs[index];
      const outputUpper = outputs[index >= idx ? idx : index + 1];
      return interpolateNumber(outputLower, outputUpper, t);
    } else {
      return 1;
    }
  }
  return 1;
}

var FillFrag = "precision highp float;\n#define GLSLIFY 1\nuniform sampler2D u_wind;uniform sampler2D u_color_ramp;uniform vec2 u_image_res;uniform vec2 u_wind_min;uniform vec2 u_wind_max;uniform vec2 u_color_range;uniform vec2 u_display_range;uniform float u_opacity;varying vec2 v_tex_pos;vec2 windTexture(const vec2 uv){return texture2D(u_wind,uv).rg;}float bilinearU(const vec2 uv){vec2 px=1.0/u_image_res;vec2 vc=(floor(uv*u_image_res))*px;vec2 f=fract(uv*u_image_res);float tl=windTexture(vc).r;float tr=windTexture(vc+vec2(px.x,0)).r;float bl=windTexture(vc+vec2(0,px.y)).r;float br=windTexture(vc+px).r;return mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);}float bilinearV(const vec2 uv){vec2 px=1.0/u_image_res;vec2 vc=(floor(uv*u_image_res))*px;vec2 f=fract(uv*u_image_res);float tl=windTexture(vc).g;float tr=windTexture(vc+vec2(px.x,0.0)).g;float bl=windTexture(vc+vec2(0.0,px.y)).g;float br=windTexture(vc+px).g;return mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);}float getV(const vec2 uv){float min=u_wind_min.y;float max=u_wind_max.y;float r=bilinearV(uv);return r*(max-min)+min;}float getU(const vec2 uv){float min=u_wind_min.x;float max=u_wind_max.x;float r=bilinearU(uv);return r*(max-min)+min;}float windSpeed(const vec2 uv){float u=getU(uv);float v=getV(uv);return length(vec2(u,v));}const float PI=3.14159265359;vec2 mercatorToWGS84(vec2 xy){float y=radians(180.0-xy.y*360.0);y=360.0/PI*atan(exp(y))-90.0;y=y/-180.0+0.5;return vec2(xy.x,y);}void main(){vec2 globalWGS84=mercatorToWGS84(v_tex_pos);float value=windSpeed(globalWGS84);float value_t=(value-u_color_range.x)/(u_color_range.y-u_color_range.x);vec2 ramp_pos=vec2(fract(16.0*value_t),floor(16.0*value_t)/16.0);vec4 color=texture2D(u_color_ramp,ramp_pos);bool display=value<u_display_range.y&&value>u_display_range.x;if(display){gl_FragColor=vec4(floor(255.0*color*u_opacity)/255.0);}else{gl_FragColor=vec4(0.0,0.0,0.0,0.0);}}"; // eslint-disable-line

var FillVert = "#define GLSLIFY 1\nattribute vec3 instancePositions;attribute vec3 instancePositions64Low;attribute vec2 a_texCoord;uniform mat4 u_matrix;uniform vec4 u_cameraEye;uniform vec4 u_cameraEye64Low;uniform float u_offset;uniform sampler2D u_wind;uniform vec2 u_image_res;uniform vec2 u_wind_min;uniform vec2 u_wind_max;uniform vec2 u_mapping_range;varying vec2 v_tex_pos;varying float v_value;vec2 windTexture(const vec2 uv){return texture2D(u_wind,uv).rg;}float bilinearU(const vec2 uv){vec2 px=1.0/u_image_res;vec2 vc=(floor(uv*u_image_res))*px;vec2 f=fract(uv*u_image_res);float tl=windTexture(vc).r;float tr=windTexture(vc+vec2(px.x,0)).r;float bl=windTexture(vc+vec2(0,px.y)).r;float br=windTexture(vc+px).r;return mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);}float bilinearV(const vec2 uv){vec2 px=1.0/u_image_res;vec2 vc=(floor(uv*u_image_res))*px;vec2 f=fract(uv*u_image_res);float tl=windTexture(vc).g;float tr=windTexture(vc+vec2(px.x,0.0)).g;float bl=windTexture(vc+vec2(0.0,px.y)).g;float br=windTexture(vc+px).g;return mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);}float getV(const vec2 uv){float min=u_wind_min.y;float max=u_wind_max.y;float r=bilinearV(uv);return r*(max-min)+min;}float getU(const vec2 uv){float min=u_wind_min.x;float max=u_wind_max.x;float r=bilinearU(uv);return r*(max-min)+min;}float windSpeed(const vec2 uv){float u=getU(uv);float v=getV(uv);float min=u_mapping_range.x;float max=u_mapping_range.y;float val=length(vec2(u,v));return val*(max-min)+min;}const float PI=3.14159265359;vec2 mercatorToWGS84(vec2 xy){float y=radians(180.0-xy.y*360.0);y=360.0/PI*atan(exp(y))-90.0;y=y/-180.0+0.5;return vec2(xy.x,y);}\n#modules-transformZ\nvoid main(){v_tex_pos=a_texCoord;vec2 globalWGS84=mercatorToWGS84(v_tex_pos);float value=windSpeed(globalWGS84);float z=transformZ(value,instancePositions);vec4 pos=vec4(instancePositions-u_cameraEye.xyz,0.0);pos+=vec4(instancePositions64Low-u_cameraEye64Low.xyz,0.0);\n#modules-project\n}"; // eslint-disable-line

class WindFill extends Base {
  constructor(gl, vShader, fShader, modules) {
    super(gl, vShader || FillVert, fShader || FillFrag, modules || {});
    this.vertShader = FillVert;
    this.fragShader = FillFrag;
  }
  draw() {
    if (this.checkExt !== void 0) {
      const primitiveType = this.primitive || this.gl.TRIANGLES;
      if (this.checkExt) {
        this.gl.drawElements(
          primitiveType,
          this.count,
          this.gl.UNSIGNED_INT,
          0
        );
      } else {
        this.gl.drawElements(
          primitiveType,
          this.count,
          this.gl.UNSIGNED_SHORT,
          0
        );
      }
    } else {
      this.checkExt = this.gl.getExtension("OES_element_index_uint");
    }
    return this;
  }
  translate() {
    return this;
  }
  rotate() {
    return this;
  }
  scale() {
    return this;
  }
  destroyed() {
  }
}

const defaultOptions$2 = {
  renderForm: "r",
  styleSpec: {
    "fill-color": [
      "interpolate",
      ["linear"],
      ["get", "value"],
      0,
      "#3288bd",
      10,
      "#66c2a5",
      20,
      "#abdda4",
      30,
      "#e6f598",
      40,
      "#fee08b",
      50,
      "#fdae61",
      60,
      "#f46d43",
      100,
      "#d53e4f"
    ],
    opacity: 1
  },
  displayRange: [Infinity, Infinity],
  mappingRange: [0, 0],
  widthSegments: 1,
  heightSegments: 1,
  wireframe: false,
  createPlaneBuffer: (points, widthSegments, heightSegments) => {
    const [startX, endX, startY, endY] = [
      points[0][0],
      points[2][0],
      points[0][1],
      points[1][1]
    ];
    return getPlaneBuffer(
      startX,
      endX,
      startY,
      endY,
      widthSegments,
      heightSegments
    );
  },
  injectShaderModules: {
    "#modules-transformZ": `
float transformZ(float value, vec3 pos) {
  return 0.0;
}
    `,
    "#modules-project": `
gl_Position = u_matrix * vec4(pos.xy + vec2(u_offset, 0.0), pos.z + z, 1.0);
    `
  }
};
let uid$1 = 0;
class ScalarFill {
  constructor(gl, options) {
    this.gl = gl;
    this.uid = `ScalarFill_${uid$1}`;
    uid$1++;
    if (!this.gl) {
      throw new Error("initialize error");
    }
    if (!options) {
      options = {};
    }
    this.options = {
      ...defaultOptions$2,
      ...options
    };
    this.opacity = this.options.opacity || 1;
  }
  updateOptions(options) {
    this.options = {
      ...this.options,
      ...options
    };
    this.buildColorRamp();
    if (typeof this.options.getZoom === "function") {
      this.setOpacity(
        createZoom(
          this.uid,
          this.options.getZoom(),
          "opacity",
          this.options.styleSpec,
          true
        )
      );
    }
  }
  setFillColor() {
    this.buildColorRamp();
  }
  setOpacity(opacity) {
    this.opacity = opacity;
  }
  handleZoom() {
    if (typeof this.options.getZoom === "function") {
      this.setOpacity(
        createZoom(
          this.uid,
          this.options.getZoom(),
          "opacity",
          this.options.styleSpec
        )
      );
    }
  }
  buildColorRamp() {
    var _a;
    const { data, colorRange } = createLinearGradient(
      [],
      (_a = this.options.styleSpec) == null ? void 0 : _a["fill-color"]
    );
    if (colorRange) {
      this.colorRange = colorRange;
    }
    if (data) {
      this.colorRampTexture = createTexture(
        this.gl,
        this.gl.NEAREST,
        data,
        16,
        16
      );
    }
  }
  initialize(gl) {
    if (!this.drawCommand) {
      if (this.options.renderForm === "rg") {
        this.drawCommand = new WindFill(
          gl,
          void 0,
          void 0,
          this.options.injectShaderModules
        );
      } else if (this.options.renderForm === "r") {
        this.drawCommand = new Fill(
          gl,
          void 0,
          void 0,
          this.options.injectShaderModules
        );
      } else {
        console.warn("This type is not supported temporarily");
      }
    }
    this.buildColorRamp();
    if (typeof this.options.getZoom === "function") {
      this.setOpacity(
        createZoom(
          this.uid,
          this.options.getZoom(),
          "opacity",
          this.options.styleSpec
        )
      );
    }
  }
  initializeVertex(coordinates) {
    let i = 0;
    const len = coordinates.length;
    const points = [];
    for (; i < len; i++) {
      const coords = coordinates[i];
      const mc = this.getMercatorCoordinate(coords);
      points.push([mc[0], mc[1]]);
    }
    const buffers = (this.options.createPlaneBuffer || defaultOptions$2.createPlaneBuffer)(
      points,
      this.options.widthSegments || 1,
      this.options.heightSegments || 1
    );
    return {
      indexes: buffers.elements.data,
      wireframeIndexes: buffers.wireframeElements.data,
      quadBuffer: createBuffer(
        this.gl,
        new Float32Array(buffers.position.data)
      ),
      quad64LowBuffer: createBuffer(
        this.gl,
        new Float32Array(buffers.positionLow.data)
      ),
      texCoordBuffer: createBuffer(this.gl, new Float32Array(buffers.uvs.data))
    };
  }
  getTextureData(data) {
    return new Promise((resolve, reject) => {
      if (data.type === "image" && data.url) {
        loadImage(data.url).then((image) => {
          const processedData = {
            width: image.width,
            height: image.height,
            texture: createTexture(
              this.gl,
              this.gl.LINEAR,
              image,
              image.width,
              image.height
            ),
            ...this.initializeVertex(data.extent)
          };
          if (this.options.renderForm === "rg") {
            processedData.uMin = data.uMin;
            processedData.uMax = data.uMax;
            processedData.vMin = data.vMin;
            processedData.vMax = data.vMax;
          } else if (this.options.renderForm === "r") {
            processedData.min = data.min;
            processedData.max = data.max;
          } else {
            console.warn("This type is not supported temporarily");
          }
          resolve(processedData);
        }).catch((error) => reject(error));
      } else if (data.type === "jsonArray" && data.data) {
        const gfsData = data.data;
        let pos;
        if (data.extent) {
          pos = data.extent;
        } else {
          pos = [
            [gfsData[0].header.lo1, gfsData[0].header.la1],
            [gfsData[0].header.lo1, gfsData[0].header.la2],
            [gfsData[0].header.lo2, gfsData[0].header.la1],
            [gfsData[0].header.lo2, gfsData[0].header.la2]
          ];
        }
        const processedData = {
          width: gfsData[0].header.nx,
          height: gfsData[0].header.ny,
          ...this.initializeVertex(pos)
        };
        if (!this.worker) {
          this.worker = new WorkerFactory();
          this.worker.addEventListener("message", ({ data: payload }) => {
            if (this.options.renderForm === "rg") {
              processedData.uMin = payload[1];
              processedData.uMax = payload[2];
              processedData.vMin = payload[3];
              processedData.vMax = payload[4];
              processedData.texture = createTexture(
                this.gl,
                this.gl.LINEAR,
                new Uint8Array(payload[0]),
                processedData.width,
                processedData.height
              );
            } else if (this.options.renderForm === "r") {
              processedData.min = payload[1];
              processedData.max = payload[2];
              processedData.texture = createTexture(
                this.gl,
                this.gl.LINEAR,
                new Uint8Array(payload[0]),
                processedData.width,
                processedData.height
              );
            } else {
              console.warn("This type is not supported temporarily");
            }
            resolve(processedData);
          });
        }
        if (this.options.renderForm === "rg") {
          let uComp;
          let vComp;
          gfsData.forEach((record) => {
            switch (record.header.parameterCategory + "," + record.header.parameterNumber) {
              case "1,2":
              case "2,2":
                uComp = record;
                break;
              case "1,3":
              case "2,3":
                vComp = record;
                break;
            }
          });
          const u = new Float32Array(uComp.data);
          const v = new Float32Array(vComp.data);
          this.worker.postMessage(["rg", u, v]);
        } else if (this.options.renderForm === "r") {
          const singleData = new Float32Array(gfsData[0].data);
          this.worker.postMessage(["r", singleData]);
        } else {
          console.warn("This type is not supported temporarily");
        }
      }
    });
  }
  setData(data, cb) {
    if (this.gl && data) {
      this.getTextureData(data).then((d) => {
        this.data = d;
        cb && cb(true);
        if (this.data) {
          this.initialize(this.gl);
        }
        if (this.options.triggerRepaint) {
          this.handleZoom();
          this.options.triggerRepaint();
        }
      }).catch((error) => {
        cb && cb(false);
        console.error(error);
      });
    }
  }
  getData() {
    return this.data;
  }
  getMercatorCoordinate([lng, lat]) {
    return [lng, lat];
  }
  prerender() {
  }
  render(matrix, offsetX, cameraParams) {
    if (this.data && this.drawCommand && this.data.texture && this.colorRampTexture) {
      const opacity = this.opacity;
      const uniforms = {
        u_opacity: isNumber(opacity) ? opacity : 1,
        u_image_res: [this.data.width, this.data.height],
        u_matrix: matrix,
        u_offset: isNumber(offsetX) ? offsetX : 0,
        u_color_ramp: this.colorRampTexture,
        u_color_range: this.colorRange,
        u_mapping_range: this.options.mappingRange || [0, 0]
      };
      if (cameraParams) {
        uniforms.u_cameraEye = cameraParams.cameraEye;
        uniforms.u_cameraEye64Low = cameraParams.cameraEye64Low;
      }
      if (this.options.renderForm === "rg") {
        uniforms.u_wind_min = [this.data.uMin, this.data.vMin];
        uniforms.u_wind_max = [this.data.uMax, this.data.vMax];
        uniforms.u_wind = this.data.texture;
        const speeds = [
          Math.sqrt(
            this.data.uMin * this.data.uMin + this.data.vMin * this.data.vMin
          ),
          Math.sqrt(
            this.data.uMin * this.data.uMin + this.data.vMax * this.data.vMax
          ),
          Math.sqrt(
            this.data.uMax * this.data.uMax + this.data.vMax * this.data.vMax
          ),
          Math.sqrt(
            this.data.uMax * this.data.uMax + this.data.vMin * this.data.vMin
          )
        ];
        const min = 0;
        const max = Math.max(...speeds);
        uniforms.u_display_range = this.options.displayRange || [min, max];
      } else if (this.options.renderForm === "r") {
        uniforms.u_range = [this.data.min, this.data.max];
        uniforms.u_image = this.data.texture;
        uniforms.u_display_range = this.options.displayRange || [
          uniforms.u_range[0] - 1,
          uniforms.u_range[1] + 1
        ];
      } else {
        console.warn("This type is not supported temporarily");
      }
      const depthEnabled = this.gl.isEnabled(this.gl.DEPTH_TEST);
      this.gl.enable(this.gl.DEPTH_TEST);
      this.gl.depthMask(true);
      this.gl.depthFunc(this.gl.LEQUAL);
      const data = this.options.wireframe ? this.data.wireframeIndexes : this.data.indexes;
      this.drawCommand.active().setUniforms(uniforms).setAttributes({
        instancePositions: {
          buffer: this.data.quadBuffer,
          numComponents: 3
        },
        instancePositions64Low: {
          buffer: this.data.quad64LowBuffer,
          numComponents: 3
        },
        a_texCoord: {
          buffer: this.data.texCoordBuffer,
          numComponents: 2
        }
      }).elements({
        data: new Uint32Array(data),
        primitive: this.options.wireframe ? this.gl.LINES : this.gl.TRIANGLES,
        count: data == null ? void 0 : data.length,
        usage: this.gl.STATIC_DRAW
      }).draw();
      if (!depthEnabled) {
        this.gl.disable(this.gl.DEPTH_TEST);
      }
    }
  }
  postrender() {
  }
  destroyData() {
    if (this.data) ;
  }
  destroyed() {
    this.destroyData();
    if (this.worker) {
      this.worker.terminate();
    }
  }
}

var drawFrag = "precision highp float;\n#define GLSLIFY 1\nuniform sampler2D u_wind;uniform vec2 u_wind_res;uniform vec4 u_wind_range;uniform vec2 u_color_range;uniform sampler2D u_color_ramp;varying vec2 v_particle_pos;vec2 decodeValue(const vec2 uv){vec4 u_color=texture2D(u_wind,uv);float u=u_wind_range[0]+((u_wind_range[1]-u_wind_range[0])*(u_color.r*255.0-1.0))/254.0;float v=u_wind_range[2]+((u_wind_range[3]-u_wind_range[2])*(u_color.g*255.0-1.0))/254.0;return vec2(u,v);}vec2 lookup_wind(const vec2 uv){vec2 px=1.0/u_wind_res;vec2 vc=(floor(uv*u_wind_res))*px;vec2 f=fract(uv*u_wind_res);vec2 tl=decodeValue(vc);vec2 tr=decodeValue(vc+vec2(px.x,0));vec2 bl=decodeValue(vc+vec2(0,px.y));vec2 br=decodeValue(vc+px);return mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);}void main(){vec2 velocity=lookup_wind(v_particle_pos);float speed_t=length(velocity);float value_t=(speed_t-u_color_range.x)/(u_color_range.y-u_color_range.x);vec2 ramp_pos=vec2(fract(16.0*value_t),floor(16.0*value_t)/16.0);vec4 color=texture2D(u_color_ramp,ramp_pos);gl_FragColor=vec4(floor(255.0*color*color.a)/255.0);}"; // eslint-disable-line

var drawVert = "#define GLSLIFY 1\nattribute float a_index;uniform sampler2D u_particles_current;uniform sampler2D u_particles_next;uniform float u_particles_res;uniform vec2 u_world;uniform float u_zoom;uniform vec4 u_bbox;uniform float u_offset;uniform float u_width;uniform float u_aspectRatio;uniform mat4 u_matrix;varying vec2 v_particle_pos;const vec2 bitEnc=vec2(1.0,255.0);const vec2 bitDec=1.0/bitEnc;vec2 fromRGBA(const vec4 color){vec4 rounded_color=floor(color*255.0+0.5)/255.0;float x=dot(rounded_color.rg,bitDec);float y=dot(rounded_color.ba,bitDec);return vec2(x,y);}vec4 buildOffset(vec2 perp){vec2 normal=perp*u_width;normal.x/=u_aspectRatio;return vec4(normal,0.0,0.0);}vec4 buildOffset(vec2 perp,vec2 scale){vec2 normal=perp/scale*u_width;normal.x/=u_aspectRatio;return vec4(normal,0.0,0.0);}vec4 getPosWithProject(vec2 current_pos,vec2 next_pos,float v_index){vec4 currentProjected=u_matrix*vec4(current_pos,0.0,1.0);vec4 nextProjected=u_matrix*vec4(next_pos,0.0,1.0);vec2 currentScreen=currentProjected.xy/currentProjected.w*u_world;vec2 nextScreen=nextProjected.xy/nextProjected.w*u_world;vec2 dir=normalize(nextScreen-currentScreen);vec2 perp=vec2(-dir.y,dir.x);float d=length(nextScreen-currentScreen);vec4 pos=currentProjected;if(a_index-v_index*6.0==0.0){pos=currentProjected+buildOffset(perp);}else if(a_index-v_index*6.0==1.0){pos=currentProjected-buildOffset(perp);}else if(a_index-v_index*6.0==2.0){pos=nextProjected+buildOffset(perp);}else if(a_index-v_index*6.0==3.0){pos=nextProjected+buildOffset(perp);}else if(a_index-v_index*6.0==4.0){pos=nextProjected-buildOffset(perp);}else if(a_index-v_index*6.0==5.0){pos=currentProjected-buildOffset(perp);}if(d>20.0||d<0.01){pos.xy+=u_world*pow(2.0,u_zoom+1.0);}return pos;}void main(){float v_index=floor(a_index/6.0);float ux=fract(v_index/u_particles_res);float vy=floor(v_index/u_particles_res)/u_particles_res;vec4 current_color=texture2D(u_particles_current,vec2(ux,vy));vec4 next_color=texture2D(u_particles_next,vec2(ux,vy));vec2 v_current_particle_pos=fromRGBA(current_color);vec2 v_next_particle_pos=fromRGBA(next_color);vec2 vc_pos=u_bbox.xy+v_current_particle_pos*(u_bbox.zw-u_bbox.xy);vec2 nc_pos=u_bbox.xy+v_next_particle_pos*(u_bbox.zw-u_bbox.xy);v_particle_pos=mix(vc_pos,nc_pos,0.5);v_current_particle_pos=clamp(vc_pos,0.0,1.0)+vec2(u_offset,0.0);v_next_particle_pos=clamp(nc_pos,0.0,1.0)+vec2(u_offset,0.0);gl_PointSize=1.0;gl_Position=getPosWithProject(v_current_particle_pos,v_next_particle_pos,v_index);}"; // eslint-disable-line

var screenFrag = "precision highp float;\n#define GLSLIFY 1\nuniform sampler2D u_screen;uniform float u_opacity;uniform float u_fade;varying vec2 v_tex_pos;void main(){vec4 color=texture2D(u_screen,v_tex_pos);gl_FragColor=vec4(floor(255.0*color*u_opacity*u_fade)/255.0);}"; // eslint-disable-line

var screenVert = "#define GLSLIFY 1\nattribute vec2 a_pos;attribute vec2 a_tex_pos;varying vec2 v_tex_pos;void main(){v_tex_pos=a_tex_pos;gl_Position=vec4(a_pos*2.0-1.0,0,1);}"; // eslint-disable-line

var updateFrag = "precision highp float;\n#define GLSLIFY 1\nuniform sampler2D u_wind;uniform sampler2D u_particles;uniform vec4 u_bbox;uniform vec2 u_wind_res;uniform vec4 u_wind_range;uniform float u_rand_seed;uniform float u_nodata;uniform float u_drop_rate;uniform float u_drop_rate_bump;uniform vec2 u_speed_factor;varying vec2 v_tex_pos;const vec2 bitEnc_0=vec2(1.0,255.0);const vec2 bitDec_0=1.0/bitEnc_0;vec4 toRGBA(const vec2 pos_0){vec2 rg=bitEnc_0*pos_0.x;rg=fract(rg);rg-=rg.yy*vec2(1.0/255.0,0.0);vec2 ba=bitEnc_0*pos_0.y;ba=fract(ba);ba-=ba.yy*vec2(1.0/255.0,0.0);return vec4(rg,ba);}const vec2 bitEnc_1=vec2(1.0,255.0);const vec2 bitDec_1=1.0/bitEnc_1;vec2 fromRGBA(const vec4 color){vec4 rounded_color=floor(color*255.0+0.5)/255.0;float x=dot(rounded_color.rg,bitDec_1);float y=dot(rounded_color.ba,bitDec_1);return vec2(x,y);}const vec3 rand_constants=vec3(12.9898,78.233,4375.85453);float rand(const vec2 co){float t=dot(rand_constants.xy,co);return fract(sin(t)*(rand_constants.z+t));}vec2 decodeValue(const vec2 uv){vec4 u_color=texture2D(u_wind,uv);float u=u_wind_range[0]+((u_wind_range[1]-u_wind_range[0])*(u_color.r*255.0-1.0))/254.0;float v=u_wind_range[2]+((u_wind_range[3]-u_wind_range[2])*(u_color.g*255.0-1.0))/254.0;return vec2(u,v);}vec2 getColor(const vec2 uv){vec2 px=1.0/(u_wind_res);vec2 vc=(floor(uv*(u_wind_res)))*px;vec4 u_color=texture2D(u_wind,vc);return vec2(u_color.r,u_color.g);}vec2 lookup_wind(const vec2 uv){vec2 px=1.0/u_wind_res;vec2 vc=(floor(uv*u_wind_res))*px;vec2 f=fract(uv*u_wind_res);vec2 tl=decodeValue(vc);vec2 tr=decodeValue(vc+vec2(px.x,0));vec2 bl=decodeValue(vc+vec2(0,px.y));vec2 br=decodeValue(vc+px);return mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);}void main(){vec4 color=texture2D(u_particles,v_tex_pos);vec2 pos=fromRGBA(color);vec2 global_pos=u_bbox.xy+pos*(u_bbox.zw-u_bbox.xy);vec2 alphas=getColor(global_pos);if(alphas.x<=u_nodata||alphas.y<=u_nodata){discard;}vec2 velocity=lookup_wind(global_pos);float speed_t=length(velocity);vec2 offset=vec2(velocity.x,-velocity.y)*u_speed_factor;pos=fract(1.0+pos+offset);vec2 seed=(pos+v_tex_pos)*u_rand_seed;float drop_rate=u_drop_rate+speed_t*u_drop_rate_bump;float drop=step(1.0-drop_rate,rand(seed));vec2 random_pos=vec2(rand(seed+1.3),rand(seed+2.1));pos=mix(pos,random_pos,drop);gl_FragColor=toRGBA(pos);}"; // eslint-disable-line

var updateVert = "#define GLSLIFY 1\nattribute vec2 a_pos;varying vec2 v_tex_pos;void main(){v_tex_pos=a_pos;gl_Position=vec4(a_pos*2.0-1.0,0,1);}"; // eslint-disable-line

const defaultOptions$1 = {
  callback: () => void 0
};
class Raf {
  constructor(options = {}) {
    this.options = {
      ...defaultOptions$1,
      ...options
    };
    this.reset();
    this.animate = this.animate.bind(this);
    this.onVisibilityChange = this.onVisibilityChange.bind(this);
  }
  reset() {
    this.animating = false;
    this.isVisible = true;
    if (this.raf !== void 0) {
      cancelAnimationFrame(this.raf);
    }
  }
  start() {
    if (this.animating) {
      return;
    }
    this.animating = true;
    document.addEventListener(
      "visibilitychange",
      this.onVisibilityChange,
      false
    );
    this.raf = requestAnimationFrame(this.animate);
  }
  stop() {
    this.reset();
    document.removeEventListener(
      "visibilitychange",
      this.onVisibilityChange,
      false
    );
  }
  animate() {
    if (!this.animating || !this.isVisible) {
      return;
    }
    this.options.callback((performance || Date).now());
    this.raf = requestAnimationFrame(this.animate);
  }
  onVisibilityChange() {
    this.isVisible = !document.hidden;
    if (this.isVisible) {
      this.reset();
      this.start();
    }
  }
}

const defaultOptions = {
  styleSpec: {
    color: [
      "interpolate",
      ["linear"],
      ["get", "value"],
      0,
      "#fff",
      100,
      "#fff"
    ],
    opacity: 1,
    numParticles: 65535
  },
  opacity: 1,
  lineWidth: 2,
  speedFactor: 1,
  fadeOpacity: 0.93,
  dropRate: 3e-3,
  dropRateBump: 2e-3
};
let uid = 0;
class WindParticles {
  constructor(gl, options = {}) {
    this.gl = gl;
    this.uid = `WindParticles_${uid}`;
    uid++;
    if (!this.gl) {
      throw new Error("initialize error");
    }
    this.options = {
      ...defaultOptions,
      ...options
    };
    this.opacity = this.options.opacity || 1;
    this.visible = this.options.visible !== void 0 || true;
    this.alpha = 0.9;
    this.frameTime = 0;
    this.lastTime = 0;
    this.initialize(this.gl);
  }
  initialize(gl) {
    this.drawCommand = new Base(gl, drawVert, drawFrag);
    this.drawCommand.draw = function() {
      this.gl.drawArrays(this.primitive, 0, this.count);
    };
    this.updateCommand = new Base(gl, updateVert, updateFrag);
    this.updateCommand.draw = function() {
      this.gl.drawArrays(this.primitive, 0, 4);
    };
    this.screenCommand = new Base(gl, screenVert, screenFrag);
    this.screenCommand.draw = function() {
      this.gl.drawArrays(this.primitive, 0, 4);
    };
    this.fbo = gl.createFramebuffer();
    this.raf = new Raf({
      callback: () => {
        if (this.options.triggerRepaint) {
          this.options.triggerRepaint();
        }
      }
    });
    this.resize();
    this.buildColorRamp();
    if (typeof this.options.getZoom === "function") {
      const zoom = this.options.getZoom();
      this.setOpacity(
        createZoom(this.uid, zoom, "opacity", this.options.styleSpec)
      );
      this.numParticles = createZoom(
        this.uid,
        zoom,
        "numParticles",
        this.options.styleSpec
      );
    }
    this.start();
  }
  set numParticles(numParticles) {
    if (numParticles === void 0) {
      return;
    }
    const gl = this.gl;
    const particleRes = Math.ceil(Math.sqrt(numParticles));
    this.particleStateResolution = particleRes;
    this.privateNumParticles = particleRes * particleRes;
    const particleState = new Uint8Array(this.privateNumParticles * 4);
    for (let i = 0; i < particleState.length; i++) {
      particleState[i] = Math.floor(Math.random() * 256);
    }
    if (!this.currentParticleStateTexture) {
      this.currentParticleStateTexture = createTexture(
        gl,
        gl.NEAREST,
        particleState,
        particleRes,
        particleRes
      );
    } else {
      resizeTexture(
        gl,
        this.currentParticleStateTexture,
        particleRes,
        particleRes,
        particleState
      );
    }
    if (!this.nextParticleStateTexture) {
      this.nextParticleStateTexture = createTexture(
        gl,
        gl.NEAREST,
        particleState,
        particleRes,
        particleRes
      );
    } else {
      resizeTexture(
        gl,
        this.nextParticleStateTexture,
        particleRes,
        particleRes,
        particleState
      );
    }
    const num = this.privateNumParticles * 6;
    const particleIndices = new Float32Array(num);
    for (let i = 0; i < num; i++) {
      particleIndices[i] = i;
    }
    if (!this.particleIndexBuffer) {
      this.particleIndexBuffer = createBuffer(gl, particleIndices);
    } else {
      updateBufferData(gl, this.particleIndexBuffer, particleIndices);
    }
  }
  get numParticles() {
    return this.privateNumParticles;
  }
  updateOptions(options) {
    const styleSpec = options.styleSpec || {};
    this.options = {
      ...this.options,
      ...options,
      styleSpec: {
        ...this.options.styleSpec,
        ...styleSpec
      }
    };
    this.buildColorRamp();
    if (typeof this.options.getZoom === "function") {
      const zoom = this.options.getZoom();
      this.setOpacity(
        createZoom(this.uid, zoom, "opacity", this.options.styleSpec, true)
      );
      this.numParticles = createZoom(
        this.uid,
        zoom,
        "numParticles",
        this.options.styleSpec,
        true
      );
    }
  }
  setOpacity(opacity) {
    this.opacity = opacity;
  }
  getOpacity() {
    return this.opacity;
  }
  handleMoveend() {
    this.updateRenderState();
    clearScene(this.gl, [0, 0, 0, 0]);
  }
  handleMovestart() {
    this.alpha = 0;
  }
  handleZoom() {
    if (typeof this.options.getZoom === "function") {
      const zoom = this.options.getZoom();
      this.setOpacity(
        createZoom(this.uid, zoom, "opacity", this.options.styleSpec)
      );
      this.numParticles = createZoom(
        this.uid,
        zoom,
        "numParticles",
        this.options.styleSpec
      );
    }
  }
  buildColorRamp() {
    var _a;
    const { data, colorRange } = createLinearGradient(
      [],
      (_a = this.options.styleSpec) == null ? void 0 : _a.color
    );
    if (colorRange) {
      this.colorRange = colorRange;
    }
    if (data) {
      this.colorRampTexture = createTexture(
        this.gl,
        this.gl.NEAREST,
        data,
        16,
        16
      );
    }
  }
  drawTexture(matrix) {
    if (this.fbo && this.screenTexture && this.nextParticleStateTexture) {
      bindFramebuffer(this.gl, this.fbo, this.screenTexture);
      const depthEnabled = this.gl.isEnabled(this.gl.DEPTH_TEST);
      const blendingEnabled = this.gl.isEnabled(this.gl.BLEND);
      this.gl.disable(this.gl.DEPTH_TEST);
      this.gl.disable(this.gl.BLEND);
      this.screenCommand.active().resize(...this.size).setUniforms({
        u_screen: this.backgroundTexture,
        u_opacity: this.options.fadeOpacity,
        u_fade: 1
      }).setAttributes({
        a_pos: {
          buffer: this.data.backgroundBuffer,
          numComponents: 2
        },
        a_tex_pos: {
          buffer: this.data.backgroundTexCoordBuffer,
          numComponents: 2
        }
      }).setPrimitive(this.gl.TRIANGLE_STRIP).draw();
      if (depthEnabled) {
        this.gl.enable(this.gl.DEPTH_TEST);
      }
      if (blendingEnabled) {
        this.gl.enable(this.gl.BLEND);
      }
      this.drawParticles(matrix);
      bindFramebuffer(this.gl, null);
      [this.backgroundTexture, this.screenTexture] = [
        this.screenTexture,
        this.backgroundTexture
      ];
    }
  }
  drawScreen() {
    const depthEnabled = this.gl.isEnabled(this.gl.DEPTH_TEST);
    const blendingEnabled = this.gl.isEnabled(this.gl.BLEND);
    this.gl.disable(this.gl.DEPTH_TEST);
    this.gl.enable(this.gl.BLEND);
    this.gl.blendColor(0, 0, 0, 0);
    this.gl.blendFunc(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
    this.screenCommand.active().resize().setUniforms({
      u_screen: this.screenTexture,
      u_opacity: this.visible ? this.opacity : 0,
      u_fade: this.alpha
    }).setAttributes({
      a_pos: {
        buffer: this.data.buffer,
        numComponents: 2
      },
      a_tex_pos: {
        buffer: this.data.texCoordBuffer,
        numComponents: 2
      }
    }).setPrimitive(this.gl.TRIANGLE_STRIP).draw();
    if (depthEnabled) {
      this.gl.enable(this.gl.DEPTH_TEST);
    }
    if (!blendingEnabled) {
      this.gl.disable(this.gl.BLEND);
    }
  }
  updateParticles() {
    if (this.fbo && this.currentParticleStateTexture && this.nextParticleStateTexture) {
      bindFramebuffer(this.gl, this.fbo, this.nextParticleStateTexture);
      const timeScale = this.options.speedFactor * 2.5;
      const depthEnabled = this.gl.isEnabled(this.gl.DEPTH_TEST);
      const blendingEnabled = this.gl.isEnabled(this.gl.BLEND);
      this.gl.disable(this.gl.DEPTH_TEST);
      this.gl.disable(this.gl.BLEND);
      this.updateCommand.active().resize(this.particleStateResolution, this.particleStateResolution).setUniforms({
        u_wind_res: [this.data.width, this.data.height],
        u_rand_seed: Math.random(),
        u_wind_range: [
          this.data.uMin,
          this.data.uMax,
          this.data.vMin,
          this.data.vMax
        ],
        u_drop_rate: this.options.dropRate,
        u_drop_rate_bump: this.options.dropRateBump,
        u_speed_factor: [
          timeScale * this.frameTime / this.size[0],
          timeScale * this.frameTime / this.size[1]
        ],
        u_wind: this.data.texture,
        u_bbox: this.renderExtent,
        nodata: this.data.nodata,
        u_particles: this.currentParticleStateTexture
      }).setAttributes({
        a_pos: {
          buffer: this.data.quadBuffer,
          numComponents: 2
        }
      }).setPrimitive(this.gl.TRIANGLE_STRIP).draw();
      if (depthEnabled) {
        this.gl.enable(this.gl.DEPTH_TEST);
      }
      if (blendingEnabled) {
        this.gl.enable(this.gl.BLEND);
      }
      [this.currentParticleStateTexture, this.nextParticleStateTexture] = [
        this.nextParticleStateTexture,
        this.currentParticleStateTexture
      ];
    }
  }
  drawParticles(matrix) {
    if (this.particleIndexBuffer && this.currentParticleStateTexture && this.nextParticleStateTexture) {
      const depthEnabled = this.gl.isEnabled(this.gl.DEPTH_TEST);
      const blendingEnabled = this.gl.isEnabled(this.gl.BLEND);
      this.gl.disable(this.gl.DEPTH_TEST);
      this.gl.disable(this.gl.BLEND);
      const zoom = this.options.getZoom();
      const worlds = this.options.getWorlds();
      for (let i = 0; i < worlds.length; i++) {
        this.drawCommand.active().setUniforms({
          u_width: this.options.lineWidth,
          u_world: this.size,
          u_matrix: matrix,
          u_zoom: zoom,
          u_bbox: this.renderExtent,
          u_offset: worlds[i],
          u_wind: this.data.texture,
          u_wind_res: [this.data.width, this.data.height],
          u_wind_range: [
            this.data.uMin,
            this.data.uMax,
            this.data.vMin,
            this.data.vMax
          ],
          u_color_ramp: this.colorRampTexture,
          u_color_range: this.colorRange,
          u_aspectRatio: this.size[0] / this.size[1],
          u_particles_current: this.currentParticleStateTexture,
          u_particles_next: this.nextParticleStateTexture,
          u_particles_res: this.particleStateResolution
        }).setAttributes({
          a_index: {
            buffer: this.particleIndexBuffer,
            numComponents: 1
          }
        }).setPrimitive(this.gl.TRIANGLES).runTimes(this.particleStateResolution ** 2 * 6).draw();
      }
      if (blendingEnabled) {
        this.gl.enable(this.gl.BLEND);
      }
      if (depthEnabled) {
        this.gl.enable(this.gl.DEPTH_TEST);
      }
    }
  }
  updateRenderState() {
    this.renderExtent = this.options.getExtent();
  }
  resize() {
    const gl = this.gl;
    this.size = this.options.getSize();
    this.updateRenderState();
    const emptyPixels = new Uint8Array(this.size[0] * this.size[1] * 4);
    if (!this.backgroundTexture) {
      this.backgroundTexture = createTexture(
        gl,
        gl.NEAREST,
        emptyPixels,
        this.size[0],
        this.size[1]
      );
    } else {
      resizeTexture(
        gl,
        this.backgroundTexture,
        this.size[0],
        this.size[1],
        emptyPixels
      );
    }
    if (!this.screenTexture) {
      this.screenTexture = createTexture(
        gl,
        gl.NEAREST,
        emptyPixels,
        this.size[0],
        this.size[1]
      );
    } else {
      resizeTexture(
        gl,
        this.screenTexture,
        this.size[0],
        this.size[1],
        emptyPixels
      );
    }
    if (this.fbo) {
      resizeFramebuffer(
        gl,
        this.fbo,
        this.size[0],
        this.size[1],
        this.screenTexture
      );
    }
  }
  start() {
    this.raf.start();
    if (this.options.triggerRepaint) {
      this.options.triggerRepaint();
    }
  }
  stop() {
    this.raf.stop();
    clearScene(this.gl, [0, 0, 0, 0]);
    if (this.options.triggerRepaint) {
      this.options.triggerRepaint();
    }
  }
  prerender(matrix) {
    if (this.data) {
      this.updateParticles();
      this.drawTexture(matrix);
      const now = 1e-3 * Date.now();
      this.frameTime = Math.min(now - (this.lastTime || 0), 0.05);
      this.lastTime = now;
    }
  }
  render() {
    if (this.data) {
      if (this.options.interacting()) {
        if (this.alpha < 1) {
          this.alpha += 3 * this.frameTime;
          if (this.alpha > 1 || !this.frameTime) {
            this.alpha = 1;
          }
        }
      }
      this.drawScreen();
    }
    return this;
  }
  initializeVertex(coordinates) {
    let i = 0;
    const len = coordinates.length;
    const instancePositions = new Float32Array(len * 2);
    for (; i < len; i++) {
      const coords = coordinates[i];
      const mc = this.getMercatorCoordinate(coords);
      instancePositions[i * 2] = mc[0];
      instancePositions[i * 2 + 1] = mc[1];
    }
    return {
      quadBuffer: createBuffer(
        this.gl,
        new Float32Array([0, 0, 0, 1, 1, 0, 1, 1])
      ),
      buffer: createBuffer(this.gl, instancePositions),
      texCoordBuffer: createBuffer(
        this.gl,
        new Float32Array([0, 0, 0, 1, 1, 0, 1, 1])
      ),
      backgroundBuffer: createBuffer(
        this.gl,
        new Float32Array([0, 0, 0, 1, 1, 0, 1, 1])
      ),
      backgroundTexCoordBuffer: createBuffer(
        this.gl,
        new Float32Array([0, 0, 0, 1, 1, 0, 1, 1])
      )
    };
  }
  getTextureData(data) {
    return new Promise((resolve, reject) => {
      if (data.type === "image" && data.url) {
        loadImage(data.url).then((image) => {
          const processedData = {
            width: image.width,
            height: image.height,
            texture: createTexture(
              this.gl,
              this.gl.LINEAR,
              image,
              image.width,
              image.height
            ),
            nodata: data.nodata || 0,
            ...this.initializeVertex(data.extent)
          };
          processedData.uMin = data.uMin;
          processedData.uMax = data.uMax;
          processedData.vMin = data.vMin;
          processedData.vMax = data.vMax;
          resolve(processedData);
        }).catch((error) => reject(error));
      }
    });
  }
  setData(data, cb) {
    if (this.gl && data) {
      this.getTextureData(data).then((d) => {
        this.data = d;
        cb && cb(true);
        if (this.options.triggerRepaint) {
          this.options.triggerRepaint();
        }
      }).catch((error) => {
        cb && cb(false);
        console.error(error);
      });
    }
  }
  getData() {
    return this.data;
  }
  getMercatorCoordinate([lng, lat]) {
    return [lng, lat];
  }
  destroyData() {
    if (this.data) {
      const {
        texture,
        quadBuffer,
        buffer,
        texCoordBuffer,
        backgroundBuffer,
        backgroundTexCoordBuffer
      } = this.data;
      if (texture) {
        this.gl.deleteTexture(texture);
      }
      if (buffer) {
        this.gl.deleteBuffer(buffer);
      }
      if (quadBuffer) {
        this.gl.deleteBuffer(quadBuffer);
      }
      if (texCoordBuffer) {
        this.gl.deleteBuffer(texCoordBuffer);
      }
      if (backgroundBuffer) {
        this.gl.deleteBuffer(backgroundBuffer);
      }
      if (backgroundTexCoordBuffer) {
        this.gl.deleteBuffer(backgroundTexCoordBuffer);
      }
      delete this.data;
    }
  }
  destroyed() {
    this.stop();
    if (this.currentParticleStateTexture) {
      this.gl.deleteTexture(this.currentParticleStateTexture);
      this.currentParticleStateTexture = null;
    }
    if (this.nextParticleStateTexture) {
      this.gl.deleteTexture(this.nextParticleStateTexture);
      this.nextParticleStateTexture = null;
    }
    if (this.backgroundTexture) {
      this.gl.deleteTexture(this.backgroundTexture);
      this.backgroundTexture = null;
    }
    if (this.screenTexture) {
      this.gl.deleteTexture(this.screenTexture);
      this.screenTexture = null;
    }
    if (this.fbo) {
      this.gl.deleteFramebuffer(this.fbo);
      this.fbo = null;
    }
    this.destroyData();
  }
}

export { ScalarFill, WindParticles, bindAttribute, bindFramebuffer, bindTexture, calcMinMax, clearScene, createBuffer, createProgram, createShader, createTexture, defaultOptions$2 as defaultOptions, defineShader, destroyTexture, findStopLessThanOrEqualTo, fp64LowPart, getDevicePixelRatio, getEye, getGlContext, getPlaneBuffer, injectShaderModule, isNumber, isValide, loadImage, mat4Invert, resizeCanvasSize, resizeFramebuffer, resizeTexture, transformMat4, updateBufferData };
//# sourceMappingURL=wind-gl-core.esm.js.map

2. 使用

引入 mapbox-wind 中WindLayer 即可

import { WindLayer } from "./wind/mapbox-wind";

  windLayer = new WindLayer("wind", res.data, {
    windOptions: {
      colorScale: () => {
        //   // console.log(m);
        return "#1280FF";
      },
      // colorScale: [
      //   "rgb(36,104, 180)",
      //   "rgb(60,157, 194)",
      //   "rgb(128,205,193 )",
      //   "rgb(151,218,168 )",
      //   "rgb(198,231,181)",
      //   "rgb(238,247,217)",
      //   "rgb(255,238,159)",
      //   "rgb(252,217,125)",
      //   "rgb(255,182,100)",
      //   "rgb(252,150,75)",
      //   "rgb(250,112,52)",
      //   "rgb(245,64,32)",
      //   "rgb(237,45,28)",
      //   "rgb(220,24,32)",
      //   "rgb(180,0,35)"
      // ],
      // velocityScale: 1 / 20,
      // paths: 5000,
      frameRate: 16,
      maxAge: 60,
      globalAlpha: 0.95,
      velocityScale: 0.01,
      // paths: 10000,
      paths: 1000,
    },
  });

图层清除

// 图层清除
// 1. 先调用windLayer自身remove
    await windLayer?.remove();
// 2. 再调用地图的removeLayer
    if (map.getLayer("wind")) {
      await map.removeLayer("wind");
    }

添加弹框
通过windLayer.getData().interpolatedValueAt(lng, lat);
在这里插入图片描述

const clickFn  = (e) => {
  const { lng, lat } = e.lngLat;

  if (windLayer && windLayer.getData) {
    const field = windLayer.getData();
    if (field && field.interpolatedValueAt) {
      const windValue = field.interpolatedValueAt(lng, lat);
      
      removePopup()
      popup = new MaplibreCustom({
        map: useInjectMap(),
        coordinates: [lng, lat]
      })

      popup.createCustomPopup({
        component: {
          component: () => import('./WindPopup.vue'),
          props: {
            data: {
              windValue,
              lng,
              lat,
              direction: getWeatherWindDirection(windValue?.u, windValue?.v),
            },
          }
        }
      })
    }
  }
}

3. 效果

在这里插入图片描述

4. 数据格式

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值