@loaders.gl/tiles
Version:
Common components for different tiles loaders.
121 lines (111 loc) • 4.34 kB
text/typescript
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
import {Vector3} from '@math.gl/core';
import {BoundingSphere, OrientedBoundingBox} from '@math.gl/culling';
import {Ellipsoid} from '@math.gl/geospatial';
import {BoundingRectangle} from '../../types';
const WGS84_RADIUS_X = 6378137.0;
const WGS84_RADIUS_Y = 6378137.0;
const WGS84_RADIUS_Z = 6356752.3142451793;
const scratchVector = new Vector3();
/**
* Calculate appropriate zoom value for a particular boundingVolume
* @param boundingVolume - the instance of bounding volume
* @param cartorgraphicCenter - cartographic center of the bounding volume
* @returns {number} - zoom value
*/
export function getZoomFromBoundingVolume(
boundingVolume: BoundingSphere | OrientedBoundingBox | BoundingRectangle,
cartorgraphicCenter: Vector3
) {
if (boundingVolume instanceof OrientedBoundingBox) {
// OrientedBoundingBox
const {halfAxes} = boundingVolume;
const obbSize = getObbSize(halfAxes);
// Use WGS84_RADIUS_Z to allign with BoundingSphere algorithm
// Add the tile elevation value for correct zooming to elevated tiles
return Math.log2(WGS84_RADIUS_Z / (obbSize + cartorgraphicCenter[2]));
} else if (boundingVolume instanceof BoundingSphere) {
// BoundingSphere
const {radius} = boundingVolume;
// Add the tile elevation value for correct zooming to elevated tiles
return Math.log2(WGS84_RADIUS_Z / (radius + cartorgraphicCenter[2]));
} else if (boundingVolume.width && boundingVolume.height) {
// BoundingRectangle
const {width, height} = boundingVolume;
const zoomX = Math.log2(WGS84_RADIUS_X / width);
const zoomY = Math.log2(WGS84_RADIUS_Y / height);
return (zoomX + zoomY) / 2;
}
return 1;
}
/**
* Calculate initial zoom for the tileset from 3D `fullExtent` defined in
* the tileset metadata
* @param fullExtent - 3D extent of the tileset
* @param fullExtent.xmin - minimal longitude in decimal degrees
* @param fullExtent.xmax - maximal longitude in decimal degrees
* @param fullExtent.ymin - minimal latitude in decimal degrees
* @param fullExtent.ymax - maximal latitude in decimal degrees
* @param fullExtent.zmin - minimal elevation in meters
* @param fullExtent.zmax - maximal elevation in meters
* @param cartorgraphicCenter - tileset center in cartographic coordinate system
* @param cartesianCenter - tileset center in cartesian coordinate system
* @returns - initial zoom for the tileset
*/
export function getZoomFromFullExtent(
fullExtent: {
xmin: number;
xmax: number;
ymin: number;
ymax: number;
zmin: number;
zmax: number;
},
cartorgraphicCenter: Vector3,
cartesianCenter: Vector3
) {
Ellipsoid.WGS84.cartographicToCartesian(
[fullExtent.xmax, fullExtent.ymax, fullExtent.zmax],
scratchVector
);
const extentSize = Math.sqrt(
Math.pow(scratchVector[0] - cartesianCenter[0], 2) +
Math.pow(scratchVector[1] - cartesianCenter[1], 2) +
Math.pow(scratchVector[2] - cartesianCenter[2], 2)
);
return Math.log2(WGS84_RADIUS_Z / (extentSize + cartorgraphicCenter[2]));
}
/**
* Calculate initial zoom for the tileset from 2D `extent` defined in
* the tileset metadata
* @param extent - 2D extent of the tileset. It is array of 4 elements [xmin, ymin, xmax, ymax]
* @param extent[0] - minimal longitude in decimal degrees
* @param extent[1] - minimal latitude in decimal degrees
* @param extent[2] - maximal longitude in decimal degrees
* @param extent[3] - maximal latitude in decimal degrees
* @param cartorgraphicCenter - tileset center in cartographic coordinate system
* @param cartesianCenter - tileset center in cartesian coordinate system
* @returns - initial zoom for the tileset
*/
export function getZoomFromExtent(
extent: [number, number, number, number],
cartorgraphicCenter: Vector3,
cartesianCenter: Vector3
) {
const [xmin, ymin, xmax, ymax] = extent;
return getZoomFromFullExtent(
{xmin, xmax, ymin, ymax, zmin: 0, zmax: 0},
cartorgraphicCenter,
cartesianCenter
);
}
function getObbSize(halfAxes) {
halfAxes.getColumn(0, scratchVector);
const axeY = halfAxes.getColumn(1);
const axeZ = halfAxes.getColumn(2);
const farthestVertex = scratchVector.add(axeY).add(axeZ);
const size = farthestVertex.len();
return size;
}