ol-owm
Version:
Weather layer for OpenLayers and Leaflet using OpenWeatherMap
1,227 lines (1,216 loc) • 36 kB
JavaScript
"use strict";
var windCore = require("wind-core");
var windGlCore = require("wind-gl-core");
var L = require("leaflet");
var rewind = require("@mapbox/geojson-rewind");
var visEngine = require("@sakitam-gis/vis-engine");
var glMatrix = require("gl-matrix");
function _interopNamespaceDefault(e) {
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== "default") {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(
n,
k,
d.get
? d
: {
enumerable: true,
get: function () {
return e[k];
},
}
);
}
});
}
n.default = e;
return Object.freeze(n);
}
var L__namespace = /*#__PURE__*/ _interopNamespaceDefault(L);
class BaseLayer extends L__namespace.Layer {
constructor(id, data, options) {
super(id, data, options);
}
initialize(id, data, options) {
if (!id) {
throw Error("layer id must be specified");
}
this._layerId = id;
L__namespace.Util.setOptions(this, options);
this.devicePixelRatio =
this.options.devicePixelRatio || // @ts-ignore 忽略错误
window.devicePixelRatio ||
window.screen.deviceXDPI / window.screen.logicalXDPI;
}
_createCanvas(id, zIndex) {
const canvas = windCore.createCanvas(
this._width,
this._height,
this.devicePixelRatio
);
canvas.id = String(id);
const panes = this._map.getPanes();
if (panes && panes.overlayPane) {
panes.overlayPane.appendChild(canvas);
}
return canvas;
}
_reset() {
const topLeft = this._map.containerPointToLayerPoint([0, 0]);
L__namespace.DomUtil.setPosition(this.canvas, topLeft);
this._redraw();
}
_onResize(resizeEvent) {
this.canvas.style.width = resizeEvent.newSize.x + "px";
this.canvas.style.height = resizeEvent.newSize.y + "px";
this._width = resizeEvent.newSize.x;
this._height = resizeEvent.newSize.y;
this._resizeCanvas(this.devicePixelRatio);
}
_zoomStart() {
this._moveStart();
}
_moveStart() {
if (!this._updating) {
this._updating = true;
}
}
_animateZoom(event) {
const scale = this._map.getZoomScale(event.zoom, this._map.getZoom());
const offset = this._map._latLngToNewLayerPoint(
this._map.getBounds().getNorthWest(),
event.zoom,
event.center
);
L__namespace.DomUtil.setTransform(this.canvas, offset, scale);
}
_resizeCanvas(scale) {
this.canvas.width = this._width * scale;
this.canvas.height = this._height * scale;
}
_redraw() {
this._render();
}
_render() {}
project(coordinate) {
const pixel = this._map.latLngToContainerPoint(
new L__namespace.LatLng(coordinate[1], coordinate[0])
);
return [pixel.x * this.devicePixelRatio, pixel.y * this.devicePixelRatio];
}
unproject(pixel) {
const coordinates = this._map.containerPointToLatLng(
new L__namespace.Point(pixel[0], pixel[1])
);
return [coordinates.lng, coordinates.lat];
}
intersectsCoordinate(coordinate) {
const bounds = this._map.getBounds();
return bounds.contains(L__namespace.latLng(coordinate[1], coordinate[0]));
}
onAdd(map) {
this._map = map;
const size = map.getSize();
this._width = size.x;
this._height = size.y;
this.canvas = this._createCanvas(this._layerId, this.options.zIndex || 1);
const animated =
this._map.options.zoomAnimation && L__namespace.Browser.any3d;
L__namespace.DomUtil.addClass(
this.canvas,
"leaflet-zoom-" + (animated ? "animated" : "hide")
);
this._map.on(this.getEvents(), this);
this._resetView();
this._render();
return this;
}
_resetView(e) {}
onMoveEnd() {
this._reset();
}
onRemove() {
const panes = this._map.getPanes();
if (panes && panes.overlayPane) {
panes.overlayPane.removeChild(this.canvas);
}
this._map.off(this.getEvents(), this);
this.canvas = null;
return this;
}
getEvents() {
const events = {
resize: this._onResize,
viewreset: this._render,
moveend: this.onMoveEnd,
// movestart: this._moveStart,
zoomstart: this._render,
zoomend: this._render,
// zoomanim: undefined,
};
if (this._map.options.zoomAnimation && L__namespace.Browser.any3d) {
events.zoomanim = this._animateZoom;
}
return events;
}
}
class WindLayer extends BaseLayer {
initialize(id, data, options) {
super.initialize(id, data, options);
this.field = void 0;
this.pickWindOptions();
if (data) {
this.setData(data, options.fieldOptions);
}
}
_redraw() {
this._render();
}
_render() {
const opt = this.getWindOptions();
if (!this.wind && this._map) {
const ctx = this.canvas.getContext("2d");
const data = this.getData();
this.wind = new windCore.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();
}
onRemove() {
if (this.wind) {
this.wind.stop();
this.wind = null;
}
return super.onRemove();
}
pickWindOptions() {
Object.keys(windCore.defaultOptions).forEach((key) => {
if (key in this.options) {
if (this.options.windOptions === void 0) {
this.options.windOptions = {};
}
this.options.windOptions[key] = this.options[key];
}
});
}
/**
* get wind layer data
*/
getData() {
return this.field;
}
/**
* set layer data
* @param data
* @param options
* @returns {WindLayer}
*/
setData(data, options = {}) {
if (data && data.checkFields && data.checkFields()) {
this.field = data;
} else if (windCore.isArray(data)) {
this.field = windCore.formatData(data, options);
} else {
console.error("Illegal data");
}
if (this.field) {
this?.wind?.updateData(this.field);
}
return this;
}
setWindOptions(options) {
const beforeOptions = this.options.windOptions || {};
this.options = windCore.assign(this.options, {
windOptions: windCore.assign(beforeOptions, options || {}),
});
if (this.wind) {
const windOptions = this.options.windOptions;
this.wind.setOptions(windOptions);
this.wind.prerender();
}
}
getWindOptions() {
return this.options.windOptions || {};
}
}
const { clamp } = visEngine.utils;
const earthRadius = 63710088e-1;
const earthCircumference = 2 * Math.PI * earthRadius;
function circumferenceAtLatitude(latitude) {
return earthCircumference * Math.cos((latitude * Math.PI) / 180);
}
function mercatorXfromLng(lng) {
return (180 + lng) / 360;
}
function mercatorYfromLat(lat) {
return (
(180 -
(180 / Math.PI) *
Math.log(Math.tan(Math.PI / 4 + (lat * Math.PI) / 360))) /
360
);
}
function mercatorZfromAltitude(altitude, lat) {
return altitude / circumferenceAtLatitude(lat);
}
function lngFromMercatorX(x, wrap = 0) {
return x * 360 - 180 + wrap * 360;
}
function latFromMercatorY(y) {
const y2 = 180 - y * 360;
return (360 / Math.PI) * Math.atan(Math.exp((y2 * Math.PI) / 180)) - 90;
}
const MAX_MERCATOR_LATITUDE = 85.051129;
function fromLngLat(lngLatLike, altitude = 0) {
const lat = clamp(
lngLatLike.lat,
-MAX_MERCATOR_LATITUDE,
MAX_MERCATOR_LATITUDE
);
return {
x: mercatorXfromLng(lngLatLike.lng),
y: mercatorYfromLat(lat),
z: mercatorZfromAltitude(altitude, lat),
};
}
function getCoordinatesCenterTileID(coords) {
let minX = Infinity;
let minY = Infinity;
let maxX = -Infinity;
let maxY = -Infinity;
for (const coord of coords) {
minX = Math.min(minX, coord.x);
minY = Math.min(minY, coord.y);
maxX = Math.max(maxX, coord.x);
maxY = Math.max(maxY, coord.y);
}
const dx = maxX - minX;
const dy = maxY - minY;
const dMax = Math.max(dx, dy);
const zoom = Math.max(0, Math.floor(-Math.log(dMax) / Math.LN2));
const tilesAtZoom = Math.pow(2, zoom);
return {
z: zoom,
x: Math.floor(((minX + maxX) / 2) * tilesAtZoom),
y: Math.floor(((minY + maxY) / 2) * tilesAtZoom),
extent: [minX, minY, maxX, maxY],
};
}
const { degToRad, radToDeg } = visEngine.utils;
visEngine.highPrecision(true);
glMatrix.mat4.identity([]);
class CameraSync {
constructor(viewState, cameraType, scene) {
this.worldMatrix = new visEngine.Matrix4();
this.mercatorMatrix = new visEngine.Matrix4();
this.labelPlaneMatrix = new visEngine.Matrix4();
this.glCoordMatrix = new visEngine.Matrix4();
const { width, height } = viewState;
const fov = radToDeg(Math.atan(3 / 4));
const nearZ = 0.1;
const farZ = 1e21;
this.viewState = viewState;
this.scene = scene;
this.scene.matrixAutoUpdate = false;
this.scene.worldMatrixNeedsUpdate = true;
this.camera =
cameraType === "orthographic"
? new visEngine.OrthographicCamera(
-width / 2,
width / 2,
height / 2,
-height / 2,
nearZ,
farZ
)
: new visEngine.PerspectiveCamera(fov, width / height, nearZ, farZ);
this.camera.matrixAutoUpdate = false;
this.camera.position.z = 600;
this.setup();
}
setup() {
const { width, height, fov } = this.viewState;
const maxPitch = degToRad(this.viewState.maxPitch);
this.camera.aspect = width / height;
this.halfFov = fov / 2;
this.cameraToCenterDistance = (0.5 / Math.tan(this.halfFov)) * height;
this.acuteAngle = Math.PI / 2 - maxPitch;
this.update();
}
update() {
const { width, height, elevation, _horizonShift, worldSize } =
this.viewState;
const center = this.viewState.getCenter();
const pitch = this.viewState.getPitch();
const pitchRad = degToRad(pitch);
const bearing = this.viewState.getBearing();
const fovRad = this.viewState.getFovRad();
const cameraPosition = this.viewState.getCameraPosition();
const halfFov = fovRad / 2;
const pitchAngle = Math.cos(Math.PI / 2 - pitchRad);
const groundAngle = Math.PI / 2 + pitchRad;
this.cameraToCenterDistance = (0.5 / Math.tan(halfFov)) * height;
const point = this.viewState.project(center);
const rotateMap = new visEngine.Matrix4().fromRotationZ(Math.PI);
const scale = new visEngine.Matrix4().fromScale(
new visEngine.Vector3(-worldSize, worldSize, worldSize)
);
const translateMap = new visEngine.Matrix4().fromTranslation(
new visEngine.Vector3(-point.x, point.y, 0)
);
const nz = height / 50;
const nearZ = Math.max(nz * pitchAngle, nz);
const fovAboveCenter =
fovRad * (0.5 + this.viewState.centerOffset().y / height);
const pixelsPerMeter =
mercatorZfromAltitude(1, center.lat) * worldSize || 1;
const minElevationInPixels = elevation
? elevation.getMinElevationBelowMSL() * pixelsPerMeter
: 0;
const cameraToSeaLevelDistance =
(cameraPosition[2] * worldSize - minElevationInPixels) /
Math.cos(pitchRad);
const topHalfSurfaceDistance =
(Math.sin(fovAboveCenter) * cameraToSeaLevelDistance) /
Math.sin(
visEngine.utils.clamp(
Math.PI - groundAngle - fovAboveCenter,
0.01,
Math.PI - 0.01
)
);
const furthestDistance =
pitchAngle * topHalfSurfaceDistance + cameraToSeaLevelDistance;
const horizonDistance = cameraToSeaLevelDistance * (1 / _horizonShift);
const farZ = Math.min(furthestDistance * 1.01, horizonDistance);
this.mercatorMatrix = new visEngine.Matrix4().scale(
new visEngine.Vector3(worldSize, worldSize, worldSize / pixelsPerMeter)
);
const may = new visEngine.Matrix4().fromTranslation(
new visEngine.Vector3(0, 0, this.cameraToCenterDistance)
);
this.labelPlaneMatrix = new visEngine.Matrix4();
const m = new visEngine.Matrix4();
m.scale(new visEngine.Vector3(1, -1, 1));
m.translate(new visEngine.Vector3(-1, -1, 0));
m.scale(new visEngine.Vector3(2 / width, 2 / height, 1));
this.glCoordMatrix = m;
this.camera.aspect = width / height;
this.cameraTranslateZ = this.cameraToCenterDistance;
if (this.camera instanceof visEngine.OrthographicCamera) {
this.camera.projectionMatrix.orthographic(
-width / 2,
width / 2,
height / 2,
-height / 2,
nearZ,
farZ
);
} else {
this.camera.projectionMatrix.perspective(
fovRad,
width / height,
nearZ,
farZ
);
}
const cameraWorldMatrix = new visEngine.Matrix4()
.premultiply(may)
.premultiply(new visEngine.Matrix4().fromRotationX(pitchRad))
.premultiply(new visEngine.Matrix4().fromRotationZ(-degToRad(bearing)));
if (elevation)
cameraWorldMatrix.elements[14] = cameraPosition[2] * worldSize;
this.camera.worldMatrix.copy(cameraWorldMatrix);
this.camera.updateMatrixWorld();
if (this.scene) {
this.scene.localMatrix = new visEngine.ProjectionMatrix()
.premultiply(rotateMap)
.premultiply(scale)
.premultiply(translateMap);
}
}
}
function getTileProjBounds(tileID) {
const numTiles = 1 << tileID.z;
return {
left: tileID.wrapedX / numTiles,
top: tileID.wrapedY / numTiles,
right: (tileID.wrapedX + 1) / numTiles,
bottom: (tileID.wrapedY + 1) / numTiles,
};
}
function getTileBounds(tileID) {
const { z, x, y } = tileID;
const wrap = tileID.wrap;
const numTiles = 1 << z;
const leftLng = lngFromMercatorX(x / numTiles, wrap);
const rightLng = lngFromMercatorX((x + 1) / numTiles, wrap);
const topLat = latFromMercatorY(y / numTiles);
const bottomLat = latFromMercatorY((y + 1) / numTiles);
return [leftLng, bottomLat, rightLng, topLat];
}
function getExtent(map) {
const bounds = map?.getBounds();
const southWest = bounds.getSouthWest();
const northEast = bounds.getNorthEast();
const [xmin, ymin, xmax, ymax] = [
southWest.lng,
southWest.lat,
northEast.lng,
northEast.lat,
];
const minY = Math.max(ymin, -MAX_MERCATOR_LATITUDE);
const maxY = Math.min(ymax, MAX_MERCATOR_LATITUDE);
const p0 = fromLngLat({ lng: xmin, lat: maxY });
const p1 = fromLngLat({ lng: xmax, lat: minY });
return [p0.x, p0.y, p1.x, p1.y];
}
function getClampZoom(options) {
const z = options.zoom;
if (void 0 !== options.minzoom && z < options.minzoom) {
return options.minzoom;
}
if (void 0 !== options.maxzoom && options.maxzoom < z) {
return options.maxzoom;
}
return z;
}
class ViewState {
constructor() {
this.tileSize = 512;
this.maxPitch = 60;
this._horizonShift = 0.1;
}
/**
* 获取 gl 宽度
*/
get width() {
return this._width;
}
/**
* 获取 gl 高度
*/
get height() {
return this._height;
}
get fov() {
return (this.getFovRad() / Math.PI) * 180;
}
get worldSize() {
const scale = Math.pow(2, this.zoom - 1);
return this.tileSize * scale;
}
getCenter() {
return this._center;
}
getPitch() {
return 0;
}
getBearing() {
return 0;
}
getFovRad() {
return 0.6435011087932844;
}
getCameraPosition() {
return [0, 0, 0];
}
centerOffset() {
return { x: 0, y: 0 };
}
project(lnglat) {
const lat = visEngine.utils.clamp(
lnglat.lat,
-MAX_MERCATOR_LATITUDE,
MAX_MERCATOR_LATITUDE
);
const x = mercatorXfromLng(lnglat.lng);
const y = mercatorYfromLat(lat);
return { x: x * this.worldSize, y: y * this.worldSize, z: 0 };
}
get pixelsPerMeter() {
return mercatorZfromAltitude(1, this._center.lat) * this.worldSize;
}
unproject(p) {
const lng = lngFromMercatorX(p[0]);
const lat = latFromMercatorY(p[1]);
return [lng, lat];
}
update(state) {
this._center = state.center;
this._width = state.width;
this._height = state.height;
this.zoom = state.zoom;
}
}
function wrapTile(x, range, includeMax) {
const max = range[1];
const min = range[0];
const d = max - min;
return {
x: x === max && includeMax ? x : ((((x - min) % d) + d) % d) + min,
wrap: Math.floor(x / max),
};
}
class WebglLayer extends BaseLayer {
initialize(id, source, options) {
super.initialize(id, source, options);
this.viewState = new ViewState();
this._currentTiles = [];
this._unLimitTiles = [];
this.source = source;
}
_resizeCanvas(scale) {
super._resizeCanvas(scale);
if (this.renderer) {
this.renderer.setSize(this._width, this._height);
}
if (this.layer) {
this.layer.resize(this._width, this._height);
}
this._render();
}
get camera() {
return this.sync.camera;
}
getTileSize() {
const s = visEngine.utils.isNumber(this.source.tileSize)
? this.source.tileSize
: this.source.tileSize?.[0] || 512;
return new L__namespace.Point(s, s);
}
_redraw() {
if (this._map && this.source) {
const tileZoom = getClampZoom({
zoom: this._map.getZoom(),
minzoom: this.source.minZoom,
maxzoom: this.source.maxZoom,
});
if (tileZoom !== this._tileZoom) {
this._tileZoom = tileZoom;
}
this._update();
}
return this;
}
_render() {
if (this._map && this.viewState) {
this.viewState.update({
center: this._map.getCenter(),
zoom: this._map.getZoom(),
width: this._width,
height: this._height,
});
}
if (!this.gl) {
this.gl = visEngine.utils.getContext(
this.canvas,
{
preserveDrawingBuffer: false,
antialias: true,
// https://bugs.webkit.org/show_bug.cgi?id=237906
stencil: true,
},
true
);
this.renderer = new visEngine.Renderer(this.gl, {
autoClear: false,
extensions: [
"OES_texture_float",
"OES_texture_float_linear",
"WEBGL_color_buffer_float",
"EXT_color_buffer_float",
],
});
this.scene = new visEngine.Scene();
this.sync = new CameraSync(this.viewState, "perspective", this.scene);
this.planeCamera = new visEngine.OrthographicCamera(0, 1, 1, 0, 0, 1);
this.layer = new windGlCore.BaseLayer(
this.source,
{
renderer: this.renderer,
scene: this.scene,
},
{
renderType: this.options.renderType,
renderFrom: this.options.renderFrom,
styleSpec: this.options.styleSpec,
displayRange: this.options.displayRange,
widthSegments: this.options.widthSegments,
heightSegments: this.options.heightSegments,
wireframe: this.options.wireframe,
picking: this.options.picking,
mask: this.processMask(),
getZoom: () => this.viewState.zoom,
triggerRepaint: () => {
requestAnimationFrame(() => this._update());
},
getTileProjSize: (z) => {
const w = 1 / Math.pow(2, z);
return [w, w];
},
getPixelsToUnits: () => {
const pixel = 1;
const y = this.canvas.clientHeight / 2 - pixel / 2;
const x = this.canvas.clientWidth / 2 - pixel / 2;
const left = fromLngLat(this.viewState.unproject([x, y]));
const right = fromLngLat(
this.viewState.unproject([x + pixel, y + pixel])
);
return [Math.abs(right.x - left.x), Math.abs(left.y - right.y)];
},
getPixelsToProjUnit: () => [
this.viewState.pixelsPerMeter,
this.viewState.pixelsPerMeter,
],
getViewTiles: (source, renderType) => {
let { type } = source;
type =
type !== windGlCore.LayerSourceType.timeline
? type
: source.privateType;
if (!this._map) return [];
const wrapTiles = [];
if (type === windGlCore.LayerSourceType.image) {
const cornerCoords = source.coordinates.map((c) =>
fromLngLat({ lng: c[0], lat: c[1] })
);
const tileID = getCoordinatesCenterTileID(cornerCoords);
if (source.wrapX) {
const x = tileID.x;
const y = tileID.y;
const z = tileID.z;
const wrap = 0;
wrapTiles.push(
new windGlCore.TileID(z, wrap, z, x, y, {
getTileBounds: () => [
source.coordinates[0][0],
source.coordinates[2][1],
source.coordinates[1][0],
source.coordinates[0][1],
],
getTileProjBounds: () => ({
left: tileID.extent[0] + wrap,
top: tileID.extent[1],
right: tileID.extent[2] + wrap,
bottom: tileID.extent[3],
}),
})
);
} else {
const x = tileID.x;
const y = tileID.y;
const z = tileID.z;
const wrap = 0;
wrapTiles.push(
new windGlCore.TileID(z, wrap, z, x, y, {
getTileBounds: () => [
source.coordinates[0][0],
source.coordinates[2][1],
source.coordinates[1][0],
source.coordinates[0][1],
],
getTileProjBounds: () => ({
left: tileID.extent[0] + wrap,
top: tileID.extent[1],
right: tileID.extent[2] + wrap,
bottom: tileID.extent[3],
}),
})
);
}
} else if (type === windGlCore.LayerSourceType.tile) {
const tiles = this._currentTiles;
for (let i = 0; i < tiles.length; i++) {
const tile = tiles[i];
const { x, y, z, wrap } = tile;
if (source.wrapX) {
wrapTiles.push(
new windGlCore.TileID(z, wrap, z, x, y, {
getTileBounds,
getTileProjBounds,
})
);
} else if (tile.wrap === 0) {
wrapTiles.push(
new windGlCore.TileID(z, wrap, z, x, y, {
getTileBounds,
getTileProjBounds,
})
);
}
}
}
return wrapTiles;
},
getExtent: () => getExtent(this._map),
getGridTiles: (source) => {
const wrapX = source.wrapX;
if (!this._map) return [];
const tiles = this._unLimitTiles;
const wrapTiles = [];
for (let i = 0; i < tiles.length; i++) {
const tile = tiles[i];
const { x, y, z, wrap } = tile;
if (wrapX) {
wrapTiles.push(
new windGlCore.TileID(z, wrap, z, x, y, {
getTileBounds,
getTileProjBounds,
})
);
} else if (tile.wrap === 0) {
wrapTiles.push(
new windGlCore.TileID(z, wrap, z, x, y, {
getTileBounds,
getTileProjBounds,
})
);
}
}
return wrapTiles;
},
}
);
}
if (this.sync) {
this.sync.update();
}
if (this.layer) {
this.layer.update();
}
this.glPrerender();
this.glRender();
}
glPrerender() {
this.scene.worldMatrixNeedsUpdate = true;
this.scene.updateMatrixWorld();
this.camera.updateMatrixWorld();
const worlds = this.calcWrappedWorlds();
this.layer?.prerender({
worlds,
camera: this.camera,
planeCamera: this.planeCamera,
});
}
glRender() {
this.scene.worldMatrixNeedsUpdate = true;
this.scene.updateMatrixWorld();
this.camera.updateMatrixWorld();
const worlds = this.calcWrappedWorlds();
this.layer?.render({
worlds,
camera: this.camera,
planeCamera: this.planeCamera,
});
}
async picker(coordinates) {
if (!this.options.picking) {
console.warn("[Layer]: please enable picking options!");
return null;
}
if (!this.layer || !coordinates || !this._map) {
console.warn("[Layer]: layer not initialized!");
return null;
}
const point = this._map.project(coordinates);
return this.layer.picker([point.x, point.y]);
}
calcWrappedWorlds() {
return [0];
}
_resetView(e) {
const animating = e && (e.pinch || e.flyTo);
this._setView(
this._map.getCenter(),
this._map.getZoom(),
animating,
animating
);
}
_resetGrid() {
const map = this._map;
const crs = map.options.crs;
const tileSize = this.getTileSize();
const tileZoom = this._tileZoom;
const bounds = this._map.getPixelWorldBounds(this._tileZoom);
if (bounds) {
this._globalTileRange = this._pxBoundsToTileRange(bounds);
}
this._wrapX = crs.wrapLng && [
Math.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x),
Math.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y),
];
this._wrapY = crs.wrapLat && [
Math.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x),
Math.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y),
];
}
_setView(center, zoom, noPrune, noUpdate) {
let tileZoom = Math.round(zoom);
if (
(this.options.maxZoom !== void 0 && tileZoom > this.options.maxZoom) ||
(this.options.minZoom !== void 0 && tileZoom < this.options.minZoom)
) {
tileZoom = void 0;
} else {
tileZoom = getClampZoom({
minzoom: this.source.minZoom,
maxzoom: this.source.maxZoom,
zoom: tileZoom,
});
}
const tileZoomChanged =
this.options.updateWhenZooming && tileZoom !== this._tileZoom;
if (!noUpdate || tileZoomChanged) {
this._tileZoom = tileZoom;
this._resetGrid();
if (tileZoom !== void 0) {
this._update(center);
}
}
}
_tileCoordsToBounds(coords) {
const bp = this._tileCoordsToNwSe(coords);
let bounds = new L__namespace.LatLngBounds(bp[0], bp[1]);
if (!this.source.wrapX) {
bounds = this._map.wrapLatLngBounds(bounds);
}
return bounds;
}
_tileCoordsToNwSe(coords) {
const map = this._map;
const tileSize = this.getTileSize();
const nwPoint = coords.scaleBy(tileSize);
const sePoint = nwPoint.add(tileSize);
const nw = map.unproject(nwPoint, coords.z);
const se = map.unproject(sePoint, coords.z);
return [nw, se];
}
_isValidTile(coords) {
const crs = this._map.options.crs;
if (!crs.infinite) {
const bounds = this._globalTileRange;
if (
(!crs.wrapLng &&
(coords.x < bounds.min.x || coords.x > bounds.max.x)) ||
(!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))
) {
return false;
}
}
return true;
}
_wrapCoords(coords) {
const t = this._wrapX
? wrapTile(coords.x, this._wrapX)
: { x: coords.x, wrap: 0 };
const newCoords = new L__namespace.Point(
t.x,
this._wrapY && !this.source.wrapX
? L__namespace.Util.wrapNum(coords.y, this._wrapY)
: coords.y
);
newCoords.z = coords.z;
newCoords.wrap = t.wrap;
return newCoords;
}
_update(center) {
const map = this._map;
if (!map || !this.source) {
return;
}
const zoom = getClampZoom({
zoom: map.getZoom(),
minzoom: this.source.minZoom,
maxzoom: this.source.maxZoom,
});
if (center === void 0) {
center = map.getCenter();
}
if (this._tileZoom === void 0) {
return;
}
const pixelBounds = this._getTiledPixelBounds(center, this._tileZoom);
const tileRange = this._pxBoundsToTileRange(pixelBounds);
const tileCenter = tileRange.getCenter();
const queue = [];
if (
!(
isFinite(tileRange.min.x) &&
isFinite(tileRange.min.y) &&
isFinite(tileRange.max.x) &&
isFinite(tileRange.max.y)
)
) {
throw new Error("Attempted to load an infinite number of tiles");
}
if (Math.abs(zoom - this._tileZoom) > 1) {
this._setView(center, zoom);
return;
}
for (let j = tileRange.min.y; j <= tileRange.max.y; j++) {
for (let i = tileRange.min.x; i <= tileRange.max.x; i++) {
const coords = new L__namespace.Point(i, j);
coords.z = this._tileZoom;
if (!this._isValidTile(coords)) {
continue;
}
queue.push(this._wrapCoords(coords));
}
}
queue.sort((a, b) => a.distanceTo(tileCenter) - b.distanceTo(tileCenter));
const z = map.getZoom();
const bounds = this._getTiledPixelBounds(center, z);
if (bounds) {
const unLimitTileRange = this._pxBoundsToTileRange(bounds);
const tc = tileRange.getCenter();
const tileCoords = [];
for (let j = unLimitTileRange.min.y; j <= unLimitTileRange.max.y; j++) {
for (let i = unLimitTileRange.min.x; i <= unLimitTileRange.max.x; i++) {
const coords = new L__namespace.Point(i, j);
coords.z = z;
if (!this._isValidTile(coords)) {
continue;
}
tileCoords.push(this._wrapCoords(coords));
}
}
tileCoords.sort((a, b) => a.distanceTo(tc) - b.distanceTo(tc));
this._unLimitTiles = tileCoords;
}
this._currentTiles = queue;
this._render();
return queue;
}
_getTiledPixelBounds(center, zoom) {
const map = this._map;
const mapZoom = map._animatingZoom
? Math.max(map._animateToZoom, map.getZoom())
: map.getZoom();
const scale = map.getZoomScale(mapZoom, zoom);
const pixelCenter = map.project(center, zoom).floor();
const halfSize = map.getSize().divideBy(scale * 2);
return new L__namespace.Bounds(
pixelCenter.subtract(halfSize),
pixelCenter.add(halfSize)
);
}
_pxBoundsToTileRange(bounds) {
const tileSize = this.getTileSize();
return new L__namespace.Bounds(
bounds.min.unscaleBy(tileSize).floor(),
bounds.max.unscaleBy(tileSize).ceil().subtract([1, 1])
);
}
handleZoom() {
this._resetView();
if (this.layer) {
this.layer.handleZoom();
}
}
onMoveEnd() {
this._reset();
if (!this._map || this._map._animatingZoom) {
return;
}
if (this.layer) {
this.layer.moveEnd();
}
}
onMoveStart() {
if (this.layer) {
this.layer.moveStart();
}
}
_animateZoom(event) {
super._animateZoom(event);
this._setView(event.center, event.zoom, true, event.noUpdate);
this.handleZoom();
}
getEvents() {
const events = {
resize: this._onResize,
viewreset: this._resetView,
moveend: this.onMoveEnd,
movestart: this.onMoveStart,
zoom: this.handleZoom,
zoomend: this._reset,
};
if (this._map.options.zoomAnimation && L__namespace.Browser.any3d) {
events.zoomanim = this._animateZoom;
}
return events;
}
updateOptions(options) {
this.options = {
...this.options,
...(options || {}),
};
if (this.layer) {
this.layer.updateOptions(options);
}
this._redraw();
}
getMask() {
return this.options.mask;
}
processMask() {
if (this.options.mask) {
const mask = this.options.mask;
const data = mask.data;
rewind(data, true);
const tr = (coords) => {
const mercatorCoordinates = [];
for (let i2 = 0; i2 < coords.length; i2++) {
const coord = coords[i2];
const p = fromLngLat(coord);
mercatorCoordinates.push([p.x, p.y]);
}
return mercatorCoordinates;
};
const features = data.features;
const len = features.length;
let i = 0;
const fs = [];
for (; i < len; i++) {
const feature = features[i];
const coordinates = feature.geometry.coordinates;
const type = feature.geometry.type;
if (type === "Polygon") {
fs.push({
type: "Feature",
properties: {},
geometry: {
type: "Polygon",
coordinates: feature.geometry.coordinates.map((c) => tr(c)),
},
});
} else if (type === "MultiPolygon") {
const css = [];
for (let k = 0; k < coordinates.length; k++) {
const coordinate = coordinates[k];
const cs = [];
for (let n = 0; n < coordinate.length; n++) {
cs.push(tr(coordinates[k][n]));
}
css.push(cs);
}
fs.push({
type: "Feature",
properties: {},
geometry: {
type: "MultiPolygon",
coordinates: css,
},
});
}
}
return {
data: windGlCore.polygon2buffer(fs),
type: mask.type,
};
}
}
setMask(mask) {
this.options.mask = Object.assign({}, this.options.mask, mask);
if (this.layer) {
this.layer.setMask(this.processMask());
}
}
onRemove() {
if (this.layer) {
this.layer.destroy();
this.layer = null;
}
if (this.source) {
if (Array.isArray(this.source.sourceCache)) {
this.source.sourceCache?.forEach((s) => {
s?.clearTiles();
});
} else {
this.source.sourceCache?.clearTiles();
}
}
this._currentTiles = [];
this._unLimitTiles = [];
this.gl = null;
this._tileZoom = void 0;
return super.onRemove();
}
}
Object.defineProperty(exports, "Field", {
enumerable: true,
get: function () {
return windCore.Field;
},
});
Object.defineProperty(exports, "DecodeType", {
enumerable: true,
get: function () {
return windGlCore.DecodeType;
},
});
Object.defineProperty(exports, "ImageSource", {
enumerable: true,
get: function () {
return windGlCore.ImageSource;
},
});
Object.defineProperty(exports, "LayerSourceType", {
enumerable: true,
get: function () {
return windGlCore.LayerSourceType;
},
});
Object.defineProperty(exports, "MaskType", {
enumerable: true,
get: function () {
return windGlCore.MaskType;
},
});
Object.defineProperty(exports, "RenderFrom", {
enumerable: true,
get: function () {
return windGlCore.RenderFrom;
},
});
Object.defineProperty(exports, "RenderType", {
enumerable: true,
get: function () {
return windGlCore.RenderType;
},
});
Object.defineProperty(exports, "TileID", {
enumerable: true,
get: function () {
return windGlCore.TileID;
},
});
Object.defineProperty(exports, "TileSource", {
enumerable: true,
get: function () {
return windGlCore.TileSource;
},
});
Object.defineProperty(exports, "TimelineSource", {
enumerable: true,
get: function () {
return windGlCore.TimelineSource;
},
});
Object.defineProperty(exports, "configDeps", {
enumerable: true,
get: function () {
return windGlCore.configDeps;
},
});
exports.WebglLayer = WebglLayer;
exports.WindLayer = WindLayer;