itowns
Version:
A JS/WebGL framework for 3D geospatial data visualization
261 lines (223 loc) • 10.3 kB
HTML
<html>
<head>
<title>Point Cloud Viewer</title>
<style type="text/css">
#info {
color: black;
position: absolute;
top: 0;
left: 0;
margin-left: 15px;
padding: 0.3rem;
background-color: white;
border: 2px solid black;
border-radius: 5px;
}
.centered {
margin-left: auto;
margin-right: auto;
max-width: 25rem;
border: 2px solid black;
padding: 1rem;
background: rgba(128, 168, 197, 1);
border-radius: 5px;
display: none;
}
#viewerDiv {
display: none;
}
input {
margin-top: 1rem;
font-size: 1rem;
}
#url {
width: calc(100% - 1rem);
}
#submit {
margin-left: 25%;
margin-right: 25%;
width: 50%;
}
/* lopocs result display */
table {
margin-top: 3rem;
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 0.3rem;
text-align: center;
}
tr:nth-child(even) {
background-color: #c6cfd5;
}
tr:nth-child(odd) {
background-color: #9fc0d5;
}
#result {
display: none;
}
@media (max-width: 600px) {
#info,
.dg {
display: none;
}
}
</style>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css/example.css">
<link rel="stylesheet" type="text/css" href="css/LoadingScreen.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="viewerDiv">
<div id="info"></div>
</div>
<div class="centered">
<div id="lopocs"> </div>
<div id="itowns"> </div>
<h2>Point cloud absolute URL: </h2>
<h4>(file.js from PotreeConverter or Lopocs url)</h4>
<input id="url" type="url" value="https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/pointclouds/eglise_saint_blaise_arles/eglise_saint_blaise_arles.js">
<input id="submit" type="submit" value="Connect">
<div id="result">
<h3>Available pointclouds:</h3>
<table id="dropdown"></table>
</div>
<!-- POINTCLOUD TABLE SELECTION -->
<script type="text/javascript">
function createResultRow(serverUrl, table) {
var tr = document.createElement('tr');
var td = document.createElement('td');
td.textContent = table;
var td2 = document.createElement('td');
var i = document.createElement('input');
i.value = 'Display';
i.type = 'submit';
function onDisplayClicked() {
showPointcloud(serverUrl, undefined, table, false);
}
i.addEventListener('click', onDisplayClicked);
td2.appendChild(i);
tr.appendChild(td);
tr.appendChild(td2);
return tr;
}
function buildLopocsResultTable(serverUrl, metadata) {
document.getElementById('result').style.display = 'block';
var dd = document.getElementById('dropdown');
// clean table
while (dd.firstChild) {
dd.removeChild(dd.firstChild);
}
var i;
for (i = 0; i < metadata.length; i++) {
dd.appendChild(createResultRow(serverUrl, metadata[i].table));
}
}
function onConnectClicked() {
var url = document.getElementById('url').value;
// assume that "url ends with .js" == potreeconverter
// no .endsWith() in ES5...
if (url.indexOf('.js') === (url.length - 3)) {
var lastSlashIndex = url.lastIndexOf('/');
var filename = url.substr(lastSlashIndex + 1);
showPointcloud(url.substr(0, lastSlashIndex), filename, undefined, true);
} else {
itowns.Fetcher.json(url + '/infos/sources').then(function(meta) { buildLopocsResultTable(url, meta); });
}
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
<script src="../dist/itowns.js"></script>
<script src="js/GUI/LoadingScreen.js"></script>
<script src="../dist/debug.js"></script>
<script type="text/javascript">
var searchParams = new URL(window.location.href).searchParams;
function showPointcloud(serverUrl, fileName, lopocsTable) {
var pointcloud;
var oldPostUpdate;
var viewerDiv;
var debugGui;
var view;
var controls;
viewerDiv = document.getElementById('viewerDiv');
viewerDiv.style.display = 'block';
itowns.THREE.Object3D.DefaultUp.set(0, 0, 1);
debugGui = new dat.GUI({ width: 400 });
// TODO: do we really need to disable logarithmicDepthBuffer ?
view = new itowns.View('EPSG:3946', viewerDiv);
setupLoadingScreen(viewerDiv, view);
view.mainLoop.gfxEngine.renderer.setClearColor(0xcccccc);
// Configure Point Cloud layer
pointcloud = new itowns.GeometryLayer('eglise_saint_blaise_arles', new itowns.THREE.Group());
pointcloud.file = fileName || 'infos/sources';
pointcloud.protocol = 'potreeconverter';
pointcloud.url = serverUrl;
pointcloud.table = lopocsTable;
if (searchParams.get('material') === 'three') {
pointcloud.material = new itowns.THREE.PointsMaterial({
color: 0xff8888,
sizeAttenuation: false,
size: 1,
vertexColors: itowns.THREE.VertexColors
});
}
// point selection on double-click
function dblClickHandler(event) {
var pick = view.pickObjectsAt(event, 5, pointcloud);
for (const p of pick) {
console.info('Selected point #' + p.index + ' in position (' +
p.object.position.x + ', ' +
p.object.position.y + ', ' +
p.object.position.z +
') in Points ' + p.object.layer.id);
}
}
view.mainLoop.gfxEngine.renderer.domElement.addEventListener('dblclick', dblClickHandler);
function placeCamera(position, lookAt) {
view.camera.camera3D.position.set(position.x, position.y, position.z);
view.camera.camera3D.lookAt(lookAt);
// create controls
controls = new itowns.FirstPersonControls(view, { focusOnClick: true });
debugGui.add(controls.options, 'moveSpeed', 1, 100).name('Movement speed');
view.notifyChange(view.camera.camera3D);
}
// add pointcloud to scene
function onLayerReady() {
var ratio;
var position;
var lookAt = new itowns.THREE.Vector3();
var size = new itowns.THREE.Vector3();
pointcloud.root.bbox.getSize(size);
pointcloud.root.bbox.getCenter(lookAt);
debug.PointCloudDebug.initTools(view, pointcloud, debugGui);
view.camera.camera3D.far = 2.0 * size.length();
ratio = size.x / size.z;
position = pointcloud.root.bbox.min.clone().add(
size.multiply({ x: 0, y: 0, z: ratio * 0.5 }));
lookAt.z = pointcloud.root.bbox.min.z;
placeCamera(position, lookAt);
controls.moveSpeed = size.length() / 3;
// update stats window
oldPostUpdate = pointcloud.postUpdate;
pointcloud.postUpdate = function postUpdate() {
var info = document.getElementById('info');
oldPostUpdate.apply(pointcloud, arguments);
info.textContent = 'Nb points: ' +
pointcloud.displayedCount.toLocaleString();
};
}
window.view = view;
view.addLayer(pointcloud).then(onLayerReady);
}
if (searchParams.get('selector')) {
document.getElementsByClassName('centered')[0].style.display = 'block';
document.getElementById('submit').addEventListener('click', onConnectClicked);
} else {
onConnectClicked();
}
</script>
</body>
</html>