UNPKG

itowns

Version:

A JS/WebGL framework for 3D geospatial data visualization

114 lines (92 loc) 3.59 kB
import { MathUtils, Vector3 } from 'three'; import { Coordinates, Extent, CameraUtils } from 'itowns'; // eslint-disable-next-line import/extensions import { createHTMLListFromObject } from './GUI/GuiTools.js'; /** * Function allowing picking on a given 3D tiles layer and filling an html div * with information on the picked feature. * @param {MouseEvent} event * @param {Object} pickingArg * @param {HTMLDivElement} pickingArg.htmlDiv - div element which contains the * picked information * @param {GlobeView} picking.view - iTowns view where the picking must be done * @param {OGC3DTilesLayer} pickingArg.layer - the layer on which the picking * must be done */ export function fillHTMLWithPickingInfo(event, pickingArg) { const { htmlDiv, view, layer } = pickingArg; // Remove content already in html div while (htmlDiv.firstChild) { htmlDiv.removeChild(htmlDiv.firstChild); } // Get intersected objects const intersects = view.pickObjectsAt(event, 5, layer); // Get information from intersected objects (from the batch table and // eventually the 3D Tiles extensions const closestC3DTileFeature = layer.getC3DTileFeatureFromIntersectsArray(intersects); if (closestC3DTileFeature) { // eslint-disable-next-line htmlDiv.appendChild(createHTMLListFromObject(closestC3DTileFeature)); } layer.getMetadataFromIntersections(intersects).then((metadata) => { // eslint-disable-next-line metadata?.forEach(m => htmlDiv.appendChild(createHTMLListFromObject(m))); }); } function zoomToSphere(view, tile, sphere) { const transform = tile.cached.transform; const center = new Vector3().fromArray(sphere).applyMatrix4(transform); const radius = sphere[3] * transform.getMaxScaleOnAxis(); // Get the distance to sphere where the diameter cover the whole screen // This is similar to SSE computation where sse = screen height. const fov = view.camera3D.fov * MathUtils.DEG2RAD; const distance = radius * Math.tan(fov * 2); return { coord: new Coordinates('EPSG:4978').setFromVector3(center), range: distance + radius, }; } function zoomToBox(view, tile, box) { const radius = Math.max( new Vector3().fromArray(box, 3).length(), new Vector3().fromArray(box, 6).length(), new Vector3().fromArray(box, 9).length(), ); // Approximate zoomToBox with sphere const sphere = [box[0], box[1], box[2], radius]; return zoomToSphere(view, tile, sphere); } function zoomToRegion(view, region) { const extent = new Extent('EPSG:4326', region[0] * MathUtils.RAD2DEG, // west region[2] * MathUtils.RAD2DEG, // east region[1] * MathUtils.RAD2DEG, // south region[3] * MathUtils.RAD2DEG, // north ); return CameraUtils.getCameraTransformOptionsFromExtent( view, view.camera3D, extent, ); } function zoomToTile(view, tile) { const { region, box, sphere } = tile.boundingVolume; let cameraTransform; if (region) { cameraTransform = zoomToRegion(view, region); } else if (box) { cameraTransform = zoomToBox(view, tile, box); } else { cameraTransform = zoomToSphere(view, tile, sphere); } view.controls.lookAtCoordinate({ coord: cameraTransform.coord, range: 1.25 * cameraTransform.range, // zoom out a little bit tilt: 60, }); } export function zoomToLayer(view, layer) { const root = layer.tilesRenderer.root; zoomToTile(view, root); }