{ "cells": [ { "cell_type": "markdown", "id": "4c45a2b2", "metadata": {}, "source": [ "# XYZLoader TLS Demo\n", "\n", "Notebook: Sina Zumstein & Hannah Weiser, 2023\n", "\n", "This demo shows how to load a point cloud as scene part, which is then converted to a voxel model by HELIOS++, and scan it with terrestrial laser scanning (TLS). We will use the command-line access of HELIOS++ to run the simulation, and use Python just for displaying the input XMLs and the resulting point clouds." ] }, { "cell_type": "code", "execution_count": 1, "id": "b6b7df31", "metadata": {}, "outputs": [], "source": [ "from IPython.display import Code\n", "from pyhelios.util.xmldisplayer import display_xml, find_playback_dir" ] }, { "cell_type": "code", "execution_count": 2, "id": "a3bf8c2f", "metadata": {}, "outputs": [], "source": [ "import os\n", "os.chdir(\"..\")" ] }, { "cell_type": "markdown", "id": "07f322e7", "metadata": {}, "source": [ "## Survey\n", "Let us look at the XML files in the simulation. First, we investigate the survey XML file, `tls_sphere_xyzloader.xml` in `data\\surveys\\voxels`:" ] }, { "cell_type": "code", "execution_count": 3, "id": "f5342331", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
<document>\n",
"\n",
" <survey name="tls_sphere_xyzloader" scene="data/scenes/voxels/sphere_xyzloader.xml#sphere_xyzloader_demo" platform="data/platforms.xml#tripod" scanner="data/scanners_tls.xml#riegl_vz400">\n",
"\t\t<leg>\n",
" <platformSettings x="40" y="-10" z="0" onGround="true" />\n",
" <scannerSettings active="true" pulseFreq_hz="100000" verticalAngleMin_deg="-40.0" verticalAngleMax_deg="60.0" scanFreq_hz="120" headRotatePerSec_deg="10.00" headRotateStart_deg="250.0" headRotateStop_deg="380.0" />\n",
" </leg>\n",
" </survey>\n",
"</document>\n",
"
<platform id="tripod" name="TLS Tripod" type="static" drag="0">\n",
"\t\t<scannerMount x="0" y="0" z="1.5">\n",
"\t\t</scannerMount>\n",
"\t</platform>\n",
"\t\n",
"
<scanner id="riegl_vz400" name="RIEGL VZ-400" accuracy_m="0.005" beamDivergence_rad="0.0003" headRotatePerSecMax_deg="60" optics="rotating" pulseFreqs_Hz="100000,300000" pulseLength_ns="5" rangeMin_m="1.5" scanAngleMax_deg="120" scanAngleEffectiveMax_deg="50" scanFreqMin_Hz="3" scanFreqMax_Hz="120">\n",
"\t\t\n",
"\t\t<FWFSettings beamSampleQuality="3" />\t\n",
"\t\t<beamOrigin x="0" y="0" z="0.2">\n",
"\t\t\t<rot axis="y" angle_deg="0" />\n",
"\t\t\t<rot axis="z" angle_deg="0" />\n",
"\t\t\t<rot axis="x" angle_deg="0" />\n",
"\t\t</beamOrigin>\n",
"\t\t<headRotateAxis x="0" y="0" z="1" />\n",
"\t\t\n",
"\t</scanner>\n",
"\t\n",
"
<scene id="sphere_xyzloader_demo" name="sphere xyzloader demo">\n",
" <part>\n",
" <filter type="objloader">\n",
" <param type="string" key="filepath" value="data/sceneparts/basic/groundplane/groundplane.obj" />\n",
" </filter>\n",
" <filter type="scale">\n",
" <param type="double" key="scale" value="100" />\n",
" </filter>\n",
" </part>\n",
" <part>\n",
" <filter type="xyzloader">\n",
" <param type="string" key="filepath" value="data/sceneparts/pointclouds/sphere_dens25000.xyz" />\n",
"\t\t\t\t<param type="string" key="separator" value=" " />\n",
"\t\t\t\t<param type="double" key="voxelSize" value="1.0" />\n",
"\t\t\t\t<!-- Normal estimation using Singular Value Decomposition (SVD)\n",
"\t\t\t\tMODE 1: simple mode / MODE 2: advanced mode for large files, which works in batches -->\n",
"\t\t\t\t<param type="int" key="estimateNormals" value="1" />\n",
"\t\t\t\t<!-- If less than three points fall into one voxel, it is discarded.\n",
"\t\t\t\tTo avoid this, a default Normal can be assigned to these voxels with:\n",
"\t\t\t\t<param type="vec3" key="defaultNormal" value="0;0;1" /> -->\n",
"\t\t\t\t<param type="string" key="matfile" value="data/sceneparts/toyblocks/sphere.mtl" />\n",
"\t\t\t\t<param type="string" key="matname" value="Material.008" />\n",
" </filter>\n",
"\t\t\t<filter type="translate">\n",
"\t\t\t\t<param type="vec3" key="offset" value="0;0;10" />\n",
"\t\t\t</filter>\n",
"\t\t</part>\n",
" </scene>\n",
"\t\n",
"\t\n",
"