diff --git a/.gitlab/ci/configure_common.cmake b/.gitlab/ci/configure_common.cmake index 02e6ca8c496bef22b292c571bcd7731165c606b8..9984c00b8aa4b397a68f04cd6fd9515b705ac075 100644 --- a/.gitlab/ci/configure_common.cmake +++ b/.gitlab/ci/configure_common.cmake @@ -4,6 +4,7 @@ set(LIDARVIEW_BUILD_ALL_MODULES ON CACHE BOOL "") set(LIDARVIEW_BUILD_EXAMPLES ON CACHE BOOL "") set(BUILD_TESTING ON CACHE STRING "") +set(LIDARVIEW_USE_PDAL ON CACHE STRING "") set(LIDARVIEW_USE_PCL ON CACHE STRING "") set(LIDARVIEW_USE_CERES ON CACHE STRING "") set(LIDARVIEW_USE_NANOFLANN ON CACHE STRING "") diff --git a/.gitlab/ci/docker/fedora35/install_deps.sh b/.gitlab/ci/docker/fedora35/install_deps.sh index 2fc7928aedf929715f1af21d3f6cd21fd4ac1caf..9bd50f84f28d55c78a271b04f20abba6fc93a706 100755 --- a/.gitlab/ci/docker/fedora35/install_deps.sh +++ b/.gitlab/ci/docker/fedora35/install_deps.sh @@ -33,7 +33,7 @@ dnf install -y --setopt=install_weak_deps=False \ dnf install -y --setopt=install_weak_deps=False \ libXcursor-devel libharu-devel utf8cpp-devel pugixml-devel libtiff-devel \ eigen3-devel double-conversion-devel glew-devel jsoncpp-devel boost-devel \ - libpcap-devel gdal-devel PDAL-devel liblas-devel pcl-devel yaml-cpp-devel + libpcap-devel gdal-devel PDAL-devel pcl-devel yaml-cpp-devel # Python dependencies dnf install -y --setopt=install_weak_deps=False \ diff --git a/.gitlab/ci/docker/ubuntu22/Dockerfile b/.gitlab/ci/docker/ubuntu22/Dockerfile index 8114fefa1089fc5a6c019cdadb594e85c9a44aab..61a733f27d1f4c23011938864d3e333092ab71a2 100644 --- a/.gitlab/ci/docker/ubuntu22/Dockerfile +++ b/.gitlab/ci/docker/ubuntu22/Dockerfile @@ -7,10 +7,6 @@ RUN sh /root/install_deps.sh COPY install_pythonqt.sh /root/install_pythonqt.sh RUN sh /root/install_pythonqt.sh -COPY install_liblas.sh /root/install_liblas.sh -COPY patches/las-new-boost.patch /root/patches/las-new-boost.patch -RUN sh /root/install_liblas.sh - COPY install_paraview.sh /root/install_paraview.sh RUN sh /root/install_paraview.sh diff --git a/.gitlab/ci/docker/ubuntu22/install_liblas.sh b/.gitlab/ci/docker/ubuntu22/install_liblas.sh deleted file mode 100755 index 1993b5e5945058d65fa779d569f139b6c4029e45..0000000000000000000000000000000000000000 --- a/.gitlab/ci/docker/ubuntu22/install_liblas.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -set -e - -readonly liblas_repo="https://github.com/libLAS/libLAS.git" -readonly liblas_commit="1.8.1" - -readonly liblas_root="$HOME/liblas" -readonly liblas_src="$liblas_root/src" -readonly liblas_build_root="$liblas_root/build" - -git clone "$liblas_repo" "$liblas_src" -git -C "$liblas_src" checkout "$liblas_commit" -git -C "$liblas_src" apply /root/patches/las-new-boost.patch - -liblas_build () { - local prefix="$1" - shift - - cmake -GNinja \ - -S "$liblas_src" \ - -B "$liblas_build_root" \ - -DWITH_GDAL:BOOL=FALSE \ - -DBUILD_OSGEO4W:BOOL=OFF \ - -DWITH_GEOTIFF:BOOL=FALSE \ - -DWITH_LASZIP:BOOL=FALSE \ - -DWITH_TESTS:BOOL=FALSE \ - -DWITH_UTILITIES:BOOL=FALSE \ - -DBoost_USE_STATIC_LIBS:BOOL=FALSE \ - "-DCMAKE_INSTALL_PREFIX=$prefix" \ - "$@" - cmake --build "$liblas_build_root" --target install -} - -liblas_build /usr - -rm -rf "$liblas_root" diff --git a/.gitlab/ci/docker/ubuntu22/patches/las-new-boost.patch b/.gitlab/ci/docker/ubuntu22/patches/las-new-boost.patch deleted file mode 100644 index 9858e607a5c50ad58785f81010325236c69e9f7b..0000000000000000000000000000000000000000 --- a/.gitlab/ci/docker/ubuntu22/patches/las-new-boost.patch +++ /dev/null @@ -1,61 +0,0 @@ -diff -u -Nru5 libLAS-1.8.1/include/liblas/detail/binary.hpp libLAS-1.8.1.new-boost/include/liblas/detail/binary.hpp ---- libLAS-1.8.1/include/liblas/detail/binary.hpp 2016-08-22 09:06:34.000000000 -0400 -+++ libLAS-1.8.1.new-boost/include/liblas/detail/binary.hpp 2021-10-19 18:42:44.908166204 -0400 -@@ -23,11 +23,11 @@ - #include - #include - - #include - #include --#include -+#include - #include - - #if CHAR_BIT != 8 - #error Platforms with CHAR_BIT != 8 are not supported - #endif -diff -u -Nru5 libLAS-1.8.1/src/c_api.cpp libLAS-1.8.1.new-boost/src/c_api.cpp ---- libLAS-1.8.1/src/c_api.cpp 2016-08-22 09:06:34.000000000 -0400 -+++ libLAS-1.8.1.new-boost/src/c_api.cpp 2021-10-19 18:46:56.615071745 -0400 -@@ -496,11 +496,11 @@ - liblas::SpatialReference* out_ref = ((liblas::SpatialReference*) hSRS); - std::vector transforms = reader->GetTransforms(); - - transforms.erase( std::remove_if( transforms.begin(), - transforms.end(), -- boost::bind( &IsReprojectionTransform, _1 ) ), -+ boost::bind( &IsReprojectionTransform, boost::placeholders::_1 ) ), - transforms.end()); - - liblas::TransformPtr srs_transform = liblas::TransformPtr(new liblas::ReprojectionTransform(in_ref, *out_ref, &h)); - if (transforms.size()) - transforms.insert(transforms.begin(), srs_transform); -@@ -1838,11 +1838,11 @@ - liblas::SpatialReference* out_ref = ((liblas::SpatialReference*) hSRS); - std::vector transforms = writer->GetTransforms(); - - transforms.erase( std::remove_if( transforms.begin(), - transforms.end(), -- boost::bind( &IsReprojectionTransform, _1 ) ), -+ boost::bind( &IsReprojectionTransform, boost::placeholders::_1 ) ), - transforms.end()); - - liblas::TransformPtr srs_transform = liblas::TransformPtr(new liblas::ReprojectionTransform(in_ref, *out_ref, &h)); - if (transforms.size()) - transforms.insert(transforms.begin(), srs_transform); -diff -u -Nru5 libLAS-1.8.1/src/header.cpp libLAS-1.8.1.new-boost/src/header.cpp ---- libLAS-1.8.1/src/header.cpp 2016-08-22 09:06:34.000000000 -0400 -+++ libLAS-1.8.1.new-boost/src/header.cpp 2021-10-19 18:47:54.707126839 -0400 -@@ -608,11 +608,11 @@ - void Header::DeleteVLRs(std::string const& name, uint16_t id) - { - - m_vlrs.erase( std::remove_if( m_vlrs.begin(), - m_vlrs.end(), -- boost::bind( &SameVLRs, name, id, _1 ) ), -+ boost::bind( &SameVLRs, name, id, boost::placeholders::_1 ) ), - m_vlrs.end()); - - m_recordsCount = static_cast(m_vlrs.size()); - - } diff --git a/Application/Client/CMakeLists.txt b/Application/Client/CMakeLists.txt index d36ae66c4cb8049ab13fabf5aab77201e1f144a1..a50669862cb1bd3e0a4cf6a6b9989deea16302c6 100644 --- a/Application/Client/CMakeLists.txt +++ b/Application/Client/CMakeLists.txt @@ -67,6 +67,10 @@ target_link_libraries(${SOFTWARE_NAME} LidarViewApp::lvApplicationComponents # Specific LidarView code base ) +target_compile_definitions(${SOFTWARE_NAME} + PRIVATE + "LIDARVIEW_USE_PDAL=$") + # Bundle Icon on Apple if(APPLE) get_target_property(MACOSX_BUNDLE_ICON_FILE ${SOFTWARE_NAME} MACOSX_BUNDLE_ICON_FILE) diff --git a/Application/Client/LidarViewMainWindow.cxx b/Application/Client/LidarViewMainWindow.cxx index 9bec1d66a174edb35306958e1aa59a532bcc785f..a13948a2de7ddca927cdcf57ceaf5a8e88de8bdb 100644 --- a/Application/Client/LidarViewMainWindow.cxx +++ b/Application/Client/LidarViewMainWindow.cxx @@ -23,7 +23,6 @@ #include "lqOpenPcapReaction.h" #include "lqOpenRecentFilesReaction.h" #include "lqOpenSensorReaction.h" -#include "lqSaveLASReaction.h" #include "lqSaveLidarFrameReaction.h" #include "lqSaveLidarStateReaction.h" #include "lqUpdateCalibrationReaction.h" @@ -438,7 +437,14 @@ void LidarViewMainWindow::setupGUICustom() this->Internals->actionSaveCSV, "DataSetCSVWriter", "csv", false, false, true, true); new lqSaveLidarFrameReaction( this->Internals->actionSavePLY, "PPLYWriter", "ply", false, false, true, true); - new lqSaveLASReaction(this->Internals->actionSaveLAS, false, false, true, true); + +// Check if PDAL should be used with lidarview. +#if LIDARVIEW_USE_PDAL + new lqSaveLidarFrameReaction( + this->Internals->actionSaveLAS, "PLASWriter", "las", false, false, true, true); +#else + this->Internals->actionSaveLAS->setEnabled(false); +#endif // Add save/load lidar state action new lqEnableAdvancedArraysReaction(this->Internals->actionEnableAdvancedArrays); diff --git a/Application/Client/LidarViewMainWindow.ui b/Application/Client/LidarViewMainWindow.ui index e860659ff5b48f128c8abaa260e992d52b4dd2e6..c7e992b985f0a9504b408690bf6286259aa978a4 100644 --- a/Application/Client/LidarViewMainWindow.ui +++ b/Application/Client/LidarViewMainWindow.ui @@ -563,6 +563,10 @@ + + + :/lvResources/Icons/las.png:/lvResources/Icons/las.png + Save LAS... @@ -700,18 +704,6 @@ Geolocation in absolute coordinates - - - - :/lvResources/Icons/las.png:/lvResources/Icons/las.png - - - Save &LAS - - - Save to ASPRS LAS format - - diff --git a/Application/Wrapping/Python/applogic.py b/Application/Wrapping/Python/applogic.py index 211beda0ae4815254d492f22bed685b105cae4e7..fb4237bb9cb1fe79490b26d1307cb628404dc13f 100644 --- a/Application/Wrapping/Python/applogic.py +++ b/Application/Wrapping/Python/applogic.py @@ -334,41 +334,6 @@ def saveCSVCurrentFrameSelection(filename): smp.Delete(w) rotateCSVFile(filename) -# transform parameter indicates the coordinates system and -# the referential for the exported points clouds: -# - 0 Sensor: sensor referential, cartesian coordinate system -# - 1: Relative Geoposition: NED base centered at the first position -# of the sensor, cartesian coordinate system -# - 2: Absolute Geoposition: NED base centered at the corresponding -# UTM zone, cartesian coordinate system -# - 3: Absolute Geoposition Lat/Lon: Lat / Lon coordinate system -def saveLASFrames(filename, first, last, transform = 0): - reader = getReader().GetClientSideObject() - - # Check that we have a position provider - if getPosition() is not None: - position = getPosition().GetClientSideObject().GetOutput() - - PythonQt.paraview.lqLidarViewManager.saveFramesToLAS( - reader, position, first, last, filename, transform) - - else: - PythonQt.paraview.lqLidarViewManager.saveFramesToLAS( - reader, None, first, last, filename, transform) - - -# transform parameter indicates the coordinates system and -# the referential for the exported points clouds: -# - 0 Sensor: sensor referential, cartesian coordinate system -# - 1: Relative Geoposition: NED base centered at the first position -# of the sensor, cartesian coordinate system -# - 2: Absolute Geoposition: NED base centered at the corresponding -# UTM zone, cartesian coordinate system -# - 3: Absolute Geoposition Lat/Lon: Lat / Lon coordinate system -def saveLASCurrentFrame(filename, transform = 0): - t = getAnimationScene().AnimationTime - saveLASFrames(filename, t, t, transform) - def saveFrameRange(filename, frameStart, frameStop, saveFunction): timesteps = range(frameStart, frameStop+1) saveFunction(filename, timesteps) @@ -397,29 +362,6 @@ def saveCSV(filename, timesteps): kiwiviewerExporter.zipDir(outDir, filename) kiwiviewerExporter.shutil.rmtree(tempDir) -# transform parameter indicates the coordinates system and -# the referential for the exported points clouds: -# - 0 Sensor: sensor referential, cartesian coordinate system -# - 1: Relative Geoposition: NED base centered at the first position -# of the sensor, cartesian coordinate system -# - 2: Absolute Geoposition: NED base centered at the corresponding -# UTM zone, cartesian coordinate system -# - 3: Absolute Geoposition Lat/Lon: Lat / Lon coordinate system -def saveLAS(filename, timesteps, transform = 0): - - tempDir = kiwiviewerExporter.tempfile.mkdtemp() - basenameWithoutExtension = os.path.splitext(os.path.basename(filename))[0] - outDir = os.path.join(tempDir, basenameWithoutExtension) - filenameTemplate = os.path.join(outDir, basenameWithoutExtension + '_%04d.csv') - os.makedirs(outDir) - - for t in sorted(timesteps): - saveLASFrames(filenameTemplate % t, t, t, transform) - - kiwiviewerExporter.zipDir(outDir, filename) - kiwiviewerExporter.shutil.rmtree(tempDir) - - def getSaveFileName(title, extension, defaultFileName=None): settings = getPVSettings() @@ -473,72 +415,6 @@ def onSavePosition(): if fileName: savePositionCSV(fileName) - -def onSaveLAS(): - # It is not possible to save as LAS during stream as we need frame numbers - if getSensor(): - QtGui.QMessageBox.information(getMainWindow(), - 'Save As LAS not available during stream', - 'Saving as LAS is not possible during lidar stream mode. ' - 'Please use the "Record" tool, and open the resulting pcap offline to process it.') - return - - frameOptions = getFrameSelectionFromUser(framePackVisibility=True, frameTransformVisibility=False) - if frameOptions is None: - return - - if frameOptions.mode == lqSelectFramesDialog.CURRENT_FRAME: - frameOptions.start = frameOptions.stop = getAnimationScene().AnimationTime - elif frameOptions.mode == lqSelectFramesDialog.ALL_FRAMES: - frameOptions.start = int(getAnimationScene().StartTime) - frameOptions.stop = int(getAnimationScene().EndTime) - - if frameOptions.mode == lqSelectFramesDialog.CURRENT_FRAME: - fileName = getSaveFileName('Save LAS', 'las', getDefaultSaveFileName('las', appendFrameNumber=True)) - if fileName: - oldTransform = transformMode() - setTransformMode(1 if frameOptions.transform else 0) - - saveLASCurrentFrame(fileName, frameOptions.transform) - - setTransformMode(oldTransform) - - elif frameOptions.pack == lqSelectFramesDialog.FILE_PER_FRAME: - fileName = getSaveFileName('Save LAS (to zip file)', 'zip', - getDefaultSaveFileName('zip')) - if fileName: - oldTransform = transformMode() - setTransformMode(1 if frameOptions.transform else 0) - - def saveTransformedLAS(filename, timesteps): - saveLAS(filename, timesteps, frameOptions.transform) - - if frameOptions.mode == lqSelectFramesDialog.ALL_FRAMES: - start = 0 - stop = len(getLidar().TimestepValues) - 1 - else: - start = frameOptions.start - stop = frameOptions.stop - saveFrameRange(fileName, start, stop, saveTransformedLAS) - - setTransformMode(oldTransform) - - else: - suffix = ' (Frame %d to %d)' % (frameOptions.start, frameOptions.stop) - defaultFileName = getDefaultSaveFileName('las', suffix=suffix) - fileName = getSaveFileName('Save LAS', 'las', defaultFileName) - if not fileName: - return - - oldTransform = transformMode() - setTransformMode(1 if frameOptions.transform else 0) - - saveLASFrames(fileName, frameOptions.start, frameOptions.stop, - frameOptions.transform) - - setTransformMode(oldTransform) - - def onSavePCAP(): # It is not possible to save as PCAP during stream as we need frame numbers if getSensor(): diff --git a/LVCore b/LVCore index 5ad8429a59a50d07867ff52c1b9f79e4ee492039..c117bbddf2cbeebaa57cf6fefd9edd056da860d2 160000 --- a/LVCore +++ b/LVCore @@ -1 +1 @@ -Subproject commit 5ad8429a59a50d07867ff52c1b9f79e4ee492039 +Subproject commit c117bbddf2cbeebaa57cf6fefd9edd056da860d2