From df6f4cb5ef2a756994e335a536775c217ebd82a2 Mon Sep 17 00:00:00 2001 From: Long Huan <8551701+longhuan2018@users.noreply.github.com> Date: Tue, 28 Sep 2021 11:37:41 +0800 Subject: [PATCH 1/2] Use PDAL instead of liblas --- CMakeLists.txt | 2 +- src/osgPlugins/CMakeLists.txt | 2 +- src/osgPlugins/las/CMakeLists.txt | 7 +- src/osgPlugins/las/ReaderWriterLAS.cpp | 398 +++++++++++++------------ 4 files changed, 209 insertions(+), 200 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21d2c05d423..18f58a3c88f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -782,7 +782,7 @@ ELSE() ENDIF() FIND_PACKAGE(ZeroConf) - FIND_PACKAGE(LIBLAS) + FIND_PACKAGE(PDAL CONFIG) IF (NOT(OSG_USE_LOCAL_LUA_SOURCE)) FIND_PACKAGE(Lua52) diff --git a/src/osgPlugins/CMakeLists.txt b/src/osgPlugins/CMakeLists.txt index 277dbebd5bd..13a53b6cde3 100644 --- a/src/osgPlugins/CMakeLists.txt +++ b/src/osgPlugins/CMakeLists.txt @@ -272,7 +272,7 @@ ADD_PLUGIN_DIRECTORY(osc) ADD_PLUGIN_DIRECTORY(trk) ADD_PLUGIN_DIRECTORY(tf) -IF(LIBLAS_FOUND) +IF(PDAL_FOUND) ADD_PLUGIN_DIRECTORY(las) ENDIF() diff --git a/src/osgPlugins/las/CMakeLists.txt b/src/osgPlugins/las/CMakeLists.txt index f3cdf01234c..50ff5c01806 100644 --- a/src/osgPlugins/las/CMakeLists.txt +++ b/src/osgPlugins/las/CMakeLists.txt @@ -1,9 +1,10 @@ -INCLUDE_DIRECTORIES(${LIBLAS_INCLUDE_DIR}) -INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${PDAL_INCLUDE_DIRS}) + +ADD_DEFINITIONS(-DNOMINMAX) SET(TARGET_SRC ReaderWriterLAS.cpp ) -SET(TARGET_LIBRARIES_VARS LIBLAS_LIBRARY LIBLASC_LIBRARY) +SET(TARGET_LIBRARIES_VARS PDAL_LIBRARIES) #### end var setup ### SETUP_PLUGIN(las) diff --git a/src/osgPlugins/las/ReaderWriterLAS.cpp b/src/osgPlugins/las/ReaderWriterLAS.cpp index 029807715d7..7d2a704a372 100644 --- a/src/osgPlugins/las/ReaderWriterLAS.cpp +++ b/src/osgPlugins/las/ReaderWriterLAS.cpp @@ -8,16 +8,19 @@ #include #include #include +#include #include #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include class ReaderWriterLAS : public osgDB::ReaderWriter { @@ -48,248 +51,253 @@ class ReaderWriterLAS : public osgDB::ReaderWriter if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; OSG_INFO << "Reading file " << fileName << std::endl; - std::ifstream ifs; - if (!liblas::Open(ifs, file)) - { - return ReadResult::ERROR_IN_READING_FILE; - } - return readNode(ifs, options); - } - - virtual ReadResult readObject(std::istream& fin, const osgDB::ReaderWriter::Options* options) const - { - return readNode(fin, options); - } - virtual ReadResult readNode(std::istream& ifs, const Options* options) const { - // Reading options - bool _verbose = false; - bool _scale = true; - bool _recenter = true; - if (options) + try { - std::istringstream iss(options->getOptionString()); - std::string opt; - while (iss >> opt) + std::string inFile = fileName; +#ifdef OSG_USE_UTF8_FILENAME + inFile = osgDB::convertStringFromUTF8toCurrentCodePage(inFile); +#endif + pdal::Option las_opt("filename", inFile); + pdal::Options las_opts; + las_opts.add(las_opt); + pdal::PointTable table; + pdal::LasReader las_reader; + las_reader.setOptions(las_opts); + las_reader.prepare(table); + pdal::PointViewSet point_view_set = las_reader.execute(table); + pdal::PointViewPtr point_view = *point_view_set.begin(); + pdal::Dimension::IdList dims = point_view->dims(); + pdal::LasHeader h = las_reader.header(); + + // Reading options + bool _verbose = false; + bool _scale = true; + bool _recenter = true; + if (options) { - if (opt == "v") + std::istringstream iss(options->getOptionString()); + std::string opt; + while (iss >> opt) { - _verbose = true; - } - if (opt == "noScale") - { - _scale = false; - } - if (opt == "noReCenter") - { - _recenter = false; + if (opt == "v") + { + _verbose = true; + } + if (opt == "noScale") + { + _scale = false; + } + if (opt == "noReCenter") + { + _recenter = false; + } } } - } - liblas::ReaderFactory f; - liblas::Reader reader = f.CreateWithStream(ifs); - liblas::Header const& h = reader.GetHeader(); - if (_verbose) - { - //std::cout << "File name: " << file << '\n'; - //std::cout << "Version : " << reader.GetVersion() << '\n'; - std::cout << "Signature: " << h.GetFileSignature() << '\n'; - std::cout << "Format : " << h.GetDataFormatId() << '\n'; - std::cout << "Project : " << h.GetProjectId() << '\n'; - std::cout << "Points count: " << h.GetPointRecordsCount() << '\n'; - std::cout << "VLRecords count: " << h.GetRecordsCount() << '\n'; - std::cout << "Points by return: "; - std::copy(h.GetPointRecordsByReturnCount().begin(), - h.GetPointRecordsByReturnCount().end(), - std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - } - - - // POINTS //// + if (_verbose) + { + //std::cout << "File name: " << file << '\n'; + //std::cout << "Version : " << reader.GetVersion() << '\n'; + std::cout << "Signature: " << h.fileSignature() << '\n'; + std::cout << "Format : " << h.pointFormat() << '\n'; + std::cout << "Project : " << h.projectId() << '\n'; + std::cout << "Points count: " << h.pointCount() << '\n'; + std::cout << "VLRecords count: " << h.vlrCount() << '\n'; + std::cout << "Points by return: "; + for (std::size_t i = 0; i < h.maxReturnCount(); ++i) + std::cout << h.pointCountByReturn(i) << " "; + std::cout << std::endl; + } - unsigned int targetNumVertices = 10000; - osg::Geode* geode = new osg::Geode; + // POINTS //// - osg::Geometry* geometry = new osg::Geometry; + unsigned int targetNumVertices = 10000; - osg::Vec3Array* vertices = new osg::Vec3Array; - osg::Vec4ubArray* colours = new osg::Vec4ubArray; + osg::Geode* geode = new osg::Geode; - vertices->reserve(targetNumVertices); - colours->reserve(targetNumVertices); + osg::Geometry* geometry = new osg::Geometry; - liblas::detail::Timer t; - t.start(); - typedef std::pair minmax_t; - minmax_t mx (DBL_MAX, -DBL_MAX); - minmax_t my (DBL_MAX, -DBL_MAX); - minmax_t mz (DBL_MAX, -DBL_MAX); + osg::Vec3Array* vertices = new osg::Vec3Array; + osg::Vec4ubArray* colours = new osg::Vec4ubArray; - uint32_t i = 0; - bool singleColor = true; - liblas::Color singleColorValue; - while (reader.ReadNextPoint()) - { - liblas::Point const& p = reader.GetPoint(); + vertices->reserve(targetNumVertices); + colours->reserve(targetNumVertices); - // Extract color components from LAS point - liblas::Color c = p.GetColor(); - uint32_t r = c.GetRed() >> 8; - uint32_t g = c.GetGreen() >> 8; - uint32_t b = c.GetBlue() >> 8; - uint32_t a = 255; // default value, since LAS point has no alpha information + std::chrono::system_clock::time_point t_start = std::chrono::system_clock::now(); + typedef std::pair minmax_t; + minmax_t mx (DBL_MAX, -DBL_MAX); + minmax_t my (DBL_MAX, -DBL_MAX); + minmax_t mz (DBL_MAX, -DBL_MAX); - if (vertices->size() == 0) - { - singleColorValue = c; - singleColor = true; - } - else + uint32_t i = 0; + bool singleColor = true; + osg::Vec4ub singleColorValue; + for (pdal::PointId idx = 0; idx < point_view->size(); ++idx) { - if (singleColor) + // Extract color components from LAS point + uint32_t r = point_view->getFieldAs(pdal::Dimension::Id::Red, idx) >> 8; + uint32_t g = point_view->getFieldAs(pdal::Dimension::Id::Green, idx) >> 8; + uint32_t b = point_view->getFieldAs(pdal::Dimension::Id::Blue, idx) >> 8; + uint32_t a = 255; // default value, since LAS point has no alpha information + + if (vertices->size() == 0) { - singleColor = singleColorValue == c;//set false if different color found + singleColorValue = osg::Vec4ub(r, g, b, a); + singleColor = true; } - } - if (vertices->size() >= targetNumVertices) - { - // finishing setting up the current geometry and add it to the geode. - geometry->setUseDisplayList(true); - geometry->setUseVertexBufferObjects(true); - geometry->setVertexArray(vertices); - if (singleColor) + else { - colours->resize(1); - geometry->setColorArray(colours, osg::Array::BIND_OVERALL); + if (singleColor) + { + singleColor = singleColorValue == osg::Vec4ub(r, g, b, a);//set false if different color found + } } - else + if (vertices->size() >= targetNumVertices) { - geometry->setColorArray(colours, osg::Array::BIND_PER_VERTEX); + // finishing setting up the current geometry and add it to the geode. + geometry->setUseDisplayList(true); + geometry->setUseVertexBufferObjects(true); + geometry->setVertexArray(vertices); + if (singleColor) + { + colours->resize(1); + geometry->setColorArray(colours, osg::Array::BIND_OVERALL); + } + else + { + geometry->setColorArray(colours, osg::Array::BIND_PER_VERTEX); - } - geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vertices->size())); + } + geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vertices->size())); + + geode->addDrawable(geometry); + + // allocate a new geometry + geometry = new osg::Geometry; - geode->addDrawable(geometry); + vertices = new osg::Vec3Array; + colours = new osg::Vec4ubArray; - // allocate a new geometry - geometry = new osg::Geometry; + vertices->reserve(targetNumVertices); + colours->reserve(targetNumVertices); + } + double X = point_view->getFieldAs(pdal::Dimension::Id::X, idx) - h.offsetX(); + double Y = point_view->getFieldAs(pdal::Dimension::Id::Y, idx) - h.offsetY(); + double Z = point_view->getFieldAs(pdal::Dimension::Id::Z, idx) - h.offsetZ(); + if (!_scale) + { + X /= h.scaleX(); + Y /= h.scaleY(); + Z /= h.scaleZ(); + } + if (_recenter) + { + mx.first = std::min(mx.first, X); + mx.second = std::max(mx.second, X); + my.first = std::min(my.first, Y); + my.second = std::max(my.second, Y); + mz.first = std::min(mz.first, Z); + mz.second = std::max(mz.second, Z); + } + vertices->push_back(osg::Vec3(X, Y, Z)); - vertices = new osg::Vec3Array; - colours = new osg::Vec4ubArray; + colours->push_back(osg::Vec4ub(r, g, b, a)); - vertices->reserve(targetNumVertices); - colours->reserve(targetNumVertices); + // Warning: Printing zillion of points may take looong time + //std::cout << i << ". " << p << '\n'; + i++; } - double X = p.GetRawX(); - double Y = p.GetRawY(); - double Z = p.GetRawZ(); - if (_scale) + // calculate the mid point of the point cloud + double mid_x = 0.5*(mx.second + mx.first); + double mid_y = 0.5*(my.second + my.first); + double mid_z = 0.5*(mz.second + mz.first); + osg::Vec3 midVec(mid_x, mid_y, mid_z); + + geometry->setUseDisplayList(true); + geometry->setUseVertexBufferObjects(true); + geometry->setVertexArray(vertices); + if (singleColor) { - X *= h.GetScaleX(); - Y *= h.GetScaleY(); - Z *= h.GetScaleZ(); + colours->resize(1); + geometry->setColorArray(colours, osg::Array::BIND_OVERALL); } - if (_recenter) + else { - mx.first = std::min(mx.first, X); - mx.second = std::max(mx.second, X); - my.first = std::min(my.first, Y); - my.second = std::max(my.second, Y); - mz.first = std::min(mz.first, Z); - mz.second = std::max(mz.second, Z); - } - vertices->push_back(osg::Vec3(X, Y, Z)); - - colours->push_back(osg::Vec4ub(r, g, b, a)); - - // Warning: Printing zillion of points may take looong time - //std::cout << i << ". " << p << '\n'; - i++; - } - // calculate the mid point of the point cloud - double mid_x = 0.5*(mx.second + mx.first); - double mid_y = 0.5*(my.second + my.first); - double mid_z = 0.5*(mz.second + mz.first); - osg::Vec3 midVec(mid_x, mid_y, mid_z); - - geometry->setUseDisplayList(true); - geometry->setUseVertexBufferObjects(true); - geometry->setVertexArray(vertices); - if (singleColor) - { - colours->resize(1); - geometry->setColorArray(colours, osg::Array::BIND_OVERALL); - } - else - { - geometry->setColorArray(colours, osg::Array::BIND_PER_VERTEX); + geometry->setColorArray(colours, osg::Array::BIND_PER_VERTEX); - } - geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vertices->size())); + } + geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vertices->size())); - geode->addDrawable(geometry); + geode->addDrawable(geometry); - if (_recenter) - { - //Transform vertices to midpoint - for (unsigned int geomIndex = 0; geomIndex < geode->getNumDrawables(); ++geomIndex) + if (_recenter) { - osg::Geometry *geom = dynamic_cast(geode->getDrawable(geomIndex)); - if (geom) + //Transform vertices to midpoint + for (unsigned int geomIndex = 0; geomIndex < geode->getNumDrawables(); ++geomIndex) { - osg::Vec3Array* vertArray = dynamic_cast(geom->getVertexArray()); - size_t vertArraySize = vertArray->size(); - for (size_t vertexIndex = 0; vertexIndex < vertArraySize; ++vertexIndex) + osg::Geometry *geom = dynamic_cast(geode->getDrawable(geomIndex)); + if (geom) { - (*vertArray)[vertexIndex] -= midVec; + osg::Vec3Array* vertArray = dynamic_cast(geom->getVertexArray()); + size_t vertArraySize = vertArray->size(); + for (size_t vertexIndex = 0; vertexIndex < vertArraySize; ++vertexIndex) + { + (*vertArray)[vertexIndex] -= midVec; + } } } } - } - double const d2 = t.stop(); + std::chrono::system_clock::time_point t_end = std::chrono::system_clock::now(); + std::chrono::microseconds t_duration = std::chrono::duration_cast(t_end - t_start); + double const d2 = double(t_duration.count())*std::chrono::microseconds::period::num / std::chrono::microseconds::period::den; - if (_verbose) - { - std::cout << "Read points: " << i << " Elapsed Time: " << d2 - << std::endl << std::endl; - } + if (_verbose) + { + std::cout << "Read points: " << i << " Elapsed Time: " << d2 + << std::endl << std::endl; + } - // MatrixTransform with the mid-point translation + // MatrixTransform with the mid-point translation - osg::MatrixTransform *mt = new osg::MatrixTransform; - mt->setDataVariance(osg::Object::STATIC);//can be optimized away - if (_scale)//vertex positions are scaled already - { - if (_recenter) + osg::MatrixTransform *mt = new osg::MatrixTransform; + mt->setDataVariance(osg::Object::STATIC);//can be optimized away + if (_scale)//vertex positions are scaled already { - mt->setMatrix(osg::Matrix::translate(osg::Vec3d(h.GetOffsetX() + mid_x, h.GetOffsetY() + mid_y, h.GetOffsetZ() + mid_z))); + if (_recenter) + { + mt->setMatrix(osg::Matrix::translate(osg::Vec3d(h.offsetX() + mid_x, h.offsetY() + mid_y, h.offsetZ() + mid_z))); + } + else + { + mt->setMatrix(osg::Matrix::translate(osg::Vec3d(h.offsetX(), h.offsetY(), h.offsetZ()))); + } } else { - mt->setMatrix(osg::Matrix::translate(osg::Vec3d(h.GetOffsetX(), h.GetOffsetY(), h.GetOffsetZ()))); + if (_recenter) + { + mid_x *= h.scaleX(); + mid_y *= h.scaleY(); + mid_z *= h.scaleZ(); + mt->setMatrix(osg::Matrix::scale(osg::Vec3d(h.scaleX(), h.scaleY(), h.scaleZ())) * osg::Matrix::translate(osg::Vec3d(h.offsetX() + mid_x, h.offsetY() + mid_y, h.offsetZ() + mid_z))); + } + else + { + mt->setMatrix(osg::Matrix::scale(osg::Vec3d(h.scaleX(), h.scaleY(), h.scaleZ())) * osg::Matrix::translate(osg::Vec3d(h.offsetX(), h.offsetY(), h.offsetZ()))); + } } + + mt->addChild (geode); + + return mt; } - else + catch (pdal::pdal_error& err) { - if (_recenter) - { - mid_x *= h.GetScaleX(); - mid_y *= h.GetScaleY(); - mid_z *= h.GetScaleZ(); - mt->setMatrix(osg::Matrix::scale(osg::Vec3d(h.GetScaleX(), h.GetScaleY(), h.GetScaleZ())) * osg::Matrix::translate(osg::Vec3d(h.GetOffsetX() + mid_x, h.GetOffsetY() + mid_y, h.GetOffsetZ() + mid_z))); - } - else - { - mt->setMatrix(osg::Matrix::scale(osg::Vec3d(h.GetScaleX(), h.GetScaleY(), h.GetScaleZ())) * osg::Matrix::translate(osg::Vec3d(h.GetOffsetX(), h.GetOffsetY(), h.GetOffsetZ()))); - } + std::cout << err.what() << std::endl; } - - mt->addChild (geode); - - return mt; + return ReadResult::ERROR_IN_READING_FILE; } }; From c2b4b57d8780cab9dbc583f646dc4940e18dac11 Mon Sep 17 00:00:00 2001 From: Long Huan <8551701+longhuan2018@users.noreply.github.com> Date: Tue, 28 Sep 2021 11:37:41 +0800 Subject: [PATCH 2/2] Remove unused FindLIBLAS.cmake --- CMakeModules/FindLIBLAS.cmake | 108 ---------------------------------- 1 file changed, 108 deletions(-) delete mode 100644 CMakeModules/FindLIBLAS.cmake diff --git a/CMakeModules/FindLIBLAS.cmake b/CMakeModules/FindLIBLAS.cmake deleted file mode 100644 index 0ce247a751f..00000000000 --- a/CMakeModules/FindLIBLAS.cmake +++ /dev/null @@ -1,108 +0,0 @@ -#--- -# File: FindLIBLAS.cmake -# -# Find the native LIBLAS includes and library -# -# LIBLAS_INCLUDE_DIRS - where to find liblas's includes. -# LIBLAS_LIBRARIES - List of libraries when using liblas. -# LIBLAS_FOUND - True if liblas found. -#--- - - -# Set the include dir: -find_path(LIBLAS_INCLUDE_DIR liblas/liblas.hpp) - -# Macro for setting libraries: -macro(FIND_LIBLAS_LIBRARY MYLIBRARY MYLIBRARYNAME) - - find_library( - "${MYLIBRARY}_DEBUG" - NAMES "${MYLIBRARYNAME}${CMAKE_DEBUG_POSTFIX}" "lib${MYLIBRARYNAME}${CMAKE_DEBUG_POSTFIX}" - PATHS - ${LIBLAS_DIR}/lib/Debug - ${LIBLAS_DIR}/lib64/Debug - ${LIBLAS_DIR}/lib - ${LIBLAS_DIR}/lib64 - $ENV{LIBLAS_DIR}/lib/debug - $ENV{LIBLAS_DIR}/lib64/debug - NO_DEFAULT_PATH - ) - - find_library( - "${MYLIBRARY}_DEBUG" - NAMES "${MYLIBRARYNAME}${CMAKE_DEBUG_POSTFIX}" "lib${MYLIBRARYNAME}${CMAKE_DEBUG_POSTFIX}" - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local/lib - /usr/local/lib64 - /usr/lib - /usr/lib64 - /sw/lib - /opt/local/lib - /opt/csw/lib - /opt/lib - [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;LIBLAS_ROOT]/lib - /usr/freeware/lib64 - ) - - find_library( - ${MYLIBRARY} - NAMES "${MYLIBRARYNAME}${CMAKE_RELEASE_POSTFIX}" "lib${MYLIBRARYNAME}${CMAKE_RELEASE_POSTFIX}" - PATHS - ${LIBLAS_DIR}/lib/Release - ${LIBLAS_DIR}/lib64/Release - ${LIBLAS_DIR}/lib - ${LIBLAS_DIR}/lib64 - $ENV{LIBLAS_DIR}/lib/Release - $ENV{LIBLAS_DIR}/lib64/Release - $ENV{LIBLAS_DIR}/lib - $ENV{LIBLAS_DIR}/lib64 - $ENV{LIBLAS_DIR} - $ENV{LIBLASDIR}/lib - $ENV{LIBLASDIR}/lib64 - $ENV{LIBLASDIR} - $ENV{LIBLAS_ROOT}/lib - $ENV{LIBLAS_ROOT}/lib64 - NO_DEFAULT_PATH - ) - - find_library( - ${MYLIBRARY} - NAMES "${MYLIBRARYNAME}${CMAKE_RELEASE_POSTFIX}" "lib${MYLIBRARYNAME}${CMAKE_RELEASE_POSTFIX}" - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local/lib - /usr/local/lib64 - /usr/lib - /usr/lib64 - /sw/lib - /opt/local/lib - /opt/csw/lib - /opt/lib - [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;LIBLAS_ROOT]/lib - /usr/freeware/lib64 - ) - - if( NOT ${MYLIBRARY}_DEBUG ) - if( MYLIBRARY ) - set( ${MYLIBRARY}_DEBUG ${MYLIBRARY} ) - endif(MYLIBRARY) - endif( NOT ${MYLIBRARY}_DEBUG ) - -endmacro(FIND_LIBLAS_LIBRARY LIBRARY LIBRARYNAME) - -FIND_LIBLAS_LIBRARY(LIBLAS_LIBRARY las) - -set(LIBLAS_FOUND "NO") -if(LIBLAS_LIBRARY AND LIBLAS_INCLUDE_DIR) - FIND_PACKAGE(Boost) # used by LIBLAS - if(Boost_FOUND) - set(LIBLAS_LIBRARIES ${LIBLAS_LIBRARY} ) - set(LIBLAS_FOUND "YES") - if(WIN32) - link_directories(${Boost_LIBRARY_DIRS}) - endif() - endif() -endif()