@giro3d/giro3d
Version:
A JS/WebGL framework for 3D geospatial data visualization
79 lines (78 loc) • 3.09 kB
JavaScript
/*
* Copyright (c) 2015-2018, IGN France.
* Copyright (c) 2018-2026, Giro3D team.
* SPDX-License-Identifier: MIT
*/
import { Box3, MathUtils, Sphere, Vector2, Vector3 } from 'three';
import Coordinates from '../../core/geographic/Coordinates';
import CoordinateSystem from '../../core/geographic/CoordinateSystem';
import { toCartesian } from './PanoramaTileGeometry';
import TileVolume from './TileVolume';
const vec3 = new Vector3();
const vec2 = new Vector2();
const coord = new Coordinates(CoordinateSystem.epsg4326, 0, 0);
const tmpCorners = [];
export default class PanoramaTileVolume extends TileVolume {
_corners = null;
get extent() {
return this._extent;
}
get radius() {
return this._radius;
}
constructor(options) {
super();
this._extent = options.extent;
this._radius = options.radius;
}
getWorldSpaceCorners(matrix, target) {
if (this._corners == null) {
const dims = this._extent.dimensions(vec2);
const xCount = MathUtils.clamp(Math.round(dims.width / 5) + 1, 2, 6);
const yCount = MathUtils.clamp(Math.round(dims.height / 5) + 1, 2, 6);
this._corners = new Array(xCount * yCount);
let index = 0;
for (let i = 0; i < xCount; i++) {
for (let j = 0; j < yCount; j++) {
const u = i * (1 / (xCount - 1));
const v = j * (1 / (yCount - 1));
const {
latitude,
longitude
} = this._extent.sampleUV(u, v, coord);
const p0 = toCartesian(latitude, longitude, this._radius, new Vector3());
this._corners[index++] = p0;
}
}
}
target = target ?? [];
target.length = this._corners.length;
for (let i = 0; i < target.length; i++) {
target[i] = this._corners[i].clone().applyMatrix4(matrix);
}
return target;
}
computeLocalBox() {
const extent = this._extent;
const radius = this._radius;
const nw = toCartesian(extent.maxY, extent.minX, radius, new Vector3());
const sw = toCartesian(extent.minY, extent.minX, radius, new Vector3());
const se = toCartesian(extent.minY, extent.maxX, radius, new Vector3());
const ne = toCartesian(extent.maxY, extent.maxX, radius, new Vector3());
const center = extent.center(coord);
const c = toCartesian(center.latitude, center.longitude, radius, new Vector3());
const nc = toCartesian(extent.maxY, center.longitude, radius, new Vector3());
const cw = toCartesian(center.latitude, extent.minX, radius, new Vector3());
const ce = toCartesian(center.latitude, extent.maxX, radius, new Vector3());
const sc = toCartesian(extent.minY, center.longitude, radius, new Vector3());
const worldBox = new Box3().setFromPoints([nw, sw, se, ne, c, nc, cw, ce, sc]);
return worldBox.setFromCenterAndSize(worldBox.getCenter(vec3).sub(nw), worldBox.getSize(new Vector3()));
}
setElevationRange() {
// Nothing to do
}
getWorldSpaceBoundingSphere(target, matrix) {
target = target ?? new Sphere();
return target.setFromPoints(this.getWorldSpaceCorners(matrix, tmpCorners));
}
}