UNPKG

itowns

Version:

A JS/WebGL framework for 3D geospatial data visualization

250 lines (191 loc) 11.3 kB
<html> <head> <title>iTowns - Potree</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" type="text/css" href="css/example.css"> <link rel="stylesheet" type="text/css" href="css/LoadingScreen.css"> <link rel="stylesheet" type="text/css" href="../potree/build/potree/potree.css"> <link rel="stylesheet" type="text/css" href="../potree/libs/jquery-ui/jquery-ui.min.css"> <link rel="stylesheet" type="text/css" href="../potree/libs/spectrum/spectrum.css"> <link rel="stylesheet" type="text/css" href="../potree/libs/jstree/themes/mixed/style.css"> <style type="text/css"> tr { color: white; } </style> </head> <body> <div class="potree_container" style="position: absolute; width: 100%; height: 100%; left: 0px; top: 0px; "> <div id="potree_render_area"></div> <div id="potree_sidebar_container"></div> </div> <!-- Import iTowns source code --> <script src="../dist/itowns.js"></script> <script src="../dist/debug.js"></script> <!-- Import iTowns LoadingScreen pluggin --> <script src="js/GUI/LoadingScreen.js"></script> <!-- Define THREE and proj4 constants so that Potree may access them. Otherwise, we would need to access them with `itowns.THREE` or `itowns.proj4`. --> <script type="text/javascript"> const THREE = itowns.THREE; THREE.Object3D.DEFAULT_UP.set(0, 0, 1); const proj4 = itowns.proj4; </script> <!-- Import Potree source code --> <script src="../potree/libs/jquery/jquery-3.1.1.min.js"></script> <script src="../potree/libs/i18next/i18next.js"></script> <script src="../potree/libs/jstree/jstree.min.js"></script> <script src="../potree/libs/plasio/js/laslaz.js"></script> <script src="../potree/build/potree/potree.js"></script> <script type="text/javascript"> // `viewerDiv` contains both iTowns and Potree rendering area (`<canvas>`) const viewerDiv = document.getElementById('potree_render_area'); // ---------- CREATE A POTREE VIEWER FOR SUPPORTING POINT CLOUD VISUALIZATION : ---------- const coordinates = new itowns.Coordinates('EPSG:4978'); // Define crs projection of the point cloud data (taken from https://epsg.io/2154, Proj4js section) proj4.defs( 'EPSG:2154', '+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80' + ' towgs84=0,0,0,0,0,0,0 +units=m +no_defs' ); const pointCloudCRS = 'EPSG:2154'; Potree.setTHREEShaderChunk(itowns.ShaderChunk.target); // Create a Potree Viewer to support point cloud visualization const potreeViewer = new Potree.Viewer(viewerDiv, { dynamicNearFar: false, isGeocentric: true, crs: pointCloudCRS, // Callback to transform coordinates displayed by Potree `Point measurement` in `EPSG:2154` measureCoordinateCallback: (position) => { return coordinates.setFromVector3(position).as(pointCloudCRS).toVector3(); }, }); potreeViewer.setEDLEnabled(true); potreeViewer.setControls(null); potreeViewer.setBackground('black'); potreeViewer.loadGUI(); // Override Potree area measure method. The original Potree method gives a planar area delimited from given // points (summits of the area). The area returned by the method is computed from `x` and `y` components of // the points coordinates. // // By default, the points coordinates passed to the method are in iTowns viewer CRS, which is geocentric. // Therefore, computing an area over the `x` and `y` components of these coordinates is incorrect - it // actualy computes its orthogonal projection on the equatorial plane. // // To fix this, we transform each coordinates of the area summits in the point cloud CRS, which is // geographic. We store each transformed coordinates in an array. Finally we override Potree area measure // method so that it computes area from this array. potreeViewer.scene.addEventListener('measurement_added', (e) => { const { measurement } = e; if(measurement.name === "Area") { // Array containing the geographic coordinates of each area summits const areaPoints = [new itowns.Coordinates(pointCloudCRS)]; // Add a Coordinates to the array when an area summit is created. measurement.addEventListener('marker_added', () => { areaPoints.push(new itowns.Coordinates(pointCloudCRS)); }, false) // Translate the area summit coordinates from itowns viewer CRS to geographic CRS when the summit is // moved. It also happens when the summit is created. measurement.addEventListener('marker_moved', (event) => { coordinates.setFromVector3(event.position).as(pointCloudCRS, areaPoints[event.index]); }, false); // Clear the coordinates array when we remove an area summit. measurement.addEventListener('marker_removed', () => { areaPoints.splice(areaPoints.length - 1, 1); }, false); // Override potree `Measure.getArea` method to use projected coordinates to compute area measurement.getArea = () => { let area = 0; let j = areaPoints.length - 1; for (let i = 0; i < areaPoints.length; i++) { let p1 = areaPoints[i]; let p2 = areaPoints[j]; area += (p2.x + p1.x) * (p1.y - p2.y); j = i } return Math.abs(area / 2); }; } }); // ---------- CREATE A GlobeView FOR SUPPORTING ORTHO-PHOTOGRAPHIES AND DEM VISUALIZATION : ---------- // Define camera initial position. const placement = { heading: -35, tilt: 30, } // Create a GlobeView. const itownsViewer = new itowns.GlobeView(viewerDiv, placement, { renderer: potreeViewer.renderer, scene3D: potreeViewer.scene.scene, }); // Setup loading screen. setupLoadingScreen(viewerDiv, itownsViewer); // Make atmosphere realistic. itownsViewer.getLayerById('atmosphere').setRealisticOn(true); // Controls and camera specific setting. itownsViewer.controls.minDistanceCollision = 0.01; itownsViewer.controls.minDistance = 20; view.camera3D.near = 0.1; // ---------- TWEAK ITOWNS VIEWER TO SUPPORT POTREE VISUALIZATION : ---------- itownsViewer.render = () => {}; // Force iTowns viewer to resize when changing #potree_render_area div size. // This allows the viewer resizing when toggling potree menu. new ResizeObserver(() => itownsViewer.resize()).observe(viewerDiv); // Disable iTowns controls when hovering Potree tool (such as a vertex of a displayed polygon). // This prevents iTowns camera from moving when we want to displace a Potree tool marker. viewerDiv.addEventListener('mousemove', () => { itownsViewer.controls.states.enabled = potreeViewer.inputHandler.hoveredElements.length === 0; }) // Set Potree viewer camera as iTowns viewer camera. view.camera3D.zoomTo = () => {}; potreeViewer.scene.cameraP = view.camera3D; // TODO : should be moved to Label2DRenderer constructor itownsViewer.mainLoop.gfxEngine.label2dRenderer.domElement.style.pointerEvents = 'none'; // ---------- DISPLAY CONTEXTUAL DATA USING ITOWNS : ---------- // Add one imagery layer to the scene. This layer's properties are defined in a json file, but it could be // defined as a plain js object. See `Layer` documentation for more info. itowns.Fetcher.json('./layers/JSONLayers/Ortho.json').then(function _(config) { config.source = new itowns.WMTSSource(config.source); config.source.zoom = { max: 19, min: 3 }; itownsViewer.addLayer( new itowns.ColorLayer(config.id, config), ); }); // Add two elevaion layers, each with a different level of detail. Here again, each layer's properties are // defined in a json file. function addElevationLayerFromConfig(config) { config.source = new itowns.WMTSSource(config.source); itownsViewer.addLayer( new itowns.ElevationLayer(config.id, config), ); } itowns.Fetcher.json('layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig); itowns.Fetcher.json('layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig); // ---------- DISPLAY POINT CLOUD DATA USING POTREE : ---------- const pointcloudUrl = `${location.protocol}//lidarhd.pocgpf.ovh/data/`; itowns.Fetcher.json( pointcloudUrl + 'metadata/pivotTHREE.json' ).then( (pivot) => new THREE.ObjectLoader().parse(pivot) ).then( (pivotTHREE) => { Potree.loadPointCloud(pointcloudUrl + 'ept/ept.json', 'pointcloud', function(e) { const pointcloud = e.pointcloud; const material = pointcloud.material; potreeViewer.scene.addPointCloud(pointcloud); pointcloud.getAttribute('intensity').range = [0, 10000]; material.pointSizeType = Potree.PointSizeType.ADAPTIVE; material.shape = Potree.PointShape.CIRCLE; pointcloud.position.copy(pivotTHREE.position); pointcloud.quaternion.copy(pivotTHREE.quaternion); pointcloud.updateMatrixWorld(true); // Move itowns viewer camera to the center of the point cloud itownsViewer.controls.lookAtCoordinate({ coord: new itowns.Coordinates('EPSG:4978').setFromVector3(pivotTHREE.position), range: 1500 }, false); }); } ); </script> </body> </html>