diff --git a/.gitignore b/.gitignore index 336b803c79..4376786559 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # these are generated by cmake # pdal_defines.h +plugins/pgpointcloud/Pgtest-Support.hpp # # rst outputs diff --git a/CMakeLists.txt b/CMakeLists.txt index 4543daa906..101aa010a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,13 +89,28 @@ endif(WIN32) # Choose package components option(WITH_APPS "Choose if PDAL utilities should be built" TRUE) -option(WITH_GREYHOUND "Choose if Greyhound support should be built" FALSE) -option(WITH_PCL "Choose if PCL support should be built" FALSE) +option(BUILD_PLUGIN_GREYHOUND "Choose if Greyhound support should be built" FALSE) +option(BUILD_PLUGIN_HEXBIN "Whether or not HexBin filter is built" FALSE) +option(BUILD_PLUGIN_ICEBRIDGE "Choose if Icebridge support should be built" FALSE) +option(BUILD_PLUGIN_MRSID "Choose if MrSID/LiDAR support should be built" FALSE) +option(BUILD_PLUGIN_NITF "Choose if NITF support should be built (only install supported is from http://github.com/hobu/nitro)" FALSE) +option(BUILD_PLUGIN_OCI "Choose if OCI support should be built" TRUE) +option(BUILD_PLUGIN_P2G "Choose if Points2Grid support should be built" FALSE) +option(BUILD_PLUGIN_PCL "Choose if PCL support should be built" FALSE) +option(BUILD_PLUGIN_PGPOINTCLOUD "Choose if PostgreSQL PointCloud support should be built" TRUE) +option(BUILD_PLUGIN_SQLITE "Choose if SQLite database support should be built" FALSE) +option(BUILD_PLUGIN_RIVLIB "Choose if RiVLib support should be built" FALSE) option(WITH_TESTS "Choose if PDAL unit tests should be built" TRUE) # Choose to use pkg-config or not option(WITH_PKGCONFIG "Choose whether a pkgconfig file (PDAL.pc) should be installed" TRUE) +# Choose dependent options +cmake_dependent_option(BUILD_PGPOINTCLOUD_TESTS "Choose if PostgreSQL PointCloud tests should be built" ON BUILD_PLUGIN_PGPOINTCLOUD ON) +cmake_dependent_option(BUILD_SQLITE_TESTS "Choose if SQLite tests should be built" ON BUILD_PLUGIN_SQLITE ON) +cmake_dependent_option(BUILD_OCI_TESTS "Choose if OCI tests should be built" ON BUILD_PLUGIN_OCI ON) +cmake_dependent_option(BUILD_RIVLIB_TESTS "Choose if RiVLib tests should be built" ON BUILD_PLUGIN_RIVLIB ON) + #------------------------------------------------------------------------------ # test harness settings @@ -290,13 +305,13 @@ find_package(GEOS 3.3) if (GEOS_FOUND) find_file(GEOS_VERSION_H version.h "${GEOS_INCLUDE_DIR}/geos") if ("${GEOS_VERSION_H}" STREQUAL "GEOS_VERSION_H-NOTFOUND") - set(GEOS_LIBRARY "") + set(GEOS_LIBRARY "") set(GEOS_FOUND FALSE) set(WITH_GEOS FALSE) else() include_directories("${GEOS_INCLUDE_DIR}") set(PDAL_HAVE_GEOS 1) - message(STATUS "...building with GEOS") + message(STATUS "...building with GEOS") endif() else() set(GEOS_LIBRARY "") @@ -324,71 +339,6 @@ if(WITH_GEOTIFF) endif() -# -# SQLite (optional) -# -option(WITH_SQLITE "Choose if sqlite database support should be built" FALSE) -if (WITH_SQLITE) - find_package(SQLite3) - mark_as_advanced(CLEAR SQLITE3_INCLUDE_DIR) - mark_as_advanced(CLEAR SQLITE3_LIBRARY) - include_directories(${SQLITE3_INCLUDE_DIR}) - set(PDAL_HAVE_SQLITE 1) -endif() - - -# -# PGPointCloud (optional) -# -option(WITH_PGPOINTCLOUD "Choose if PostgreSQL PointCloud support should be built" TRUE) -cmake_dependent_option( - WITH_PGPOINTCLOUD_TESTS - "Choose if PostgreSQL PointCloud tests should be built" - OFF - WITH_PGPOINTCLOUD - OFF - ) -if (WITH_PGPOINTCLOUD) - find_package(PostgreSQL) - if (POSTGRESQL_FOUND) - set(PDAL_HAVE_POSTGRESQL 1) - mark_as_advanced(CLEAR POSTGRESQL_INCLUDE_DIR) - mark_as_advanced(CLEAR POSTGRESQL_LIBRARIES) - include_directories(${POSTGRESQL_INCLUDE_DIR}) - message(STATUS "..building with PgPointCloud") - else() - set(WITH_PGPOINTCLOUD FALSE) - set(POSTGRESQL_LIBRARIES "") - endif() -endif() - - -# -# Nitro (optional) -# -option(WITH_NITRO "Choose if Nitro support (only install supported is from http://github.com/hobu/nitro)" TRUE) -if(WITH_NITRO) - find_package(Nitro 2.6) - IF (NITRO_FOUND) - set(PDAL_HAVE_NITRO 1) - include_directories(${NITRO_INCLUDE_DIR}) - include_directories("${NITRO_INCLUDE_DIR}/nitro/c++") - include_directories("${NITRO_INCLUDE_DIR}/nitro/c") - add_definitions("-D_REENTRANT") - if (WIN32) - add_definitions("-DSIZEOF_SIZE_T=4") - add_definitions("-DIMPORT_NITRO_API") - else() - add_definitions("-D__POSIX") - endif() - message(STATUS "...building with Nitro") - else() - set(WITH_NITRO FALSE) - set(NITRO_LIBRARIES "") - endif() -endif() - - # # ICONV (optional) # @@ -406,23 +356,6 @@ if(WITH_ICONV) endif() -# -# Oracle support (optional) -# -option(WITH_ORACLE "Choose if Oracle support should be built" TRUE) -if(WITH_ORACLE) - find_package(Oracle) - if(ORACLE_FOUND) - include_directories(${ORACLE_INCLUDE_DIR}) - set(PDAL_HAVE_ORACLE 1) - message(STATUS "...building with Oracle") - else() - set(WITH_ORACLE FALSE) - set(ORACLE_LIBRARY "") - endif() -endif() - - # # LASZIP support (optional) # @@ -445,6 +378,16 @@ if(WITH_LASZIP) endif() endif() +option(WITH_COMPRESSION "Choose to use laz-perf compression for database drivers" FALSE) +if (WITH_COMPRESSION) + find_package(Lazperf) + if (LAZPERF_FOUND) + include_directories(${LAZPERF_INCLUDE_DIR}) + set(PDAL_HAVE_LAZPERF 1) + else() + set(WITH_COMPRESSION FALSE) + endif() +endif() # # ZLIB support - required @@ -459,25 +402,6 @@ if(ZLIB_FOUND) endif() -# -# MrSID/LiDAR support (optional) -# -option(WITH_MRSID "Choose if MrSID/LiDAR support should be built" FALSE) - -if(WITH_MRSID) - - set(MRSID_ROOT "/Users/hobu/installs/mrsid/Lidar_DSDK" CACHE STRING "Root directory of MrSID install") - - find_package(MrSID) - if(MRSID_FOUND) - set(CMAKE_REQUIRED_LIBRARIES "${MRSID_LIBRARY}") - include_directories(${MRSID_INCLUDE_DIR}) - add_definitions(-DHAVE_MRSID=1) - set(PDAL_HAVE_MRSID 1) - endif() -endif() - - # # CARIS/BDB support (optional) # @@ -488,55 +412,6 @@ if(WITH_CARIS) endif() -# -# Points2Grid (optional) -# -option(WITH_P2G "Choose if Points2Grid support should be built" FALSE) -if(WITH_P2G) - find_package(Points2Grid) - if(P2G_FOUND) - set(CMAKE_REQUIRED_LIBRARIES "${P2G_LIBRARY}") - include_directories(${P2G_INCLUDE_DIR}) - add_definitions(-DHAVE_P2G=1) - set(PDAL_HAVE_P2G 1) - endif() -endif() - - -# -# HDF5 - optional -# -option(WITH_HDF5 "Choose if HDF5 support should be built" FALSE) -if(WITH_HDF5) - set (HDF5_FIND_COMPONENTS "CXX") - find_package(HDF5 COMPONENTS CXX) - if(HDF5_FOUND) - include_directories(${HDF5_INCLUDE_DIR}) - add_definitions(-DHAVE_HDF5=1) - set(PDAL_HAVE_HDF5 1) - message(STATUS "Found HDF5") - else() - set(WITH_HDF5 FALSE) - set(PDAL_HAVE_HDF5 0) - message(STATUS "HDF5 not found") - endif() -endif() - - -# -# Hexer - optional -# -option(WITH_HEXER "Whether or not hexbin filter is built" FALSE) -if(WITH_HEXER) - find_package(Hexer) - if(HEXER_FOUND) - include_directories(${HEXER_INCLUDE_DIR}) - add_definitions(-DHAVE_HEXER=1) - set(PDAL_HAVE_HEXER 1) - endif() -endif() - - # # Python - optional # @@ -561,13 +436,13 @@ endif() # -# libxml2 (used iff ORACLE or PGPOINTCLOUD or SQLITE) +# libxml2 (used iff OCI or PGPOINTCLOUD or SQLITE) # option(WITH_LIBXML2 "Choose if libxml2 support should be built " FALSE) if (WITH_LIBXML2 OR - (WITH_ORACLE OR - WIT_PGPOINTCLOUD OR - WITH_SQLITE)) + (BUILD_PLUGIN_OCI OR + BUILD_PLUGIN_PGPOINTCLOUD OR + BUILD_PLUGIN_SQLITE)) set(WITH_LIBXML2 TRUE) else() set(WITH_LIBXML2 FALSE) @@ -587,21 +462,6 @@ if(WITH_LIBXML2) endif() -option(USE_PDAL_PLUGIN_TEXT "Build the text driver as a plugin rather than embedding" FALSE) -option(USE_PDAL_PLUGIN_SOCI "Build the soci driver as a plugin rather than embedding" FALSE) -option(USE_PDAL_PLUGIN_OCI "Build the oci driver as a plugin rather than embedding" FALSE) -option(USE_PDAL_PLUGIN_MRSID "Build the MrSID driver as a plugin rather than embedding" FALSE) -option(USE_PDAL_PLUGIN_CARIS "Build the Caris driver as a plugin rather than embedding" FALSE) -option(USE_PDAL_PLUGIN_NITRO "Build the NITF writer as a plugin rather than embedding" FALSE) - -if (USE_PDAL_PLUGIN_TEXT OR USE_PDAL_PLUGIN_SOCI OR USE_PDAL_PLUGIN_OCI OR - USE_PDAL_PLUGIN_MRSID OR USE_PDAL_PLUGIN_CARIS OR USE_PDAL_PLUGIN_NITRO) - if (PDAL_BUILD_STATIC) - message(SEND_ERROR "Cannot build separate plugins with statically compiled PDAL") - endif() -endif() - - #------------------------------------------------------------------------------ # installation commands #------------------------------------------------------------------------------ @@ -632,13 +492,6 @@ include_directories("${CMAKE_CURRENT_BINARY_DIR}/include") # subdirectory controls #------------------------------------------------------------------------------ -add_subdirectory(src) -add_subdirectory(plugins) - -if(WITH_APPS) - add_subdirectory(apps) -endif() - if(WITH_TESTS) message(STATUS "Building with PDAL unit tests") enable_testing() @@ -663,6 +516,14 @@ else() endif() +add_subdirectory(src) +add_subdirectory(plugins) + +if(WITH_APPS) + add_subdirectory(apps) +endif() + + #------------------------------------------------------------------------------ # CPACK controls diff --git a/cmake/examples/hobu-config.sh b/cmake/examples/hobu-config.sh index 6c76bcb5ec..953b9fab17 100755 --- a/cmake/examples/hobu-config.sh +++ b/cmake/examples/hobu-config.sh @@ -2,7 +2,7 @@ USR_LOCAL="/usr/local" USR="/usr" TIFF_HOME=$USR_LOCAL LASZIP_HOME=$USR_LOCAL -LIBXML2_HOME=$USR +LIBXML2_HOME=/usr/local/Cellar/libxml2/2.9.2/ GEOTIFF_HOME=$USR_LOCAL P2G_HOME=$USR_LOCAL HEXER_HOME="/usr/local" @@ -12,6 +12,7 @@ SO_EXT=dylib # CXX=/usr/local/bin/g++-4.8 ORACLE_HOME=$HOME/oracle +LAZPERF_HOME=$HOME/dev/git/laz-perf export ORACLE_HOME CONFIG="Unix Makefiles" #CONFIG="Ninja" @@ -23,16 +24,18 @@ fi CC=$CC CXX=$CXX cmake -G "$CONFIG" \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_INSTALL_PREFIX=/Users/hobu \ - -DWITH_ORACLE=ON \ + -DBUILD_PLUGIN_OCI=ON \ -DWITH_GEOTIFF=ON \ - -DWITH_SQLITE=ON \ - -DWITH_P2G=ON \ - -DWITH_HEXER=ON \ - -DWITH_NITRO=ON \ - -DWITH_MRSID=OFF \ - -DWITH_HDF5=ON \ - -DWITH_PCL=ON \ - -DWITH_PGPOINTCLOUD=ON \ + -DBUILD_PLUGIN_SQLITE=ON \ + -DBUILD_PLUGIN_PGPOINTCLOUD=ON \ + -DBUILD_OCI_TESTS=ON \ + -DBUILD_PLUGIN_HEXBIN=ON \ + -DBUILD_PLUGIN_NITF=ON \ + -DBUILD_PLUGIN_P2G=ON \ + -DBUILD_PLUGIN_MRSID=OFF \ + -DBUILD_PLUGIN_ICEBRIDGE=ON \ + -DBUILD_PLUGIN_PCL=ON \ + -DWITH_COMPRESSION=ON \ -DMRSID_INCLUDE_DIR=/Users/hobu/dev/release/mrsid/Lidar_DSDK/include \ -DMRSID_LIBRARY=/Users/hobu/dev/release/mrsid/Lidar_DSDK/lib/liblti_lidar_dsdk.dylib \ -DHEXER_INCLUDE_DIR=${HEXER_HOME}/include \ @@ -46,6 +49,7 @@ CC=$CC CXX=$CXX cmake -G "$CONFIG" \ -DLASZIP_LIBRARY=${LASZIP_HOME}/lib/liblaszip.${SO_EXT} \ -DLIBXML2_INCLUDE_DIR=${LIBXML2_HOME}/include/libxml2 \ -DLIBXML2_LIBRARIES=${LIBXML2_HOME}/lib/libxml2.${SO_EXT} \ + -DLAZPERF_INCLUDE_DIR=${LAZPERF_HOME}/ \ -DSQLITE3_INCLUDE_DIR=${SQLITE_HOME}/include \ -DSQLITE3_LIBRARY=${SQLITE_HOME}/lib/libsqlite3.${SO_EXT} diff --git a/cmake/modules/FindLazperf.cmake b/cmake/modules/FindLazperf.cmake new file mode 100644 index 0000000000..d391e2a4d5 --- /dev/null +++ b/cmake/modules/FindLazperf.cmake @@ -0,0 +1,29 @@ +# - Find lazperf +# Find the native LAZ-perf headers and libraries. +# +# LAZPERF_INCLUDE_DIRS - where to find encoder.hpp.hpp, etc. +# LAZPERF_LIBRARIES - List of libraries when using LAZPERF. +# LAZPERF_FOUND - True if LAZPERF found. + + +# Look for the header file. +FIND_PATH(LAZPERF_INCLUDE_DIR NAMES encoder.hpp ) + +# Look for the library. +#FIND_LIBRARY(LAZPERF_LIBRARY NAMES msgpack libmsgpack) + +# handle the QUIETLY and REQUIRED arguments and set LAZPERF_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LAZPERF DEFAULT_MSG LAZPERF_INCLUDE_DIR) + +# Copy the results to the output variables. +IF(LAZPERF_FOUND) + SET(LAZPERF_LIBRARIES ${LAZPERF_LIBRARY}) + SET(LAZPERF_INCLUDE_DIRS ${LAZPERF_INCLUDE_DIR}) +ELSE(LAZPERF_FOUND) + SET(LAZPERF_LIBRARIES) + SET(LAZPERF_INCLUDE_DIRS) +ENDIF(LAZPERF_FOUND) + +MARK_AS_ADVANCED(LAZPERF_INCLUDE_DIR LAZPERF_LIBRARY) diff --git a/cmake/pdal_targets.cmake b/cmake/pdal_targets.cmake index b151b3785a..5854ece4ed 100644 --- a/cmake/pdal_targets.cmake +++ b/cmake/pdal_targets.cmake @@ -91,20 +91,25 @@ endmacro(PDAL_ADD_EXECUTABLE) # # Todo: handle windows/unix variants of the plugin name # Todo: accept deps for target_link_libraries -macro(PDAL_ADD_PLUGIN _name _type _shortname _srcs _incs) - add_library(${_name} SHARED ${_srcs} ${_incs}) - target_link_libraries(${_name} ${PDAL_LINKAGE} ${PDAL_LIB_NAME}) +macro(PDAL_ADD_PLUGIN _name _type _shortname _srcs _incs _deps) + if(WIN32) + set(${_name} "libpdal_plugin_${_type}_${_shortname}") + else() + set(${_name} "pdal_plugin_${_type}_${_shortname}") + endif() + add_library(${${_name}} SHARED ${_srcs} ${_incs}) + target_link_libraries(${${_name}} ${PDAL_LINKAGE} ${PDAL_LIB_NAME} ${_deps}) source_group("Header Files\\${_type}\\${_shortname}" FILES ${_incs}) source_group("Source Files\\${_type}\\${_shortname}" FILES ${_srcs}) - install(TARGETS ${_name} + install(TARGETS ${${_name}} RUNTIME DESTINATION ${PDAL_BIN_DIR} LIBRARY DESTINATION ${PDAL_LIB_DIR} ARCHIVE DESTINATION ${PDAL_LIB_DIR}) endmacro(PDAL_ADD_PLUGIN) -macro(PDAL_ADD_TEST _name _srcs) +macro(PDAL_ADD_TEST _name _srcs _deps) include_directories(${PROJECT_SOURCE_DIR}/test/unit) include_directories(${PROJECT_BINARY_DIR}/test/unit) set(common_srcs @@ -114,7 +119,12 @@ macro(PDAL_ADD_TEST _name _srcs) ) add_executable(${_name} ${_srcs} ${common_srcs}) set_target_properties(${_name} PROPERTIES COMPILE_DEFINITIONS PDAL_DLL_IMPORT) - add_definitions("-DBOOST_TEST_DYN_LINK") + if(WIN32) + add_definitions("-DPDAL_DLL_EXPORT=1") + else() + add_definitions("-DBOOST_TEST_DYN_LINK") + endif() target_link_libraries(${_name} ${PDAL_LINKAGE} ${PDAL_LIB_NAME}) + target_link_libraries(${_name} ${PDAL_LINKAGE} ${_deps}) add_test(${_name} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_name}" "${PROJECT_SOURCE_DIR}/test/data" --catch_system_errors=no) endmacro(PDAL_ADD_TEST) diff --git a/doc/stages/drivers.rxp.reader.rst b/doc/stages/drivers.rxp.reader.rst new file mode 100644 index 0000000000..b553d391a5 --- /dev/null +++ b/doc/stages/drivers.rxp.reader.rst @@ -0,0 +1,127 @@ +.. _drivers.rxp.reader: + +drivers.rxp.reader +================== + +The **RXP reader** read from files in the RXP format, the in-house streaming format used by `RIEGL Laser Measurement Systems`_. + +.. warning:: + This software has not been developed by RIEGL, and RIEGL will not provide any support for this driver. + Please do not contact RIEGL with any questions or issues regarding this driver. + RIEGL is not responsible for damages or other issues that arise from use of this driver. + This driver has been tested against RiVLib version 1.39 on a Ubuntu 14.04 using gcc43. + + +Installation +------------ + +To build PDAL with rxp support, set RiVLib_DIR to the path of your local RiVLib installation. +RiVLib can be obtained from the `RIEGL download pages`_ with a properly enabled user account. +The RiVLib files do not need to be in a system-level directory, though they could be (e.g. they could be in ``/usr/local``, or just in your home directory somewhere). +For help building PDAL with optional libraries, see `the optional library documentation`_. + + +Example +------- + +This example rescales the points, given in the scanner's own coordinate system, to values that can be written to a las file. +Only points with a valid gps time, as determined by a pps pulse, are read from the rxp, since the ``sync_to_pps`` option is "true". + +.. code-block:: xml + + + + + + + + + + + + + + + + + + + + + + + + +A few things to note: + +- We use a ``filters.programmable`` to remap Reflectance values to Intensity values, scaling them so the entire range of Reflectance values fit into the Intensity field. + This is analogous to the "Export reflectance as intensity" option in RiSCAN Pro. + You could also explicitly set the minimum and maximum Reflectance values as you would in RiSCAN Pro using the same programmable filter. + You could also use "Amplitude" instead of "Reflectance". + If you do not need Intensity values in your output file, you can delete the programmable filter. +- We set the ``discard_high_return_numbers`` option to ``true`` on the las writer. + RXP files can contain more returns per shot than is supported by las, and so we need to explicitly tell the las writer to ignore those high return number points. + You could also use ``filters.predicate`` to filter those points earlier in the pipeline, or modify the return values with a ``filters.programmable``. + + +Options +------- + +filename + File to read from [Required if rdtp is not provided] + +rdtp + URI for a network-assessable scanner [Required if filename is not provided] + +sync_to_pps + If "true", ensure all incoming points have a valid pps timestamp, usually provided by some sort of GPS clock. + If "false", use the scanner's internal time. + Defaults to "true" + +minimal + If "true", only write X, Y, Z, and time values to the data stream. + If "false", write all available values as derived from the rxp file. + Use this feature to reduce the memory footprint of a PDAL run, if you don't need any values but the points themselves. + Defaults to "false". + +inclination_fix + *EXPERIMENTAL*: If "true", use inclination values in the rxp file to dynamically correct for inclination changes throughout the scan, using a moving average of 2 * ``inclination_fix_window`` inclination readings (see below). + This is an experimental feature that will remove some points from the data stream and modify many others. + Use with caution. + If "false", disable this feature. + Defaults to "false". + +inclination_fix_window + *EXPERIMENTAL*: Sets the half-size of the inclination fix window (see above). + Use of this feature should be considered highly experimental. + + +.. _RIEGL Laser Measurement Systems: http://www.riegl.com +.. _RIEGL download pages: http://www.riegl.com/members-area/software-downloads/libraries/ +.. _the optional library documentation: http://www.pdal.io/compilation/unix.html#configure-your-optional-libraries diff --git a/doc/stages/index.rst b/doc/stages/index.rst index 01d796f482..db0c2884ba 100644 --- a/doc/stages/index.rst +++ b/doc/stages/index.rst @@ -28,6 +28,7 @@ Readers & Writers drivers.pcd.reader drivers.pcd.writer drivers.qfit.reader + drivers.rxp.reader drivers.sbet.reader drivers.text.writer diff --git a/include/pdal/Charbuf.hpp b/include/pdal/Charbuf.hpp index 12de1ff310..d31443d570 100644 --- a/include/pdal/Charbuf.hpp +++ b/include/pdal/Charbuf.hpp @@ -34,6 +34,7 @@ #pragma once +#include #include #include @@ -41,7 +42,7 @@ namespace pdal { // Turns a vector into a streambuf. -class Charbuf : public std::streambuf +class PDAL_DLL Charbuf : public std::streambuf { public: Charbuf() : m_bufOffset(0) @@ -54,15 +55,15 @@ class Charbuf : public std::streambuf void initialize(char *buf, size_t count, pos_type bufOffset = 0); protected: - pos_type seekpos(pos_type pos, std::ios_base::openmode which = + std::ios::pos_type seekpos(std::ios::pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out); - pos_type seekoff(off_type off, std::ios_base::seekdir dir, + std::ios::pos_type seekoff(std::ios::off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out); private: // The offset allows one to use offsets when seeking that refer not to // the positions in the backing vector, but to some other reference point. - pos_type m_bufOffset; + std::ios::pos_type m_bufOffset; // For the put pointer, it seems we need the beginning of the buffer // in order to deal with offsets. char *m_buf; diff --git a/include/pdal/Compression.hpp b/include/pdal/Compression.hpp new file mode 100644 index 0000000000..a89ea817e5 --- /dev/null +++ b/include/pdal/Compression.hpp @@ -0,0 +1,378 @@ +/****************************************************************************** +* Copyright (c) 2014, Howard Butler (howard@hobu.co) +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following +* conditions are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided +* with the distribution. +* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the +* names of its contributors may be used to endorse or promote +* products derived from this software without specific prior +* written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +* OF SUCH DAMAGE. +****************************************************************************/ +#pragma once + + +#include + +#ifdef PDAL_HAVE_LAZPERF +#include +#include +#include + +#include +#include +#include +#include +#endif + +#include +#include +#include +#include + + + + +#include +#include + +namespace pdal +{ + + +namespace compression +{ + + +namespace CompressionType +{ + +enum Enum +{ + None = 0, + Ght = 1, + Dimensional = 2, + Lazperf = 3, + Unknown = 256 +}; + +} // namespace CompressionType + + +template inline void Compress(PointContextRef ctx, + const PointBuffer& buffer, + CompressionStream& output, + CompressionType::Enum ctype, + PointId start, + PointId end) +{ + +#ifdef PDAL_HAVE_LAZPERF + using namespace laszip; + using namespace laszip::formats; + + typedef encoders::arithmetic EncoderType; + + EncoderType encoder(output); + auto compressor = make_dynamic_compressor(encoder); + const Dimension::IdList& dims = ctx.dims(); +// std::cout << listDims(ctx) << std::endl; + for (auto di = dims.begin(); di != dims.end(); ++di) + { + Dimension::Type::Enum t = ctx.dimType(*di); + size_t s = ctx.dimSize(*di); + if (t == Dimension::Type::Signed32) + { + if (s == 4) + { + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Signed32 but size != 4!"); + } + else if (t == Dimension::Type::Signed16) + { + if (s == 2) + { + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Signed16 but size != 2 !"); + } + else if (t == Dimension::Type::Signed8) + { + if (s == 1) + { + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Signed8 but size != 1!"); + } + else if (t == Dimension::Type::Signed64) + { + if (s == 8) + { + compressor->template add_field(); + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Signed64 but size != 8!"); + } + else if (t == Dimension::Type::Unsigned32) + { + if (s == 4) + { + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Unsigned32 but size != 4!"); + } + else if (t == Dimension::Type::Unsigned16) + { + if (s == 2) + { + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Unsigned16 but size != 2!"); + } + else if (t == Dimension::Type::Unsigned8) + { + if (s == 1) + { + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Unsigned8 but size != 1!"); + } + else if (t == Dimension::Type::Unsigned64) + { + if (s == 8) + { + compressor->template add_field(); + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Unsigned64 but size != 8!"); + } + else if (t == Dimension::Type::Double) + { + if (s == 8) + { + compressor->template add_field(); + compressor->template add_field(); +// compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Double but size != 8!"); + } + else if (t == Dimension::Type::Float) + { + if (s == 4) + { + compressor->template add_field(); + } + else + throw pdal_error("Dimension is type Float but size != 4!"); + } + else + { + + std::ostringstream oss; + oss << "Unhandled compression for dimension of type '" << Dimension::interpretationName(t) << "' for dimension '" << Dimension::name(*di) << "'"; + throw pdal_error(oss.str()); + } + + } + + std::vector bytes = buffer.getBytes(); + size_t pointSize = ctx.pointSize(); + uint8_t* pos = &(bytes.front())+ (pointSize * start); + if (end == 0) // Set to max + end = buffer.size(); + uint8_t* end_pos = &(bytes.front())+ (pointSize * end); + while (pos != end_pos) + { + compressor->compress((const char*)pos); + pos += pointSize; + } + + encoder.done(); +#endif +} + + + +template inline PointBufferPtr Decompress(PointContextRef ctx, + CompressionStream& strm, + size_t howMany, + CompressionType::Enum ctype) +{ + std::vector output; +#ifdef PDAL_HAVE_LAZPERF + using namespace laszip; + using namespace laszip::formats; + + typedef decoders::arithmetic DecoderType; + + + DecoderType decoder(strm); + auto decompressor = make_dynamic_decompressor(decoder); + const Dimension::IdList& dims = ctx.dims(); + +// std::cout << listDims(ctx) << std::endl; + for (auto di = dims.begin(); di != dims.end(); ++di) + { + Dimension::Type::Enum t = ctx.dimType(*di); + size_t s = ctx.dimSize(*di); + if (t == Dimension::Type::Signed32) + { + if (s == 4) + { + decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Signed32 but size != 4!"); + } + else if (t == Dimension::Type::Signed16) + { + if (s == 2) + { + decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Signed16 but size != 2 !"); + } + else if (t == Dimension::Type::Signed8) + { + if (s == 1) + { + decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Signed8 but size != 1!"); + } + else if (t == Dimension::Type::Signed64) + { + if (s == 8) + { + decompressor->template add_field(); + decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Signed64 but size != 8!"); + } + else if (t == Dimension::Type::Unsigned32) + { + if (s == 4) + { + decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Unsigned32 but size != 4!"); + } + else if (t == Dimension::Type::Unsigned16) + { + if (s == 2) + { + decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Unsigned16 but size != 2!"); + } + else if (t == Dimension::Type::Unsigned8) + { + if (s == 1) + { + decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Unsigned8 but size != 1!"); + } + else if (t == Dimension::Type::Unsigned64) + { + if (s == 8) + { + decompressor->template add_field(); + decompressor->template add_field(); + } + + else + throw pdal_error("Dimension is type Unsigned64 but size != 8!"); + } + else if (t == Dimension::Type::Double) + { + if (s == 8) + { + decompressor->template add_field(); + decompressor->template add_field(); +// decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Double but size != 8!"); + } + else if (t == Dimension::Type::Float) + { + if (s == 4) + { + decompressor->template add_field(); + } + else + throw pdal_error("Dimension is type Float but size != 4!"); + } + else + { + + std::ostringstream oss; + oss << "Unhandled compression for dimension of type '" << Dimension::interpretationName(t) << "' for dimension '" << Dimension::name(*di) << "'"; + throw pdal_error(oss.str()); + } + + } + + + output.resize(howMany * ctx.pointSize()); + uint8_t* pos = &(output[0]); + size_t point_size = ctx.pointSize(); + + uint8_t* end_pos = pos + (point_size * howMany); + while (pos != end_pos) + { + decompressor->decompress((char*)pos); + pos+=point_size; + } + +#endif + PointBufferPtr b = PointBufferPtr(new PointBuffer(output, ctx)); + + return b; + + +} + +} // compression +} // namespace pdal + + diff --git a/include/pdal/Dimension.hpp b/include/pdal/Dimension.hpp index b0866c59dd..b82ad1d4b0 100644 --- a/include/pdal/Dimension.hpp +++ b/include/pdal/Dimension.hpp @@ -156,6 +156,8 @@ enum Enum Y, Z, Intensity, + Amplitude, + Reflectance, ReturnNumber, NumberOfReturns, ScanDirectionFlag, @@ -168,6 +170,7 @@ enum Enum Green, Blue, GpsTime, + InternalTime, OffsetTime, IsPpsLocked, StartPulse, @@ -176,7 +179,9 @@ enum Enum Pitch, Roll, PulseWidth, + Deviation, PassiveSignal, + BackgroundRadiation, PassiveX, PassiveY, PassiveZ, @@ -194,6 +199,7 @@ enum Enum Flag, Mark, Alpha, + EchoRange, ScanChannel, Infrared }; @@ -218,6 +224,16 @@ inline std::string description(Id::Enum id) return "Z coordinate"; case Id::Intensity: return "Representation of the pulse return magnitude"; + case Id::Amplitude: + return "This is the ratio of the received power to the " + "power received at the detection limit expressed in dB"; + case Id::Reflectance: + return "This is the ratio of the received power to the " + "power that would be received from a white diffuse target " + "at the same distance expressed in dB. The reflectance " + "represents a range independent property of the target. " + "The surface normal of this target is assumed to be in " + "parallel to the laser beam direction."; case Id::ReturnNumber: return "Pulse return number for a given output pulse. A given output " "laser pulse can have many returns, and they must be marked in " @@ -249,6 +265,8 @@ inline std::string description(Id::Enum id) "indicates that the point originated in the current file"; case Id::GpsTime: return "GPS time that the point was acquired"; + case Id::InternalTime: + return "Scanner's internal time when the point was aquired, in seconds"; case Id::OffsetTime: return "Milliseconds from first acquired point"; case Id::IsPpsLocked: @@ -274,8 +292,12 @@ inline std::string description(Id::Enum id) return "GPS PDOP (dilution of precision)"; case Id::PulseWidth: return "Laser received pulse width (digitizer samples)"; + case Id::Deviation: + return "A larger value for deviation indicates larger distortion."; case Id::PassiveSignal: return "Relative passive signal"; + case Id::BackgroundRadiation: + return "A measure of background radiation."; case Id::PassiveX: return "Passive X footprint"; case Id::PassiveY: @@ -308,6 +330,8 @@ inline std::string description(Id::Enum id) return "Mark"; case Id::Flag: return "Flag"; + case Id::EchoRange: + return "The distance from the laser origin to the target."; case Id::ScanChannel: return "Scan Channel"; case Id::Infrared: @@ -334,6 +358,10 @@ inline Id::Enum id(std::string s) return Id::Z; else if (s == "INTENSITY") return Id::Intensity; + else if (s == "AMPLITUDE") + return Id::Amplitude; + else if (s == "REFLECTANCE") + return Id::Reflectance; else if (s == "RETURNNUMBER") return Id::ReturnNumber; else if (s == "NUMBEROFRETURNS") @@ -360,6 +388,8 @@ inline Id::Enum id(std::string s) return Id::Alpha; else if (s == "GPSTIME") return Id::GpsTime; + else if (s == "INTERNALTIME") + return Id::InternalTime; else if (s == "TIME" || s == "OFFSETTIME") return Id::OffsetTime; else if (s == "ISPPSLOCKED") @@ -376,8 +406,12 @@ inline Id::Enum id(std::string s) return Id::Pdop; else if (s == "PULSEWIDTH") return Id::PulseWidth; + else if (s == "DEVIATION") + return Id::Deviation; else if (s == "PASSIVESIGNAL") return Id::PassiveSignal; + else if (s == "BACKGROUNDRADIATION") + return Id::BackgroundRadiation; else if (s == "PASSIVEX") return Id::PassiveX; else if (s == "PASSIVEY") @@ -410,6 +444,8 @@ inline Id::Enum id(std::string s) return Id::Mark; else if (s == "FLAG") return Id::Flag; + else if (s == "ECHORANGE") + return Id::EchoRange; else if (s == "SCANCHANNEL") return Id::ScanChannel; else if (s == "INFRARED" || s == "NEARINFRARED") @@ -432,6 +468,10 @@ inline std::string name(Id::Enum id) return "Z"; case Id::Intensity: return "Intensity"; + case Id::Amplitude: + return "Amplitude"; + case Id::Reflectance: + return "Reflectance"; case Id::ReturnNumber: return "ReturnNumber"; case Id::NumberOfReturns: @@ -458,6 +498,8 @@ inline std::string name(Id::Enum id) return "Alpha"; case Id::GpsTime: return "GpsTime"; + case Id::InternalTime: + return "InternalTime"; case Id::OffsetTime: return "OffsetTime"; case Id::IsPpsLocked: @@ -474,8 +516,12 @@ inline std::string name(Id::Enum id) return "Pdop"; case Id::PulseWidth: return "PulseWidth"; + case Id::Deviation: + return "Deviation"; case Id::PassiveSignal: return "PassiveSignal"; + case Id::BackgroundRadiation: + return "BackgroundRadiation"; case Id::PassiveX: return "PassiveX"; case Id::PassiveY: @@ -508,6 +554,8 @@ inline std::string name(Id::Enum id) return "Mark"; case Id::Flag: return "Flag"; + case Id::EchoRange: + return "EchoRange"; case Id::ScanChannel: return "ScanChannel"; case Id::Infrared: @@ -537,6 +585,10 @@ inline Type::Enum defaultType(Id::Enum id) return Double; case Id::Intensity: return Unsigned16; + case Id::Amplitude: + return Float; + case Id::Reflectance: + return Float; case Id::ReturnNumber: return Unsigned8; case Id::NumberOfReturns: @@ -555,6 +607,8 @@ inline Type::Enum defaultType(Id::Enum id) return Unsigned16; case Id::GpsTime: return Double; + case Id::InternalTime: + return Double; case Id::OffsetTime: return Unsigned32; case Id::IsPpsLocked: @@ -579,8 +633,12 @@ inline Type::Enum defaultType(Id::Enum id) return Float; case Id::PulseWidth: return Float; + case Id::Deviation: + return Float; case Id::PassiveSignal: return Signed32; + case Id::BackgroundRadiation: + return Float; case Id::PassiveX: return Double; case Id::PassiveY: @@ -613,6 +671,8 @@ inline Type::Enum defaultType(Id::Enum id) return Unsigned8; case Id::Flag: return Unsigned8; + case Id::EchoRange: + return Double; case Id::ScanChannel: return Unsigned8; case Id::Infrared: diff --git a/include/pdal/Drivers.hpp b/include/pdal/Drivers.hpp index 9ece4bee90..6d114a6c6b 100644 --- a/include/pdal/Drivers.hpp +++ b/include/pdal/Drivers.hpp @@ -32,8 +32,7 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#ifndef INCLUDED_PDAL_DRIVERS_HPP -#define INCLUDED_PDAL_DRIVERS_HPP +#pragma once #include @@ -47,68 +46,10 @@ #include -#ifdef PDAL_HAVE_HDF5 -#include -#endif - -#ifdef PDAL_HAVE_ORACLE -#ifndef USE_PDAL_PLUGIN_OCI -#include -#endif -#endif - #ifdef PDAL_HAVE_CARIS -#ifndef USE_PDAL_PLUGIN_CARIS #include #endif -#endif - -#ifdef PDAL_HAVE_MRSID -#ifndef USE_PDAL_PLUGIN_MRSID -#include -#endif -#endif #include #include #include - -#ifdef PDAL_HAVE_ORACLE -#ifndef USE_PDAL_PLUGIN_OCI -#include -#endif -#endif - -#ifdef PDAL_HAVE_NITRO -#ifndef USE_PDAL_PLUGIN_NITF -#include -#endif -#endif - -#ifdef PDAL_HAVE_NITRO -#include -#endif - -#ifdef PDAL_HAVE_P2G -#include -#endif - -#ifdef PDAL_HAVE_HDF5 -#include -#endif - -#ifdef PDAL_HAVE_SQLITE -#ifndef USE_PDAL_PLUGIN_SQLITE -#include -#include -#endif -#endif - -#ifdef PDAL_HAVE_POSTGRESQL -#ifndef USE_PDAL_PLUGIN_PGPOINTCLOUD -#include -#include -#endif -#endif - -#endif diff --git a/include/pdal/Filters.hpp b/include/pdal/Filters.hpp index bc604db02e..fb9adb916c 100644 --- a/include/pdal/Filters.hpp +++ b/include/pdal/Filters.hpp @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #ifdef PDAL_HAVE_PYTHON diff --git a/include/pdal/Metadata.hpp b/include/pdal/Metadata.hpp index 9553ec10c5..7a2d72ce7f 100644 --- a/include/pdal/Metadata.hpp +++ b/include/pdal/Metadata.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,8 @@ namespace { auto ischar = [](char c) { - return c == ';' || c == ':' || c == ' ' || c == '\'' || c == '\"' || c == '[' || c ==']'; + return c == ';' || c == ':' || c == ' ' || c == '\'' || + c == '\"' || c == '[' || c ==']'; }; std::string v; @@ -206,7 +208,6 @@ class MetadataNodeImpl return MetadataType::Instance; } - std::string toJSON() const; void toJSON(std::ostream& o, int level) const; void subnodesToJSON(std::ostream& o, int level) const; @@ -450,8 +451,41 @@ class PDAL_DLL MetadataNode } std::string name() const { return m_impl->m_name; } + + template + T value() const + { + T t; + + if (m_impl->m_type == "base64Binary") + { + std::vector encVal = + Utils::base64_decode(m_impl->m_value); + encVal.resize(sizeof(T)); + memcpy(&t, encVal.data(), sizeof(T)); + } + else + { + try + { + t = boost::lexical_cast(m_impl->m_value); + } + catch (boost::bad_lexical_cast&) + { + // Static to get default initialization. + static T t2; + std::cerr << "Error converting metadata [" << name() << + "] = " << m_impl->m_value << " to type " << + Utils::typeidName() << " -- return default initialized."; + t = t2; + } + } + return t; + } + std::string value() const { return m_impl->m_value; } + std::string description() const { return m_impl->m_descrip; } std::vector children() const diff --git a/include/pdal/PointBuffer.hpp b/include/pdal/PointBuffer.hpp index 749b7bdb55..d651dbc7dc 100644 --- a/include/pdal/PointBuffer.hpp +++ b/include/pdal/PointBuffer.hpp @@ -220,6 +220,65 @@ class PDAL_DLL PointBuffer Dimension::IdList dims() const { return m_context.dims(); } + std::ostream& getBytes(std::ostream& strm, PointId start, PointId end) const + { + char buf[sizeof(double)]; + for (PointId i = start; i < end; ++i) + { + for (const auto& dim : m_context.m_dims->m_used) + { + getFieldInternal(dim, i, buf); + strm.write(buf, m_context.dimSize(dim)); + } + } + return strm; + } + std::vector getBytes() const + { + return getBytes(0, size()); + } + + std::vector getBytes(PointId start, PointId end) const + { + std::vector output; + + size_t byteCount = PointBuffer::size() * m_context.pointSize(); + output.reserve(byteCount); + output.resize(byteCount); + + if (end == 0) end = PointBuffer::size(); + + uint8_t* pos = &(output.front()); + for (PointId i = start; i < end; ++i) + { + for (const auto& dim : m_context.m_dims->m_used) + { + getFieldInternal(dim, i, pos); + pos += m_context.dimSize(dim); + } + } + return output; + } + + PointBuffer(const std::vector& bytes, PointContextRef ctx) : m_context(ctx) + { + + size_t pointCount = bytes.size() / ctx.pointSize(); + if (bytes.size() % ctx.pointSize()) + throw pdal_error("byte count is not a multiple of point size!"); + +// assert(ctx.m_dims->m_used.size() == ctx.m_dims->m_detail.size()); + const uint8_t* pos = &(bytes[0]); + for (PointId i = 0; i < pointCount; ++i) + { + for (const auto& dim : ctx.m_dims->m_used) + { + setFieldInternal(dim, i, pos); + pos += m_context.dimSize(dim); + } + } + } + protected: PointContextRef m_context; std::vector m_index; diff --git a/include/pdal/PointContext.hpp b/include/pdal/PointContext.hpp index 69f1b3e361..bd8bbfcdd0 100644 --- a/include/pdal/PointContext.hpp +++ b/include/pdal/PointContext.hpp @@ -206,6 +206,14 @@ class PointContext size_t dimSize(Dimension::Id::Enum id) const { return dimDetail(id)->size(); } + size_t pointSize() const + { + size_t size(0); + for (auto d: m_dims->m_detail) + size += d.size(); + return size; + } + private: Dimension::Detail *dimDetail(Dimension::Id::Enum id) const { return &(m_dims->m_detail[(size_t)id]); } diff --git a/include/pdal/XMLSchema.hpp b/include/pdal/XMLSchema.hpp index 6ee9c7a7d9..8225cdb2be 100644 --- a/include/pdal/XMLSchema.hpp +++ b/include/pdal/XMLSchema.hpp @@ -196,13 +196,16 @@ class PDAL_DLL Reader XMLSchema schema() const { return m_schema; } + MetadataNode getMetadata() const + { return m_metadata;} + protected: void Initialize(); void Load(); private: #ifdef PDAL_HAVE_LIBXML2 - pdal::Metadata LoadMetadata(xmlNode* node); + pdal::MetadataNode LoadMetadata(xmlNode* node, pdal::MetadataNode& input); std::string remapOldNames(std::string const& input); DocPtr m_doc; @@ -220,6 +223,7 @@ class PDAL_DLL Reader std::string m_xsd; uint32_t m_field_position; XMLSchema m_schema; + MetadataNode m_metadata; Reader& operator=(const Reader&); // not implemented Reader(const Reader&); // not implemented; @@ -230,7 +234,7 @@ class PDAL_DLL Writer { public: Writer(const Dimension::IdList& ids, - const std::vector& types, + const std::vector& types, Orientation::Enum orientation= Orientation::PointMajor) : m_dims(ids), m_types(types), m_orientation(orientation) {} diff --git a/include/pdal/drivers/bpf/BpfReader.hpp b/include/pdal/drivers/bpf/BpfReader.hpp index c9e31cb692..3cd4aca1c4 100644 --- a/include/pdal/drivers/bpf/BpfReader.hpp +++ b/include/pdal/drivers/bpf/BpfReader.hpp @@ -85,6 +85,7 @@ class PDAL_DLL BpfReader : public Reader bool readUlemData(); bool readUlemFiles(); + bool readHeaderExtraData(); bool readPolarData(); point_count_t readPointMajor(PointBuffer& data, point_count_t count); point_count_t readDimMajor(PointBuffer& data, point_count_t count); diff --git a/include/pdal/drivers/las/VariableLengthRecord.hpp b/include/pdal/drivers/las/VariableLengthRecord.hpp index 7787e5b86f..27c51dfb17 100644 --- a/include/pdal/drivers/las/VariableLengthRecord.hpp +++ b/include/pdal/drivers/las/VariableLengthRecord.hpp @@ -89,6 +89,8 @@ class PDAL_DLL VariableLengthRecord const char* data() const { return (const char *)m_data.data(); } + char* data() + { return (char *)m_data.data(); } uint64_t dataLen() const { return m_data.size(); } void setDataLen(uint64_t size) diff --git a/include/pdal/drivers/las/Writer.hpp b/include/pdal/drivers/las/Writer.hpp index 4a4334298c..5acc93b50e 100644 --- a/include/pdal/drivers/las/Writer.hpp +++ b/include/pdal/drivers/las/Writer.hpp @@ -41,12 +41,14 @@ namespace pdal { +class LasTester; + namespace drivers { namespace nitf { - class Writer; + class NitfWriter; } namespace las @@ -65,7 +67,8 @@ struct VlrOptionInfo class PDAL_DLL Writer : public pdal::Writer { - friend class nitf::Writer; + friend class pdal::LasTester; + friend class nitf::NitfWriter; public: SET_STAGE_NAME("drivers.las.writer", "Las Writer") SET_STAGE_LINK("http://pdal.io/stages/drivers.las.writer.html") @@ -122,6 +125,42 @@ class PDAL_DLL Writer : public pdal::Writer Writer(const Writer&); // not implemented }; +// Find the approriate value for the specified header field. +/// \param name - Name of header field. +/// \return Value of header field. +template +T Writer::headerVal(const std::string& name) +{ + // The header values either come from options, or are overriden in + // the metadata for options which had the value FORWARD. For those, + // grab the value from metadata if it exists, or use the default value, + // which was stuck on following the FORWARD value when processing options. + auto pred = [name](MetadataNode n) + { + return n.name() == name; + }; + + std::string val = m_headerVals[name]; + if (val.find("FORWARD") == 0) + { + MetadataNode m = m_metadata.findChild(pred); + if (m.valid()) + return m.value(); + val = val.substr(strlen("FORWARD")); + } + try + { + return boost::lexical_cast(val); + } + catch (boost::bad_lexical_cast ex) + { + std::stringstream out; + out << "Couldn't convert option \"" << name << "\" with value \"" << + val << "\" from string as necessary."; + throw pdal_error(out.str()); + } +} + } // namespace las } // namespace drivers } // namespace pdal diff --git a/include/pdal/drivers/text/Writer.hpp b/include/pdal/drivers/text/Writer.hpp index beec474ef1..e32aaff326 100644 --- a/include/pdal/drivers/text/Writer.hpp +++ b/include/pdal/drivers/text/Writer.hpp @@ -48,14 +48,6 @@ namespace drivers namespace text { -#ifdef USE_PDAL_PLUGIN_TEXT -PDAL_C_START - -PDAL_DLL void PDALRegister_writer_text(void* factory); - -PDAL_C_END -#endif - typedef std::shared_ptr FileStreamPtr; class PDAL_DLL Writer : public pdal::Writer diff --git a/include/pdal/pdal_macros.hpp b/include/pdal/pdal_macros.hpp index 97f9d7f164..ecdddcbafb 100644 --- a/include/pdal/pdal_macros.hpp +++ b/include/pdal/pdal_macros.hpp @@ -40,10 +40,7 @@ // #define MAKE_READER_CREATOR(T, FullT) \ pdal::Reader* create_##T() \ - { \ - return new FullT(); \ - } - + { pdal::Reader *r = new FullT(); return r; } #define MAKE_FILTER_CREATOR(T, FullT) \ pdal::Filter* create_##T() \ { pdal::Filter *f = new FullT(); return f; } @@ -52,7 +49,7 @@ { pdal::Writer *w = new FullT(); return w; } #define MAKE_KERNEL_CREATOR(T, FullT) \ pdal::Kernel* create_##T() \ - { pdal::Kernel *a = new FullT(); return a; } + { pdal::Kernel *k = new FullT(); return k; } // // macros to register the stage creators @@ -70,6 +67,9 @@ registerKernelDriverInfo(); \ registerKernel(FullT::s_getName(), create_##T) +// +// macros to create the various plugins types +// #define CREATE_READER_PLUGIN(T, FullT) \ MAKE_READER_CREATOR(T, FullT) \ PDAL_C_START PDAL_DLL void PDALRegister_reader_##T(void* factory) \ @@ -79,8 +79,7 @@ f.registerReader(FullT::s_getName(), create_##T); \ } \ PDAL_C_END \ - SET_PLUGIN_VERSION(T) - + SET_READER_PLUGIN_VERSION(T) #define CREATE_FILTER_PLUGIN(T, FullT) \ MAKE_FILTER_CREATOR(T, FullT) \ PDAL_C_START PDAL_DLL void PDALRegister_filter_##T(void* factory) \ @@ -90,8 +89,7 @@ f.registerFilter(FullT::s_getName(), create_##T); \ } \ PDAL_C_END \ - SET_PLUGIN_VERSION(T) - + SET_FILTER_PLUGIN_VERSION(T) #define CREATE_WRITER_PLUGIN(T, FullT) \ MAKE_WRITER_CREATOR(T, FullT) \ PDAL_C_START PDAL_DLL void PDALRegister_writer_##T(void* factory) \ @@ -101,8 +99,7 @@ f.registerWriter(FullT::s_getName(), create_##T); \ } \ PDAL_C_END \ - SET_PLUGIN_VERSION(T) - + SET_WRITER_PLUGIN_VERSION(T) #define CREATE_KERNEL_PLUGIN(T, FullT) \ MAKE_KERNEL_CREATOR(T, FullT) \ PDAL_C_START PDAL_DLL void PDALRegister_kernel_##T(void* factory) \ @@ -112,15 +109,27 @@ f.registerKernel(FullT::s_getName(), create_##T); \ } \ PDAL_C_END \ - SET_PLUGIN_VERSION(T) + SET_KERNEL_PLUGIN_VERSION(T) -#define SET_PLUGIN_VERSION(DriverName) \ - PDAL_C_START PDAL_DLL int PDALRegister_version_##DriverName() \ - { \ - return PDAL_PLUGIN_VERSION; \ - } \ +// +// macro to register the version of PDAL the plugin was linked against +// +#define SET_READER_PLUGIN_VERSION(T) \ + PDAL_C_START PDAL_DLL int PDALRegister_version_reader_##T() \ + { return PDAL_PLUGIN_VERSION; } \ + PDAL_C_END +#define SET_FILTER_PLUGIN_VERSION(T) \ + PDAL_C_START PDAL_DLL int PDALRegister_version_filter_##T() \ + { return PDAL_PLUGIN_VERSION; } \ + PDAL_C_END +#define SET_WRITER_PLUGIN_VERSION(T) \ + PDAL_C_START PDAL_DLL int PDALRegister_version_writer_##T() \ + { return PDAL_PLUGIN_VERSION; } \ + PDAL_C_END +#define SET_KERNEL_PLUGIN_VERSION(T) \ + PDAL_C_START PDAL_DLL int PDALRegister_version_kernel_##T() \ + { return PDAL_PLUGIN_VERSION; } \ PDAL_C_END - #ifdef _WIN32 inline long lround(double d) diff --git a/pdal_defines.h.in b/pdal_defines.h.in index 38c0a8e12c..01d7b34a97 100644 --- a/pdal_defines.h.in +++ b/pdal_defines.h.in @@ -31,6 +31,7 @@ #cmakedefine PDAL_HAVE_HDF5 #cmakedefine PDAL_HAVE_HEXER #cmakedefine PDAL_HAVE_LASZIP +#cmakedefine PDAL_HAVE_LAZPERF #cmakedefine PDAL_HAVE_LIBXML2 #cmakedefine PDAL_HAVE_LIBGEOTIFF #cmakedefine PDAL_HAVE_MRSID @@ -41,7 +42,6 @@ #cmakedefine PDAL_HAVE_SQLITE #cmakedefine PDAL_HAVE_POSTGRESQL - /* * plugins */ diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 1e78054264..83828ec28d 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -1,7 +1,43 @@ -if(WITH_GREYHOUND) +if(BUILD_PLUGIN_GREYHOUND) add_subdirectory(greyhound) endif() -if(WITH_PCL) +if(BUILD_PLUGIN_HEXBIN) + add_subdirectory(hexbin) +endif() + +if(BUILD_PLUGIN_ICEBRIDGE) + add_subdirectory(icebridge) +endif() + +if(BUILD_PLUGIN_MRSID) + add_subdirectory(mrsid) +endif() + +if(BUILD_PLUGIN_NITF) + add_subdirectory(nitf) +endif() + +if(BUILD_PLUGIN_OCI) + add_subdirectory(oci) +endif() + +if(BUILD_PLUGIN_P2G) + add_subdirectory(p2g) +endif() + +if(BUILD_PLUGIN_PCL) add_subdirectory(pcl) endif() + +if(BUILD_PLUGIN_PGPOINTCLOUD) + add_subdirectory(pgpointcloud) +endif() + +if(BUILD_PLUGIN_SQLITE) + add_subdirectory(sqlite) +endif() + +if(BUILD_PLUGIN_RIVLIB) + add_subdirectory(rxp) +endif(BUILD_PLUGIN_RIVLIB) diff --git a/plugins/greyhound/CMakeLists.txt b/plugins/greyhound/CMakeLists.txt index d47b43486d..37dd11f192 100644 --- a/plugins/greyhound/CMakeLists.txt +++ b/plugins/greyhound/CMakeLists.txt @@ -3,38 +3,38 @@ # include_directories(${PROJECT_SOURCE_DIR}/include) -include_directories(${PROJECT_SOURCE_DIR}/plugin/greyhound) - -# attempt to find Greyhound required dependencies -find_package(JSONCPP REQUIRED) -find_package(WEBSOCKETPP REQUIRED) - -# JSONCPP and WEBSOCKETPP were both found -message(STATUS "Building with Greyhound support") - -# add JSONCPP stuff -include_directories(${JSONCPP_INCLUDE_DIR}) -add_definitions(-DHAVE_JSONCPP=1) - -# add WEBSOCKETPP stuff -include_directories(${WEBSOCKETPP_INCLUDE_DIR}) -add_definitions(-D_WEBSOCKETPP_NULLPTR_TOKEN_=0) -add_definitions(-DHAVE_WEBSOCKETPP=1) - -# -# Greyhound Reader -# -set(srcs - drivers/GreyhoundReader.cpp - drivers/WebSocketClient.cpp -) - -set(incs - drivers/Exchanges.hpp - drivers/GreyhoundReader.hpp - drivers/WebSocketClient.hpp -) - -set(GREYHOUND_LIB_NAME pdal_plugin_reader_greyhound) -PDAL_ADD_PLUGIN(${GREYHOUND_LIB_NAME} reader greyhound ${srcs} ${incs}) -target_link_libraries(${GREYHOUND_LIB_NAME} ${PDAL_LINKAGE} ${JSONCPP_LIBRARY}) +include_directories(${PROJECT_SOURCE_DIR}/plugins/greyhound) + +find_package(JSONCPP) +find_package(WEBSOCKETPP) +if(JSONCPP_FOUND AND WEBSOCKETPP_FOUND) + message(STATUS "Building with Greyhound support") + + # add JSONCPP stuff + include_directories(${JSONCPP_INCLUDE_DIR}) + add_definitions(-DHAVE_JSONCPP=1) + + # add WEBSOCKETPP stuff + include_directories(${WEBSOCKETPP_INCLUDE_DIR}) + add_definitions(-D_WEBSOCKETPP_NULLPTR_TOKEN_=0) + add_definitions(-DHAVE_WEBSOCKETPP=1) + + # + # Greyhound Reader + # + set(srcs + drivers/GreyhoundReader.cpp + drivers/WebSocketClient.cpp + ) + + set(incs + drivers/Exchanges.hpp + drivers/GreyhoundReader.hpp + drivers/WebSocketClient.hpp + ) + + set(deps ${JSONCPP_LIBRARY}) + PDAL_ADD_PLUGIN(greyhound_reader_lib_name reader greyhound "${srcs}" "${incs}" "${deps}") +else() + message(STATUS "Building without Greyhound support") +endif() diff --git a/plugins/greyhound/drivers/GreyhoundReader.hpp b/plugins/greyhound/drivers/GreyhoundReader.hpp index dc350c51b3..4977c79c7c 100644 --- a/plugins/greyhound/drivers/GreyhoundReader.hpp +++ b/plugins/greyhound/drivers/GreyhoundReader.hpp @@ -39,12 +39,6 @@ #include "WebSocketClient.hpp" -PDAL_C_START - -PDAL_DLL void PDALRegister_reader_greyhound(void* factory); - -PDAL_C_END - namespace pdal { namespace drivers diff --git a/plugins/hexbin/CMakeLists.txt b/plugins/hexbin/CMakeLists.txt new file mode 100644 index 0000000000..a48be35c2b --- /dev/null +++ b/plugins/hexbin/CMakeLists.txt @@ -0,0 +1,39 @@ +# +# HexBin plugin CMake configuration +# + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugins/hexbin) + +find_package(Hexer) +if (HEXER_FOUND) + message(STATUS "Building with Hexer support") + + include_directories(${HEXER_INCLUDE_DIR}) + add_definitions(-DHAVE_HEXER=1) + + # + # HexBin filter + # + set(srcs + filters/HexBin.cpp + ) + + set(incs + filters/HexBin.hpp + ) + + set(deps ${HEXER_LIBRARY}) + PDAL_ADD_PLUGIN(hexbin_filter_lib_name filter hexbin "${srcs}" "${incs}" "${deps}") + + # + # HexBin tests + # + set(srcs + test/HexbinFilterTest.cpp + ) + + PDAL_ADD_TEST(hexbintest "${srcs}" ${hexbin_filter_lib_name}) +else() + message(STATUS "Building without Hexer support") +endif() diff --git a/src/filters/HexBin.cpp b/plugins/hexbin/filters/HexBin.cpp similarity index 96% rename from src/filters/HexBin.cpp rename to plugins/hexbin/filters/HexBin.cpp index 31202c81d1..5bf17af0ec 100644 --- a/src/filters/HexBin.cpp +++ b/plugins/hexbin/filters/HexBin.cpp @@ -32,13 +32,14 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include +#include "HexBin.hpp" -#ifdef PDAL_HAVE_HEXER #include +#include using namespace hexer; -#endif + +CREATE_FILTER_PLUGIN(hexbin, pdal::filters::HexBin) namespace pdal { @@ -60,7 +61,6 @@ void HexBin::processOptions(const Options& options) void HexBin::ready(PointContext ctx) { -#ifdef PDAL_HAVE_HEXER if (m_edgeLength == 0.0) // 0 can always be represented exactly. { m_grid.reset(new HexGrid(m_density)); @@ -68,26 +68,22 @@ void HexBin::ready(PointContext ctx) } else m_grid.reset(new HexGrid(m_edgeLength * sqrt(3), m_density)); -#endif } void HexBin::filter(PointBuffer& buf) { -#ifdef PDAL_HAVE_HEXER for (PointId idx = 0; idx < buf.size(); ++idx) { double x = buf.getFieldAs(pdal::Dimension::Id::X, idx); double y = buf.getFieldAs(pdal::Dimension::Id::Y, idx); m_grid->addPoint(x, y); } -#endif } void HexBin::done(PointContext ctx) { -#ifdef PDAL_HAVE_HEXER m_grid->processSample(); m_grid->findShapes(); m_grid->findParentPaths(); @@ -137,7 +133,6 @@ void HexBin::done(PointContext ctx) m_grid->toWKT(polygon); m_metadata.add("boundary", polygon.str(), "Boundary MULTIPOLYGON of domain"); -#endif } } // namespace filters diff --git a/include/pdal/filters/HexBin.hpp b/plugins/hexbin/filters/HexBin.hpp similarity index 95% rename from include/pdal/filters/HexBin.hpp rename to plugins/hexbin/filters/HexBin.hpp index 3f7a7aa1e4..354510e0be 100644 --- a/include/pdal/filters/HexBin.hpp +++ b/plugins/hexbin/filters/HexBin.hpp @@ -36,11 +36,9 @@ #include -#ifdef PDAL_HAVE_HEXER #include #include #include -#endif namespace pdal { @@ -52,20 +50,14 @@ class PDAL_DLL HexBin : public Filter public: SET_STAGE_NAME("filters.hexbin", "Hexbin implementation") SET_STAGE_LINK("http://pdal.io/stages/filters.hexbin.html") -#ifdef PDAL_HAVE_HEXER SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif HexBin() : Filter() {} private: -#ifdef PDAL_HAVE_HEXER std::unique_ptr m_grid; -#endif std::string m_xDimName; std::string m_yDimName; uint32_t m_sampleSize; diff --git a/test/unit/filters/HexbinFilterTest.cpp b/plugins/hexbin/test/HexbinFilterTest.cpp similarity index 80% rename from test/unit/filters/HexbinFilterTest.cpp rename to plugins/hexbin/test/HexbinFilterTest.cpp index 761a8c1caf..e3550d58bb 100644 --- a/test/unit/filters/HexbinFilterTest.cpp +++ b/plugins/hexbin/test/HexbinFilterTest.cpp @@ -35,16 +35,14 @@ #include "UnitTest.hpp" #include +#include #include -#include #include #include "Support.hpp" BOOST_AUTO_TEST_SUITE(HexbinFilterTest) -#ifdef PDAL_HAVE_HEXER - using namespace pdal; void printChildren(std::ostream& out, MetadataNode m, int depth = 0) @@ -75,29 +73,34 @@ BOOST_AUTO_TEST_CASE(HexbinFilterTest_test_1) drivers::las::Reader reader; reader.setOptions(options); - filters::HexBin hexbin; - hexbin.setOptions(options); - hexbin.setInput(&reader); + StageFactory f; + StageFactory::FilterCreator* fc = f.getFilterCreator("filters.hexbin"); + if(fc) + { + BOOST_CHECK(fc); - PointContext ctx; + std::unique_ptr hexbin(fc()); + hexbin->setOptions(options); + hexbin->setInput(&reader); - hexbin.prepare(ctx); - hexbin.execute(ctx); + PointContext ctx; - MetadataNode m = ctx.metadata(); - m = m.findChild(hexbin.getName()); + hexbin->prepare(ctx); + hexbin->execute(ctx); - std::string filename = Support::temppath("hexbin.txt"); - std::ofstream out(filename); - printChildren(out, m); - out.close(); + MetadataNode m = ctx.metadata(); + m = m.findChild(hexbin->getName()); - BOOST_CHECK(Support::compare_text_files(filename, - Support::datapath("filters/hexbin.txt"))); + std::string filename = Support::temppath("hexbin.txt"); + std::ofstream out(filename); + printChildren(out, m); + out.close(); - FileUtils::deleteFile(filename); -} + BOOST_CHECK(Support::compare_text_files(filename, + Support::datapath("filters/hexbin.txt"))); -#endif + FileUtils::deleteFile(filename); + } +} BOOST_AUTO_TEST_SUITE_END() diff --git a/plugins/icebridge/CMakeLists.txt b/plugins/icebridge/CMakeLists.txt new file mode 100644 index 0000000000..df5bf35f92 --- /dev/null +++ b/plugins/icebridge/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# Icebridge plugin CMake configuration +# + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugins/icebridge) + +set (HDF5_FIND_COMPONENTS "CXX") +find_package(HDF5 COMPONENTS CXX REQUIRED) +if (HDF5_FOUND) + message(STATUS "Building with Icebridge support") + + include_directories(${HDF5_INCLUDE_DIR}) + add_definitions(-DHAVE_HDF5=1) + + # + # Icebridge Reader + # + set(srcs + drivers/IcebridgeReader.cpp + drivers/Hdf5Handler.cpp + ) + + set(incs + drivers/IcebridgeReader.hpp + drivers/Hdf5Handler.hpp + ) + + set(deps ${HDF5_LIBRARIES}) + PDAL_ADD_PLUGIN(icebridge_reader_lib_name reader icebridge "${srcs}" "${incs}" "${deps}") + + # + # Icebridge tests + # + set(srcs + test/IcebridgeReaderTest.cpp + ) + + PDAL_ADD_TEST(icetest "${srcs}" ${icebridge_reader_lib_name}) +else() + message(STATUS "Building without Icebridge support") +endif() diff --git a/src/Hdf5Handler.cpp b/plugins/icebridge/drivers/Hdf5Handler.cpp similarity index 99% rename from src/Hdf5Handler.cpp rename to plugins/icebridge/drivers/Hdf5Handler.cpp index 36a52fcb70..9ddb5a5f28 100644 --- a/src/Hdf5Handler.cpp +++ b/plugins/icebridge/drivers/Hdf5Handler.cpp @@ -32,7 +32,7 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include +#include "Hdf5Handler.hpp" #include #include diff --git a/include/pdal/Hdf5Handler.hpp b/plugins/icebridge/drivers/Hdf5Handler.hpp similarity index 100% rename from include/pdal/Hdf5Handler.hpp rename to plugins/icebridge/drivers/Hdf5Handler.hpp diff --git a/src/drivers/icebridge/Reader.cpp b/plugins/icebridge/drivers/IcebridgeReader.cpp similarity index 92% rename from src/drivers/icebridge/Reader.cpp rename to plugins/icebridge/drivers/IcebridgeReader.cpp index c33f9bb663..ca2cdfe019 100644 --- a/src/drivers/icebridge/Reader.cpp +++ b/plugins/icebridge/drivers/IcebridgeReader.cpp @@ -32,12 +32,14 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include +#include "IcebridgeReader.hpp" #include #include #include +CREATE_READER_PLUGIN(icebridge, pdal::drivers::icebridge::IcebridgeReader) + namespace { const std::vector hdf5Columns = @@ -64,7 +66,7 @@ namespace drivers namespace icebridge { -Options Reader::getDefaultOptions() +Options IcebridgeReader::getDefaultOptions() { Options options; options.add("filename", "", "file to read from"); @@ -72,7 +74,7 @@ Options Reader::getDefaultOptions() } -Dimension::IdList Reader::getDefaultDimensions() +Dimension::IdList IcebridgeReader::getDefaultDimensions() { Dimension::IdList ids; @@ -94,20 +96,20 @@ Dimension::IdList Reader::getDefaultDimensions() } -void Reader::addDimensions(PointContextRef ctx) +void IcebridgeReader::addDimensions(PointContextRef ctx) { return ctx.registerDims(getDefaultDimensions()); } -void Reader::ready(PointContextRef ctx) +void IcebridgeReader::ready(PointContextRef ctx) { m_hdf5Handler.initialize(m_filename, hdf5Columns); m_index = 0; } -point_count_t Reader::read(PointBuffer& buf, point_count_t count) +point_count_t IcebridgeReader::read(PointBuffer& buf, point_count_t count) { //All data we read for icebridge is currently 4 bytes wide, so // just allocate once and forget it. @@ -172,13 +174,13 @@ point_count_t Reader::read(PointBuffer& buf, point_count_t count) } -void Reader::done(PointContextRef ctx) +void IcebridgeReader::done(PointContextRef ctx) { m_hdf5Handler.close(); } -bool Reader::eof() +bool IcebridgeReader::eof() { return m_index >= m_hdf5Handler.getNumPoints(); } diff --git a/include/pdal/drivers/icebridge/Reader.hpp b/plugins/icebridge/drivers/IcebridgeReader.hpp similarity index 89% rename from include/pdal/drivers/icebridge/Reader.hpp rename to plugins/icebridge/drivers/IcebridgeReader.hpp index 6528469d1a..ffa325b7be 100644 --- a/include/pdal/drivers/icebridge/Reader.hpp +++ b/plugins/icebridge/drivers/IcebridgeReader.hpp @@ -36,7 +36,9 @@ #include #include -#include +#include + +#include "Hdf5Handler.hpp" #include @@ -54,14 +56,14 @@ class icebridge_error : public pdal_error { } }; -class PDAL_DLL Reader : public pdal::Reader +class PDAL_DLL IcebridgeReader : public pdal::Reader { public: SET_STAGE_NAME("drivers.icebridge.reader", "Icebridge Reader") SET_STAGE_LINK("http://pdal.io/stages/drivers.icebridge.reader.html") SET_STAGE_ENABLED(true) - Reader() : pdal::Reader() + IcebridgeReader() : pdal::Reader() {} static Options getDefaultOptions(); @@ -77,8 +79,8 @@ class PDAL_DLL Reader : public pdal::Reader virtual void done(PointContextRef ctx); virtual bool eof(); - Reader& operator=(const Reader&); // Not implemented. - Reader(const Reader&); // Not implemented. + IcebridgeReader& operator=(const IcebridgeReader&); // Not implemented. + IcebridgeReader(const IcebridgeReader&); // Not implemented. }; } // namespace icebridge diff --git a/test/unit/drivers/icebridge/IcebridgeReaderTest.cpp b/plugins/icebridge/test/IcebridgeReaderTest.cpp similarity index 68% rename from test/unit/drivers/icebridge/IcebridgeReaderTest.cpp rename to plugins/icebridge/test/IcebridgeReaderTest.cpp index a2db5c4a18..b292912893 100644 --- a/test/unit/drivers/icebridge/IcebridgeReaderTest.cpp +++ b/plugins/icebridge/test/IcebridgeReaderTest.cpp @@ -38,8 +38,7 @@ #include #include #include - -#include +#include #include "StageTester.hpp" #include "Support.hpp" @@ -94,49 +93,56 @@ BOOST_AUTO_TEST_SUITE(IcebridgeReaderTest) BOOST_AUTO_TEST_CASE(testRead) { - Option filename("filename", getFilePath(), ""); - Options options(filename); - drivers::icebridge::Reader reader; - reader.setOptions(options); - - PointContext ctx; - reader.prepare(ctx); - PointBufferSet pbSet = reader.execute(ctx); - BOOST_CHECK_EQUAL(pbSet.size(), 1); - PointBufferPtr buf = *pbSet.begin(); - BOOST_CHECK_EQUAL(buf->size(), 2); - - checkPoint( - *buf, - 0, - 141437548, // time - 82.605319, // latitude - 301.406196, // longitude - 18.678, // elevation - 2408, // xmtSig - 181, // rcvSig - 49.91, // azimuth - -4.376, // pitch - 0.608, // roll - 2.9, // gpsPdop - 20.0, // pulseWidth - 0.0); // relTime - - checkPoint( - *buf, - 1, - 141437548, // time - 82.605287, // latitude - 301.404862, // longitude - 18.688, // elevation - 2642, // xmtSig - 173, // rcvSig - 52.006, // azimuth - -4.376, // pitch - 0.609, // roll - 2.9, // gpsPdop - 17.0, // pulseWidth - 0.0); // relTime + StageFactory f; + StageFactory::ReaderCreator* rc = f.getReaderCreator("drivers.icebridge.reader"); + if (rc) + { + BOOST_CHECK(rc); + + Option filename("filename", getFilePath(), ""); + Options options(filename); + std::unique_ptr reader(rc()); + reader->setOptions(options); + + PointContext ctx; + reader->prepare(ctx); + PointBufferSet pbSet = reader->execute(ctx); + BOOST_CHECK_EQUAL(pbSet.size(), 1); + PointBufferPtr buf = *pbSet.begin(); + BOOST_CHECK_EQUAL(buf->size(), 2); + + checkPoint( + *buf, + 0, + 141437548, // time + 82.605319, // latitude + 301.406196, // longitude + 18.678, // elevation + 2408, // xmtSig + 181, // rcvSig + 49.91, // azimuth + -4.376, // pitch + 0.608, // roll + 2.9, // gpsPdop + 20.0, // pulseWidth + 0.0); // relTime + + checkPoint( + *buf, + 1, + 141437548, // time + 82.605287, // latitude + 301.404862, // longitude + 18.688, // elevation + 2642, // xmtSig + 173, // rcvSig + 52.006, // azimuth + -4.376, // pitch + 0.609, // roll + 2.9, // gpsPdop + 17.0, // pulseWidth + 0.0); // relTime + } } BOOST_AUTO_TEST_CASE(testPipeline) diff --git a/plugins/mrsid/CMakeLists.txt b/plugins/mrsid/CMakeLists.txt new file mode 100644 index 0000000000..8601b0e6d1 --- /dev/null +++ b/plugins/mrsid/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# MrSID plugin CMake configuration +# + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugins/mrsid) + +set(MRSID_ROOT "/Users/hobu/installs/mrsid/Lidar_DSDK" CACHE STRING "Root directory of MrSID install") +find_package(MrSID) +if(MRSID_FOUND) + message(STATUS "Building with MrSID support") + + include_directories(${MRSID_INCLUDE_DIR}) + add_definitions(-DHAVE_MRSID=1) + + # + # MrSID Reader + # + set(srcs + drivers/MrsidReader.cpp + ) + + set(incs + drivers/MrsidReader.hpp + ) + + set(deps ${MRSID_LIBRARY}) + PDAL_ADD_PLUGIN(mrsid_reader_lib_name reader mrsid "${srcs}" "${incs}" "${deps}") +else() + message(STATUS "Building without MrSID support") +endif() diff --git a/src/drivers/mrsid/Reader.cpp b/plugins/mrsid/drivers/MrsidReader.cpp similarity index 93% rename from src/drivers/mrsid/Reader.cpp rename to plugins/mrsid/drivers/MrsidReader.cpp index c7b2bdba77..03b394f480 100644 --- a/src/drivers/mrsid/Reader.cpp +++ b/plugins/mrsid/drivers/MrsidReader.cpp @@ -32,13 +32,15 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include +#include "MrsidReader.hpp" #include #include +CREATE_READER_PLUGIN(mrsid, pdal::drivers::mrsid::MrsidReader) + namespace pdal { namespace drivers @@ -47,28 +49,21 @@ namespace mrsid { -Reader::Reader(const Options& options) - : pdal::Reader(options) -{ - return; -} - - -Reader::Reader(LizardTech::PointSource *ps) - : pdal::Reader(Options::none()) +MrsidReader::MrsidReader(LizardTech::PointSource *ps) + : pdal::Reader() , m_PS(ps), m_iter(NULL) { m_PS->retain(); return; } -Reader::~Reader() +MrsidReader::~MrsidReader() { m_iter->release(); m_PS->release(); } -Dimension Reader::LTChannelToPDalDimension(const LizardTech::ChannelInfo & channel, pdal::Schema const& dimensions) const +Dimension MrsidReader::LTChannelToPDalDimension(const LizardTech::ChannelInfo & channel, pdal::Schema const& dimensions) const { std::string name = channel.getName(); @@ -89,7 +84,7 @@ Dimension Reader::LTChannelToPDalDimension(const LizardTech::ChannelInfo & chann } -void Reader::initialize() +void MrsidReader::initialize() { const LizardTech::PointInfo& pointinfo = m_PS->getPointInfo(); @@ -111,18 +106,18 @@ void Reader::initialize() } -Options Reader::getDefaultOptions() +Options MrsidReader::getDefaultOptions() { Options options; return options; } -pdal::StageSequentialIterator* Reader::createSequentialIterator(PointBuffer& buffer) const +pdal::StageSequentialIterator* MrsidReader::createSequentialIterator(PointBuffer& buffer) const { - return new pdal::drivers::mrsid::iterators::sequential::Reader(*this, buffer, getNumPoints()); + return new pdal::drivers::mrsid::iterators::sequential::MrsidReader(*this, buffer, getNumPoints()); } -int Reader::SchemaToPointInfo(const Schema &schema, LizardTech::PointInfo &pointInfo) const +int MrsidReader::SchemaToPointInfo(const Schema &schema, LizardTech::PointInfo &pointInfo) const { schema::index_by_index const& dims = schema.getDimensions().get(); @@ -176,7 +171,7 @@ int Reader::SchemaToPointInfo(const Schema &schema, LizardTech::PointInfo &point } -boost::uint32_t Reader::processBuffer(PointBuffer& data, boost::uint64_t index) const +boost::uint32_t MrsidReader::processBuffer(PointBuffer& data, boost::uint64_t index) const { const Schema& schema = data.getSchema(); @@ -313,7 +308,7 @@ boost::uint32_t Reader::processBuffer(PointBuffer& data, boost::uint64_t index) return cnt; } -std::vector Reader::getDefaultDimensions() +std::vector MrsidReader::getDefaultDimensions() { std::vector output; @@ -408,7 +403,7 @@ namespace sequential { -Reader::Reader(const pdal::drivers::mrsid::Reader& reader, PointBuffer& buffer, boost::uint32_t numPoints) +MrsidReader::MrsidReader(const pdal::drivers::mrsid::MrsidReader& reader, PointBuffer& buffer, boost::uint32_t numPoints) : pdal::ReaderSequentialIterator(buffer) , m_numPoints(numPoints) , m_reader(reader) @@ -417,13 +412,13 @@ Reader::Reader(const pdal::drivers::mrsid::Reader& reader, PointBuffer& buffer, } -boost::uint64_t Reader::skipImpl(boost::uint64_t count) +boost::uint64_t MrsidReader::skipImpl(boost::uint64_t count) { return count; } -bool Reader::atEndImpl() const +bool MrsidReader::atEndImpl() const { // const boost::uint64_t numPoints = getStage().getNumPoints(); const boost::uint64_t currPoint = getIndex(); @@ -431,7 +426,7 @@ bool Reader::atEndImpl() const } -boost::uint32_t Reader::readBufferImpl(PointBuffer& data) +boost::uint32_t MrsidReader::readBufferImpl(PointBuffer& data) { return m_reader.processBuffer(data, getIndex()); } diff --git a/include/pdal/drivers/mrsid/Reader.hpp b/plugins/mrsid/drivers/MrsidReader.hpp similarity index 82% rename from include/pdal/drivers/mrsid/Reader.hpp rename to plugins/mrsid/drivers/MrsidReader.hpp index ff5261cafc..58fdb2a09b 100644 --- a/include/pdal/drivers/mrsid/Reader.hpp +++ b/plugins/mrsid/drivers/MrsidReader.hpp @@ -32,8 +32,7 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#ifndef INCLUDED_DRIVERS_MrSID_READER_HPP -#define INCLUDED_DRIVERS_MrSID_READER_HPP +#pragma once #include #include @@ -61,21 +60,17 @@ namespace mrsid // The MrSIDReader wraps LT's PointSource abstraction // -class PDAL_DLL Reader : public pdal::Reader +class PDAL_DLL MrsidReader : public pdal::Reader { public: SET_STAGE_NAME("drivers.mrsid.reader", "MrSID Reader") SET_STAGE_LINK("http://www.pdal.io/stages/drivers.mrsid.reader.html") -#ifdef PDAL_HAVE_MRSID SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif - virtual ~Reader(); - Reader(); - Reader(LizardTech::PointSource *ps); + virtual ~MrsidReader(); + MrsidReader() : Writer() {}; + MrsidReader(LizardTech::PointSource *ps); static Options getDefaultOptions(); static std::vector getDefaultDimensions(); @@ -92,8 +87,8 @@ class PDAL_DLL Reader : public pdal::Reader virtual void initialize(); int SchemaToPointInfo(const Schema &schema, LizardTech::PointInfo &pointInfo) const; Dimension LTChannelToPDalDimension(const LizardTech::ChannelInfo & channel, pdal::Schema const& dimensions) const; - Reader& operator=(const Reader&); // not implemented - Reader(const Reader&); // not implemented + MrsidReader& operator=(const MrsidReader&); // not implemented + MrsidReader(const MrsidReader&); // not implemented }; namespace iterators @@ -102,10 +97,10 @@ namespace iterators namespace sequential { -class Reader : public pdal::ReaderSequentialIterator +class MrsidReader : public pdal::ReaderSequentialIterator { public: - Reader(const pdal::drivers::mrsid::Reader& reader, PointBuffer& buffer, boost::uint32_t numPoints); + MrsidReader(const pdal::drivers::mrsid::MrsidReader& reader, PointBuffer& buffer, boost::uint32_t numPoints); private: boost::uint64_t skipImpl(boost::uint64_t); @@ -113,7 +108,7 @@ class Reader : public pdal::ReaderSequentialIterator bool atEndImpl() const; boost::uint32_t m_numPoints; - const pdal::drivers::mrsid::Reader& m_reader; + const pdal::drivers::mrsid::MrsidReader& m_reader; }; } // sequential @@ -121,17 +116,17 @@ class Reader : public pdal::ReaderSequentialIterator namespace random { -class Reader : public pdal::ReaderRandomIterator +class MrsidReader : public pdal::ReaderRandomIterator { public: - Reader(const pdal::drivers::mrsid::Reader& reader, + MrsidReader(const pdal::drivers::mrsid::MrsidReader& reader, PointBuffer& buffer, boost::uint32_t numPoints); private: boost::uint64_t seekImpl(boost::uint64_t); boost::uint32_t readBufferImpl(PointBuffer&); - const pdal::drivers::mrsid::Reader& m_reader; + const pdal::drivers::mrsid::MrsidReader& m_reader; boost::uint32_t m_numPoints; }; @@ -144,6 +139,3 @@ class Reader : public pdal::ReaderRandomIterator } } } // namespaces - - -#endif diff --git a/plugins/nitf/CMakeLists.txt b/plugins/nitf/CMakeLists.txt new file mode 100644 index 0000000000..975197e4fe --- /dev/null +++ b/plugins/nitf/CMakeLists.txt @@ -0,0 +1,104 @@ +# +# NITF plugin CMake configuration +# + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugins/nitf) + +find_package(Nitro 2.6 REQUIRED) +if(NITRO_FOUND) + message(STATUS "Building with NITF support") + + include_directories(${NITRO_INCLUDE_DIR}) + include_directories("${NITRO_INCLUDE_DIR}/nitro/c++") + include_directories("${NITRO_INCLUDE_DIR}/nitro/c") + add_definitions("-D_REENTRANT") + if (WIN32) + add_definitions("-DSIZEOF_SIZE_T=4") + add_definitions("-DIMPORT_NITRO_API") + else() + add_definitions("-D__POSIX") + endif() + + set(PDAL_LAS_PATH drivers/las) + set(PDAL_LAS_HEADERS "${PROJECT_SOURCE_DIR}/include/pdal/${PDAL_LAS_PATH}") + set(PDAL_LAS_SRC "${PROJECT_SOURCE_DIR}/src/${PDAL_LAS_PATH}") + + if ((GEOTIFF_FOUND) AND (GDAL_FOUND)) + set(PDAL_GTIFF_SRCS "${PDAL_LAS_SRC}/GeotiffSupport.cpp") + set(PDAL_GTIFF_INCS "${PDAL_LAS_SRC}/GeotiffSupport.hpp") + endif() + + if (LASZIP_FOUND) + set(PDAL_LASZIP_SRCS "${PDAL_LAS_SRC}/ZipPoint.cpp") + set(PDAL_LASZIP_INCS "${PDAL_LAS_HEADERS}/ZipPoint.hpp") + endif() + + set(PDAL_LAS_SRCS + ${PDAL_GTIFF_SRCS} + ${PDAL_LASZIP_SRCS} + "${PDAL_LAS_SRC}/Header.cpp" + "${PDAL_LAS_SRC}/Reader.cpp" + "${PDAL_LAS_SRC}/SummaryData.cpp" + "${PDAL_LAS_SRC}/VariableLengthRecord.cpp" + "${PDAL_LAS_SRC}/Writer.cpp" + ) + + set(PDAL_LAS_INCS + ${PDAL_GTIFF_INCS} + ${PDAL_LASZIP_INCS} + "${PDAL_LAS_HEADERS}/Header.hpp" + "${PDAL_LAS_HEADERS}/Reader.hpp" + "${PDAL_LAS_HEADERS}/SummaryData.hpp" + "${PDAL_LAS_HEADERS}/VariableLengthRecord.hpp" + "${PDAL_LAS_HEADERS}/Writer.hpp" + ) + + # + # NITF Reader + # + set(srcs + ${PDAL_LAS_SRCS} + drivers/NitfFile.cpp + drivers/MetadataReader.cpp + drivers/tre_plugins.cpp + drivers/NitfReader.cpp + ) + + set(incs + ${PDAL_LAS_INCS} + drivers/NitfFile.hpp + drivers/MetadataReader.hpp + drivers/tre_plugins.hpp + drivers/NitfReader.hpp + ) + + set(deps ${NITRO_LIBRARIES}) + PDAL_ADD_PLUGIN(nitf_reader_lib_name reader nitf "${srcs}" "${incs}" "${deps}") + + # + # NITF Writer + # + set(srcs + ${PDAL_LAS_SRCS} + drivers/NitfWriter.cpp + drivers/tre_plugins.cpp + ) + + set(incs + ${PDAL_LAS_INCS} + drivers/NitfWriter.hpp + drivers/tre_plugins.hpp + ) + + set(deps ${NITRO_LIBRARIES}) + PDAL_ADD_PLUGIN(nitf_writer_lib_name writer nitf "${srcs}" "${incs}" "${deps}") + + set(srcs + test/NitfReaderTest.cpp + test/NitfWriterTest.cpp + ) + + set(deps ${nitf_reader_lib_name} ${nitf_writer_lib_name}) + PDAL_ADD_TEST(nitftest "${srcs}" "${deps}") +endif() diff --git a/src/drivers/nitf/MetadataReader.cpp b/plugins/nitf/drivers/MetadataReader.cpp similarity index 99% rename from src/drivers/nitf/MetadataReader.cpp rename to plugins/nitf/drivers/MetadataReader.cpp index 700aff3f9f..06d2cc2faf 100644 --- a/src/drivers/nitf/MetadataReader.cpp +++ b/plugins/nitf/drivers/MetadataReader.cpp @@ -34,8 +34,6 @@ #include "MetadataReader.hpp" -#ifdef PDAL_HAVE_NITRO - #include #include @@ -423,5 +421,3 @@ void MetadataReader::doComments(const std::string& key, } } } // namespaces - -#endif // PDAL_HAVE_NITRO diff --git a/src/drivers/nitf/MetadataReader.hpp b/plugins/nitf/drivers/MetadataReader.hpp similarity index 98% rename from src/drivers/nitf/MetadataReader.hpp rename to plugins/nitf/drivers/MetadataReader.hpp index c868d73720..79ccc511af 100644 --- a/src/drivers/nitf/MetadataReader.hpp +++ b/plugins/nitf/drivers/MetadataReader.hpp @@ -36,8 +36,6 @@ #include -#ifdef PDAL_HAVE_NITRO - #include #ifdef PDAL_COMPILER_GCC @@ -133,5 +131,3 @@ class PDAL_DLL MetadataReader } } } // namespaces - -#endif // HAVE_NITRO diff --git a/src/drivers/nitf/NitfFile.cpp b/plugins/nitf/drivers/NitfFile.cpp similarity index 99% rename from src/drivers/nitf/NitfFile.cpp rename to plugins/nitf/drivers/NitfFile.cpp index c5f5cb135c..e6363dabbe 100644 --- a/src/drivers/nitf/NitfFile.cpp +++ b/plugins/nitf/drivers/NitfFile.cpp @@ -34,8 +34,6 @@ #include "NitfFile.hpp" -#ifdef PDAL_HAVE_NITRO - #include #include @@ -268,5 +266,3 @@ bool NitfFile::locateLidarDataSegment() } } } // namespaces - -#endif // PDAL_HAVE_NITRO diff --git a/src/drivers/nitf/NitfFile.hpp b/plugins/nitf/drivers/NitfFile.hpp similarity index 98% rename from src/drivers/nitf/NitfFile.hpp rename to plugins/nitf/drivers/NitfFile.hpp index f6182490b2..6d298a158c 100644 --- a/src/drivers/nitf/NitfFile.hpp +++ b/plugins/nitf/drivers/NitfFile.hpp @@ -36,8 +36,6 @@ #include -#ifdef PDAL_HAVE_NITRO - #include #ifdef PDAL_COMPILER_GCC @@ -109,5 +107,3 @@ class PDAL_DLL NitfFile } } } // namespaces - -#endif // HAVE_NITRO diff --git a/src/drivers/nitf/Reader.cpp b/plugins/nitf/drivers/NitfReader.cpp similarity index 96% rename from src/drivers/nitf/Reader.cpp rename to plugins/nitf/drivers/NitfReader.cpp index be0d26cd56..2695eaddf2 100644 --- a/src/drivers/nitf/Reader.cpp +++ b/plugins/nitf/drivers/NitfReader.cpp @@ -32,17 +32,10 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include - -#ifdef PDAL_HAVE_NITRO - -// local #include "NitfFile.hpp" +#include "NitfReader.hpp" -#include -#include - - +CREATE_READER_PLUGIN(nitf, pdal::drivers::nitf::NitfReader) namespace pdal { @@ -137,5 +130,3 @@ void NitfReader::ready(PointContextRef ctx) } // namespace nitf } // namespace drivers } // namespace pdal - -#endif // PDAL_HAVE_NITRO diff --git a/include/pdal/drivers/nitf/Reader.hpp b/plugins/nitf/drivers/NitfReader.hpp similarity index 96% rename from include/pdal/drivers/nitf/Reader.hpp rename to plugins/nitf/drivers/NitfReader.hpp index b93a966805..d2658e7b48 100644 --- a/include/pdal/drivers/nitf/Reader.hpp +++ b/plugins/nitf/drivers/NitfReader.hpp @@ -34,10 +34,9 @@ #pragma once -#include - -#ifdef PDAL_HAVE_NITRO #include +#include +#include namespace pdal { @@ -76,5 +75,3 @@ class PDAL_DLL NitfReader : public las::Reader } // namespace nitf } // namespace drivers } // namespace pdal - -#endif // PDAL_HAVE_NITRO diff --git a/src/drivers/nitf/Writer.cpp b/plugins/nitf/drivers/NitfWriter.cpp similarity index 97% rename from src/drivers/nitf/Writer.cpp rename to plugins/nitf/drivers/NitfWriter.cpp index e1ce165787..4c5945aac5 100644 --- a/src/drivers/nitf/Writer.cpp +++ b/plugins/nitf/drivers/NitfWriter.cpp @@ -35,15 +35,13 @@ #include #include -#include +#include "NitfWriter.hpp" #include +#include #include #include - -#ifdef PDAL_HAVE_NITRO - #ifdef PDAL_COMPILER_GCC # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wredundant-decls" @@ -73,14 +71,14 @@ # pragma GCC diagnostic pop #endif -#endif - // NOTES // // is it legal to write a LAZ file? // syntactically, how do we name all the LAS writer options that we will pass to the las writer? // +CREATE_WRITER_PLUGIN(nitf, pdal::drivers::nitf::NitfWriter) + namespace pdal { namespace drivers @@ -135,12 +133,12 @@ BOX3D reprojectBoxToDD(const SpatialReference& reference, const BOX3D& box) return output; } -Writer::Writer() : las::Writer(&m_oss) +NitfWriter::NitfWriter() : las::Writer(&m_oss) { register_tre_plugins(); } -void Writer::processOptions(const Options& options) +void NitfWriter::processOptions(const Options& options) { las::Writer::processOptions(options); m_cLevel = options.getValueOrDefault("CLEVEL","03"); @@ -170,18 +168,17 @@ void Writer::processOptions(const Options& options) {} } -void Writer::write(const PointBuffer& buffer) +void NitfWriter::write(const PointBuffer& buffer) { m_bounds.grow(buffer.calculateBounds(true)); drivers::las::Writer::write(buffer); } -void Writer::done(PointContextRef ctx) +void NitfWriter::done(PointContextRef ctx) { las::Writer::done(ctx); -#ifdef PDAL_HAVE_NITRO try { ::nitf::Record record(NITF_VER_21); @@ -344,7 +341,6 @@ void Writer::done(PointContextRef ctx) // std::cout << t.getTrace(); throw pdal_error(t.getMessage()); } -#endif } diff --git a/include/pdal/drivers/nitf/Writer.hpp b/plugins/nitf/drivers/NitfWriter.hpp similarity index 92% rename from include/pdal/drivers/nitf/Writer.hpp rename to plugins/nitf/drivers/NitfWriter.hpp index 1446597ea5..74125adcb3 100644 --- a/include/pdal/drivers/nitf/Writer.hpp +++ b/plugins/nitf/drivers/NitfWriter.hpp @@ -34,6 +34,7 @@ #pragma once +#include #include namespace pdal @@ -44,18 +45,14 @@ namespace nitf { -class PDAL_DLL Writer : public las::Writer +class PDAL_DLL NitfWriter : public las::Writer { public: SET_STAGE_NAME("drivers.nitf.writer", "NITF Writer") SET_STAGE_LINK("http://pdal.io/stages/drivers.nitf.writer.html") -#ifdef PDAL_HAVE_NITRO SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif - Writer() ; + NitfWriter() ; private: virtual void processOptions(const Options& options); @@ -82,8 +79,8 @@ class PDAL_DLL Writer : public las::Writer std::string m_igeolob; std::stringstream m_oss; - Writer& operator=(const Writer&); // not implemented - Writer(const Writer&); // not implemented + NitfWriter& operator=(const NitfWriter&); // not implemented + NitfWriter(const NitfWriter&); // not implemented }; } // namespace nitf diff --git a/src/drivers/nitf/nitflib.h b/plugins/nitf/drivers/nitflib.h similarity index 100% rename from src/drivers/nitf/nitflib.h rename to plugins/nitf/drivers/nitflib.h diff --git a/src/drivers/nitf/tre_plugins.cpp b/plugins/nitf/drivers/tre_plugins.cpp similarity index 99% rename from src/drivers/nitf/tre_plugins.cpp rename to plugins/nitf/drivers/tre_plugins.cpp index 1cc92add94..34719e0ec0 100644 --- a/src/drivers/nitf/tre_plugins.cpp +++ b/plugins/nitf/drivers/tre_plugins.cpp @@ -34,8 +34,6 @@ #include "tre_plugins.hpp" -#ifdef PDAL_HAVE_NITRO - #ifdef PDAL_COMPILER_GCC # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wredundant-decls" @@ -256,5 +254,3 @@ void register_tre_plugins() } } // namespaces - -#endif // HAVE_NITRO diff --git a/src/drivers/nitf/tre_plugins.hpp b/plugins/nitf/drivers/tre_plugins.hpp similarity index 97% rename from src/drivers/nitf/tre_plugins.hpp rename to plugins/nitf/drivers/tre_plugins.hpp index 9de14ebadb..a167533b0e 100644 --- a/src/drivers/nitf/tre_plugins.hpp +++ b/plugins/nitf/drivers/tre_plugins.hpp @@ -36,9 +36,6 @@ #include -#ifdef PDAL_HAVE_NITRO - - namespace pdal { namespace drivers { namespace nitf { @@ -48,4 +45,3 @@ void register_tre_plugins(); } } } // namespaces -#endif // HAVE_NITRO diff --git a/test/unit/drivers/nitf/NitfReaderTest.cpp b/plugins/nitf/test/NitfReaderTest.cpp similarity index 59% rename from test/unit/drivers/nitf/NitfReaderTest.cpp rename to plugins/nitf/test/NitfReaderTest.cpp index b19e8eb77c..618e98ae67 100644 --- a/test/unit/drivers/nitf/NitfReaderTest.cpp +++ b/plugins/nitf/test/NitfReaderTest.cpp @@ -39,8 +39,8 @@ #include #include #include +#include -#include #include #include #include @@ -67,57 +67,64 @@ BOOST_AUTO_TEST_CASE(test_one) nitf_opts.add("count", 750); PointContext ctx; - drivers::nitf::NitfReader nitf_reader; - nitf_reader.setOptions(nitf_opts); - nitf_reader.prepare(ctx); - PointBufferSet pbSet = nitf_reader.execute(ctx); - BOOST_CHECK_EQUAL(nitf_reader.getDescription(), "NITF Reader"); - BOOST_CHECK_EQUAL(pbSet.size(), 1); - PointBufferPtr buf = *pbSet.begin(); - - // check metadata -//ABELL -/** + StageFactory f; + StageFactory::ReaderCreator* rc = f.getReaderCreator("drivers.nitf.reader"); + if(rc) { - pdal::Metadata metadata = nitf_reader.getMetadata(); - /////////////////////////////////////////////////BOOST_CHECK_EQUAL(metadatums.size(), 80u); - BOOST_CHECK_EQUAL(metadata.toPTree().get("metadata.FH_FDT.value"), "20120323002946"); - } -**/ - - // - // read LAS - // - pdal::Options las_opts; - las_opts.add("count", 750); - las_opts.add("filename", Support::datapath("nitf/autzen-utm10.las")); - - PointContext ctx2; - drivers::las::Reader las_reader; - las_reader.setOptions(las_opts); - las_reader.prepare(ctx2); - PointBufferSet pbSet2 = las_reader.execute(ctx2); - BOOST_CHECK_EQUAL(pbSet2.size(), 1); - PointBufferPtr buf2 = *pbSet.begin(); - // - // - // compare the two buffers - // - BOOST_CHECK_EQUAL(buf->size(), buf2->size()); - - for (PointId i = 0; i < buf2->size(); i++) - { - int32_t nitf_x = buf->getFieldAs(Dimension::Id::X, i); - int32_t nitf_y = buf->getFieldAs(Dimension::Id::Y, i); - int32_t nitf_z = buf->getFieldAs(Dimension::Id::Z, i); - - int32_t las_x = buf2->getFieldAs(Dimension::Id::X, i); - int32_t las_y = buf2->getFieldAs(Dimension::Id::Y, i); - int32_t las_z = buf2->getFieldAs(Dimension::Id::Z, i); + BOOST_CHECK(rc); + + std::unique_ptr nitf_reader(rc()); + nitf_reader->setOptions(nitf_opts); + nitf_reader->prepare(ctx); + PointBufferSet pbSet = nitf_reader->execute(ctx); + BOOST_CHECK_EQUAL(nitf_reader->getDescription(), "NITF Reader"); + BOOST_CHECK_EQUAL(pbSet.size(), 1); + PointBufferPtr buf = *pbSet.begin(); + + // check metadata + //ABELL + /** + { + pdal::Metadata metadata = nitf_reader.getMetadata(); + /////////////////////////////////////////////////BOOST_CHECK_EQUAL(metadatums.size(), 80u); + BOOST_CHECK_EQUAL(metadata.toPTree().get("metadata.FH_FDT.value"), "20120323002946"); + } + **/ - BOOST_CHECK_EQUAL(nitf_x, las_x); - BOOST_CHECK_EQUAL(nitf_y, las_y); - BOOST_CHECK_EQUAL(nitf_z, las_z); + // + // read LAS + // + pdal::Options las_opts; + las_opts.add("count", 750); + las_opts.add("filename", Support::datapath("nitf/autzen-utm10.las")); + + PointContext ctx2; + drivers::las::Reader las_reader; + las_reader.setOptions(las_opts); + las_reader.prepare(ctx2); + PointBufferSet pbSet2 = las_reader.execute(ctx2); + BOOST_CHECK_EQUAL(pbSet2.size(), 1); + PointBufferPtr buf2 = *pbSet.begin(); + // + // + // compare the two buffers + // + BOOST_CHECK_EQUAL(buf->size(), buf2->size()); + + for (PointId i = 0; i < buf2->size(); i++) + { + int32_t nitf_x = buf->getFieldAs(Dimension::Id::X, i); + int32_t nitf_y = buf->getFieldAs(Dimension::Id::Y, i); + int32_t nitf_z = buf->getFieldAs(Dimension::Id::Z, i); + + int32_t las_x = buf2->getFieldAs(Dimension::Id::X, i); + int32_t las_y = buf2->getFieldAs(Dimension::Id::Y, i); + int32_t las_z = buf2->getFieldAs(Dimension::Id::Z, i); + + BOOST_CHECK_EQUAL(nitf_x, las_x); + BOOST_CHECK_EQUAL(nitf_y, las_y); + BOOST_CHECK_EQUAL(nitf_z, las_z); + } } } @@ -154,21 +161,28 @@ BOOST_AUTO_TEST_CASE(optionSrs) nitfOpts.add("spatialreference", sr); PointContext ctx; - drivers::nitf::NitfReader nitfReader; - nitfReader.setOptions(nitfOpts); + StageFactory f; + StageFactory::ReaderCreator* rc = f.getReaderCreator("drivers.nitf.reader"); + if (rc) + { + BOOST_CHECK(rc); - Options lasOpts; - lasOpts.add("filename", "/dev/null"); - drivers::las::Writer lasWriter; - lasWriter.setInput(&nitfReader); - lasWriter.setOptions(lasOpts);; + Stage* nitfReader = rc(); + nitfReader->setOptions(nitfOpts); - lasWriter.prepare(ctx); - PointBufferSet pbSet = lasWriter.execute(ctx); + Options lasOpts; + lasOpts.add("filename", "/dev/null"); + drivers::las::Writer lasWriter; + lasWriter.setInput(nitfReader); + lasWriter.setOptions(lasOpts);; - BOOST_CHECK_EQUAL(sr, nitfReader.getSpatialReference().getWKT()); - BOOST_CHECK_EQUAL("", lasWriter.getSpatialReference().getWKT()); - BOOST_CHECK_EQUAL(sr, ctx.spatialRef().getWKT()); + lasWriter.prepare(ctx); + PointBufferSet pbSet = lasWriter.execute(ctx); + + BOOST_CHECK_EQUAL(sr, nitfReader->getSpatialReference().getWKT()); + BOOST_CHECK_EQUAL("", lasWriter.getSpatialReference().getWKT()); + BOOST_CHECK_EQUAL(sr, ctx.spatialRef().getWKT()); + } } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/unit/drivers/nitf/NitfWriterTest.cpp b/plugins/nitf/test/NitfWriterTest.cpp similarity index 88% rename from test/unit/drivers/nitf/NitfWriterTest.cpp rename to plugins/nitf/test/NitfWriterTest.cpp index da460c87e2..1d538ebda5 100644 --- a/test/unit/drivers/nitf/NitfWriterTest.cpp +++ b/plugins/nitf/test/NitfWriterTest.cpp @@ -35,9 +35,8 @@ #include "UnitTest.hpp" #include +#include #include -#include -#include #include "Support.hpp" using namespace pdal; @@ -111,7 +110,6 @@ static void compare_contents(const std::string& las_file, const std::string& ntf BOOST_AUTO_TEST_CASE(test1) { -#ifdef PDAL_HAVE_NITRO const std::string las_input(Support::datapath("las/1.2-with-color.las")); const std::string nitf_output(Support::temppath("temp_nitf.ntf")); const std::string reference_output( @@ -153,26 +151,31 @@ BOOST_AUTO_TEST_CASE(test1) pdal::drivers::las::Reader reader; reader.setOptions(reader_opts); - pdal::drivers::nitf::Writer writer; - writer.setOptions(writer_opts); - writer.setInput(&reader); + StageFactory f; + StageFactory::WriterCreator* wc = f.getWriterCreator("drivers.nitf.writer"); + if(wc) { - // writer.setCompressed(false); - // // writer.setDate(0, 0); - // // writer.setPointFormat(::pdal::drivers::las::PointFormat3); - // // writer.setSystemIdentifier(""); - // writer.setGeneratingSoftware("PDAL-NITF"); - // writer.setChunkSize(100); + BOOST_CHECK(wc); + + std::unique_ptr writer(wc()); + writer->setOptions(writer_opts); + writer->setInput(&reader); + { + // writer.setCompressed(false); + // // writer.setDate(0, 0); + // // writer.setPointFormat(::pdal::drivers::las::PointFormat3); + // // writer.setSystemIdentifier(""); + // writer.setGeneratingSoftware("PDAL-NITF"); + // writer.setChunkSize(100); + } + PointContext ctx; + writer->prepare(ctx); + writer->execute(ctx); } - PointContext ctx; - writer.prepare(ctx); - writer.execute(ctx); } FileUtils::deleteFile(nitf_output); -#endif - #if 0 // // check the generated NITF diff --git a/plugins/oci/CMakeLists.txt b/plugins/oci/CMakeLists.txt new file mode 100644 index 0000000000..ba1cfbabc6 --- /dev/null +++ b/plugins/oci/CMakeLists.txt @@ -0,0 +1,63 @@ +# +# Oracle OCI plugin CMake configuration +# + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugins/oci) + +find_package(Oracle) +if(ORACLE_FOUND) + message(STATUS "Building with Oracle support") + + include_directories(${ORACLE_INCLUDE_DIR}) + + # + # OCI Reader + # + set(srcs + drivers/OciCommon.cpp + drivers/OciReader.cpp + drivers/OciWrapper.cpp + ) + + set(incs + drivers/OciCommon.hpp + drivers/OciReader.hpp + drivers/OciWrapper.h + ) + + set(deps ${ORACLE_LIBRARY}) + PDAL_ADD_PLUGIN(oci_reader_lib_name reader oci "${srcs}" "${incs}" "${deps}") + + # + # OCI Writer + # + set(srcs + drivers/OciCommon.cpp + drivers/OciWrapper.cpp + drivers/OciWriter.cpp + ) + + set(incs + drivers/OciCommon.hpp + drivers/OciWrapper.h + drivers/OciWriter.hpp + ) + + set(deps ${ORACLE_LIBRARY}) + PDAL_ADD_PLUGIN(oci_writer_lib_name writer oci "${srcs}" "${incs}" "${deps}") + + # + # OCI tests + # + if(BUILD_OCI_TESTS) + set(srcs + test/OCITest.cpp + ) + + set(deps ${oci_reader_lib_name} ${oci_writer_lib_name}) + PDAL_ADD_TEST(ocitest "${srcs}" "${deps}") + endif() +else() + message(STATUS "Building without Oracle support") +endif() diff --git a/src/drivers/oci/common.cpp b/plugins/oci/drivers/OciCommon.cpp similarity index 99% rename from src/drivers/oci/common.cpp rename to plugins/oci/drivers/OciCommon.cpp index 1714de1f0a..59aa262d4d 100644 --- a/src/drivers/oci/common.cpp +++ b/plugins/oci/drivers/OciCommon.cpp @@ -33,7 +33,7 @@ ****************************************************************************/ -#include +#include "OciCommon.hpp" #include diff --git a/include/pdal/drivers/oci/common.hpp b/plugins/oci/drivers/OciCommon.hpp similarity index 99% rename from include/pdal/drivers/oci/common.hpp rename to plugins/oci/drivers/OciCommon.hpp index cb24c74a17..0a97aca7b1 100644 --- a/include/pdal/drivers/oci/common.hpp +++ b/plugins/oci/drivers/OciCommon.hpp @@ -34,7 +34,7 @@ #pragma once -#include "oci_wrapper.h" +#include "OciWrapper.h" #include diff --git a/src/drivers/oci/OciReader.cpp b/plugins/oci/drivers/OciReader.cpp similarity index 98% rename from src/drivers/oci/OciReader.cpp rename to plugins/oci/drivers/OciReader.cpp index 889d67b22a..6cfda577f8 100644 --- a/src/drivers/oci/OciReader.cpp +++ b/plugins/oci/drivers/OciReader.cpp @@ -36,12 +36,9 @@ #include #include -#include +#include "OciReader.hpp" -#ifdef USE_PDAL_PLUGIN_OCI -//MAKE_READER_CREATOR(ociReader, pdal::drivers::oci::Reader) -CREATE_READER_PLUGIN(ociReader, pdal::drivers::oci::Reader) -#endif +CREATE_READER_PLUGIN(oci, pdal::drivers::oci::OciReader) namespace pdal { diff --git a/include/pdal/drivers/oci/OciReader.hpp b/plugins/oci/drivers/OciReader.hpp similarity index 97% rename from include/pdal/drivers/oci/OciReader.hpp rename to plugins/oci/drivers/OciReader.hpp index b4bba567d1..bc8c44970d 100644 --- a/include/pdal/drivers/oci/OciReader.hpp +++ b/plugins/oci/drivers/OciReader.hpp @@ -37,7 +37,9 @@ #include #include -#include +#include + +#include "OciCommon.hpp" namespace pdal { @@ -52,11 +54,7 @@ class PDAL_DLL OciReader : public pdal::Reader public: SET_STAGE_NAME("drivers.oci.reader", "OCI Reader") SET_STAGE_LINK("http://pdal.io/stages/drivers.oci.reader.html") -#ifdef PDAL_HAVE_ORACLE SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif OciReader() : pdal::Reader() {} diff --git a/src/drivers/oci/oci_wrapper.cpp b/plugins/oci/drivers/OciWrapper.cpp similarity index 99% rename from src/drivers/oci/oci_wrapper.cpp rename to plugins/oci/drivers/OciWrapper.cpp index f93ef1dbe3..b730dfc6ec 100644 --- a/src/drivers/oci/oci_wrapper.cpp +++ b/plugins/oci/drivers/OciWrapper.cpp @@ -28,7 +28,7 @@ * DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include +#include "OciWrapper.h" #include diff --git a/include/pdal/drivers/oci/oci_wrapper.h b/plugins/oci/drivers/OciWrapper.h similarity index 100% rename from include/pdal/drivers/oci/oci_wrapper.h rename to plugins/oci/drivers/OciWrapper.h diff --git a/src/drivers/oci/Writer.cpp b/plugins/oci/drivers/OciWriter.cpp similarity index 96% rename from src/drivers/oci/Writer.cpp rename to plugins/oci/drivers/OciWriter.cpp index a5d6f5b652..76445c67b0 100644 --- a/src/drivers/oci/Writer.cpp +++ b/plugins/oci/drivers/OciWriter.cpp @@ -39,7 +39,7 @@ #include #include -#include +#include "OciWriter.hpp" #include @@ -47,12 +47,7 @@ #include - -#ifdef USE_PDAL_PLUGIN_OCI -//MAKE_WRITER_CREATOR(ociWriter, pdal::drivers::oci::Writer) -CREATE_WRITER_PLUGIN(ociWriter, pdal::drivers::oci::Writer) -#endif - +CREATE_WRITER_PLUGIN(oci, pdal::drivers::oci::OciWriter) namespace pdal { @@ -62,7 +57,7 @@ namespace oci { -Writer::Writer() +OciWriter::OciWriter() : pdal::Writer() , m_createIndex(false) , m_bDidCreateBlockTable(false) @@ -77,12 +72,12 @@ Writer::Writer() , m_orientation(Orientation::PointMajor) {} -Writer::~Writer() +OciWriter::~OciWriter() { } -void Writer::initialize() +void OciWriter::initialize() { GlobalEnvironment::get().getGDALDebug()->addLog(log()); m_connection = connect(m_connSpec); @@ -90,7 +85,7 @@ void Writer::initialize() } -Options Writer::getDefaultOptions() +Options OciWriter::getDefaultOptions() { Options options; @@ -230,7 +225,7 @@ Options Writer::getDefaultOptions() } -void Writer::runCommand(std::ostringstream const& command) +void OciWriter::runCommand(std::ostringstream const& command) { Statement statement(m_connection->CreateStatement(command.str().c_str())); @@ -241,7 +236,7 @@ void Writer::runCommand(std::ostringstream const& command) } -void Writer::wipeBlockTable() +void OciWriter::wipeBlockTable() { std::ostringstream oss; @@ -293,7 +288,7 @@ void Writer::wipeBlockTable() } -void Writer::createBlockIndex() +void OciWriter::createBlockIndex() { std::ostringstream oss; @@ -320,7 +315,7 @@ void Writer::createBlockIndex() } -void Writer::createSDOEntry() +void OciWriter::createSDOEntry() { std::ostringstream oss; oss.setf(std::ios_base::fixed, std::ios_base::floatfield); @@ -366,7 +361,7 @@ void Writer::createSDOEntry() } -bool Writer::blockTableExists() +bool OciWriter::blockTableExists() { std::ostringstream oss; @@ -402,7 +397,7 @@ bool Writer::blockTableExists() } -void Writer::createBlockTable() +void OciWriter::createBlockTable() { std::ostringstream oss; oss << "CREATE TABLE " << m_blockTableName << @@ -414,7 +409,7 @@ void Writer::createBlockTable() } -bool Writer::isGeographic(int32_t srid) +bool OciWriter::isGeographic(int32_t srid) { std::unique_ptr kind(new char[OWNAME]); std::string stmt("SELECT COORD_REF_SYS_KIND from " @@ -442,7 +437,7 @@ bool Writer::isGeographic(int32_t srid) } -std::string Writer::loadSQLData(std::string const& filename) +std::string OciWriter::loadSQLData(std::string const& filename) { if (!FileUtils::fileExists(filename)) { @@ -473,7 +468,7 @@ std::string Writer::loadSQLData(std::string const& filename) } -void Writer::runFileSQL(std::string const& filename) +void OciWriter::runFileSQL(std::string const& filename) { std::ostringstream oss; std::string sql = getOptions().getValueOrDefault(filename, ""); @@ -494,7 +489,7 @@ void Writer::runFileSQL(std::string const& filename) // Get the geometry type -long Writer::getGType() +long OciWriter::getGType() { if (m_3d) return (m_solid ? 3008 : 3003); @@ -502,7 +497,7 @@ long Writer::getGType() } -std::string Writer::createPCElemInfo() +std::string OciWriter::createPCElemInfo() { if (m_3d) return m_solid ? "(1,1007,3)" : "(1,1003,3)"; @@ -510,7 +505,7 @@ std::string Writer::createPCElemInfo() } -void Writer::createPCEntry() +void OciWriter::createPCEntry() { std::ostringstream oss; @@ -691,7 +686,7 @@ void Writer::createPCEntry() } -bool Writer::isValidWKT(std::string const& input) +bool OciWriter::isValidWKT(std::string const& input) { OGRGeometryH g; @@ -702,7 +697,7 @@ bool Writer::isValidWKT(std::string const& input) } -void Writer::processOptions(const Options& options) +void OciWriter::processOptions(const Options& options) { m_precision = getDefaultedOption(options, "stream_output_precision"); @@ -752,14 +747,14 @@ void Writer::processOptions(const Options& options) } -void Writer::write(const PointBuffer& buffer) +void OciWriter::write(const PointBuffer& buffer) { writeInit(); writeTile(buffer); } -void Writer::writeInit() +void OciWriter::writeInit() { if (m_sdo_pc_is_initialized) return; @@ -792,7 +787,7 @@ void Writer::writeInit() } -void Writer::ready(PointContextRef ctx) +void OciWriter::ready(PointContextRef ctx) { bool haveOutputTable = blockTableExists(); if (m_overwrite && haveOutputTable) @@ -818,7 +813,7 @@ void Writer::ready(PointContextRef ctx) } -void Writer::done(PointContextRef ctx) +void OciWriter::done(PointContextRef ctx) { if (!m_connection) return; @@ -840,7 +835,7 @@ void Writer::done(PointContextRef ctx) } -void Writer::setElements(Statement statement, OCIArray* elem_info) +void OciWriter::setElements(Statement statement, OCIArray* elem_info) { statement->AddElement(elem_info, 1); if (m_solid == true) @@ -857,7 +852,7 @@ void Writer::setElements(Statement statement, OCIArray* elem_info) } -void Writer::setOrdinates(Statement statement, OCIArray* ordinates, +void OciWriter::setOrdinates(Statement statement, OCIArray* ordinates, const BOX3D& extent) { @@ -934,7 +929,7 @@ void fillBuf(const PointBuffer& buf, char *pos, Dimension::Id::Enum d, } // anonymous namespace. -void Writer::writeTile(PointBuffer const& buffer) +void OciWriter::writeTile(PointBuffer const& buffer) { bool usePartition = (m_blockTablePartitionColumn.size() != 0); @@ -1084,7 +1079,7 @@ void Writer::writeTile(PointBuffer const& buffer) } -std::string Writer::shutOff_SDO_PC_Trigger() +std::string OciWriter::shutOff_SDO_PC_Trigger() { // Don't monkey with the trigger unless the user says to. if (!m_disableCloudTrigger) @@ -1124,7 +1119,7 @@ std::string Writer::shutOff_SDO_PC_Trigger() } -void Writer::turnOn_SDO_PC_Trigger(std::string trigger_name) +void OciWriter::turnOn_SDO_PC_Trigger(std::string trigger_name) { if (!trigger_name.size()) return; @@ -1137,7 +1132,7 @@ void Writer::turnOn_SDO_PC_Trigger(std::string trigger_name) } -void Writer::updatePCExtent() +void OciWriter::updatePCExtent() { BOX3D bounds = m_baseTableBounds; if (bounds.empty()) diff --git a/include/pdal/drivers/oci/Writer.hpp b/plugins/oci/drivers/OciWriter.hpp similarity index 92% rename from include/pdal/drivers/oci/Writer.hpp rename to plugins/oci/drivers/OciWriter.hpp index ab5db3324d..e955d748f1 100644 --- a/include/pdal/drivers/oci/Writer.hpp +++ b/plugins/oci/drivers/OciWriter.hpp @@ -40,15 +40,7 @@ pdal::Writer* createOciWriter(); -#ifdef USE_PDAL_PLUGIN_OCI -PDAL_C_START - -PDAL_DLL void PDALRegister_writer_oci(void* factory); - -PDAL_C_END -#endif - -#include "common.hpp" +#include "OciCommon.hpp" namespace pdal { @@ -57,18 +49,14 @@ namespace drivers namespace oci { -class PDAL_DLL Writer : public pdal::Writer +class PDAL_DLL OciWriter : public pdal::Writer { public: SET_STAGE_NAME("drivers.oci.writer", "OCI Writer") SET_STAGE_LINK("http://pdal.io/stages/drivers.oci.writer.html") -#ifdef PDAL_HAVE_ORACLE SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif - Writer(); - ~Writer(); + OciWriter(); + ~OciWriter(); static Options getDefaultOptions(); @@ -85,8 +73,8 @@ class PDAL_DLL Writer : public pdal::Writer {} private: - Writer& operator=(const Writer&); // not implemented - Writer(const Writer&); // not implemented + OciWriter& operator=(const OciWriter&); // not implemented + OciWriter(const OciWriter&); // not implemented template T getDefaultedOption(const Options& options, diff --git a/test/unit/drivers/oci/OCITest.cpp b/plugins/oci/test/OCITest.cpp similarity index 94% rename from test/unit/drivers/oci/OCITest.cpp rename to plugins/oci/test/OCITest.cpp index a86a40ace8..17eb17e7e1 100644 --- a/test/unit/drivers/oci/OCITest.cpp +++ b/plugins/oci/test/OCITest.cpp @@ -37,22 +37,15 @@ #include #include -#include -#include -#include - +#include +#include #include #include - #include #include #include -#include -#include - -#include - +#include "../drivers/OciCommon.hpp" #include "Support.hpp" #include "TestConfig.hpp" @@ -251,15 +244,21 @@ bool WriteUnprojectedData() reader.setOptions(options); // pdal::filters::Chipper chipper(options); // chipper.setInput(&reader); - pdal::drivers::oci::Writer writer; - writer.setOptions(options); - writer.setInput(&reader); + StageFactory f; + StageFactory::WriterCreator* wc = f.getWriterCreator("drivers.oci.writer"); + if (wc) + { + BOOST_CHECK(wc); - writer.prepare(ctx); - writer.execute(ctx); + std::unique_ptr writer(wc()); + writer->setOptions(options); + writer->setInput(&reader); - //ABELL - This test doesn't test anything anymore. Perhaps it should. + writer->prepare(ctx); + writer->execute(ctx); + //ABELL - This test doesn't test anything anymore. Perhaps it should. + } return true; } @@ -379,19 +378,27 @@ BOOST_AUTO_TEST_CASE(read_unprojected_data) Option& verbose = options.getOptionByRef("verbose"); verbose.setValue( "7"); - pdal::drivers::oci::OciReader reader; - reader.setOptions(options); - PointContext ctx; - reader.prepare(ctx); - PointBufferSet pbSet = reader.execute(ctx); - BOOST_CHECK_EQUAL(pbSet.size(), 1); - PointBufferPtr buf = *pbSet.begin(); - BOOST_CHECK_EQUAL(buf->size(), 1065); + StageFactory f; + StageFactory::ReaderCreator* rc = f.getReaderCreator("drivers.oci.reader"); + if (rc) + { + BOOST_CHECK(rc); + + std::unique_ptr reader(rc()); - // checkUnProjectedPoints(*buf); + reader->setOptions(options); + PointContext ctx; + reader->prepare(ctx); + PointBufferSet pbSet = reader->execute(ctx); + BOOST_CHECK_EQUAL(pbSet.size(), 1); + PointBufferPtr buf = *pbSet.begin(); + BOOST_CHECK_EQUAL(buf->size(), 1065); - // compareAgainstSourceBuffer(*buf, Support::datapath("autzen-utm-chipped-25.las")); - compareAgainstSourceBuffer(*buf, Support::datapath("autzen/autzen-utm.las")); + // checkUnProjectedPoints(*buf); + + // compareAgainstSourceBuffer(*buf, Support::datapath("autzen-utm-chipped-25.las")); + compareAgainstSourceBuffer(*buf, Support::datapath("autzen/autzen-utm.las")); + } } diff --git a/plugins/p2g/CMakeLists.txt b/plugins/p2g/CMakeLists.txt new file mode 100644 index 0000000000..5a748c2998 --- /dev/null +++ b/plugins/p2g/CMakeLists.txt @@ -0,0 +1,30 @@ +# +# Points2grid plugin CMake configuration +# + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugins/p2g) + +find_package(Points2Grid) +if (P2G_FOUND) + message(STATUS "Building with Points2grid support") + + include_directories(${P2G_INCLUDE_DIR}) + add_definitions(-DHAVE_P2G=1) + + # + # Points2grid Writer + # + set(srcs + drivers/P2gWriter.cpp + ) + + set(incs + drivers/P2gWriter.hpp + ) + + set(deps ${P2G_LIBRARY}) + PDAL_ADD_PLUGIN(p2g_writer_lib_name writer p2g "${srcs}" "${incs}" "${deps}") +else() + message(STATUS "Building without Points2grid support") +endif() diff --git a/src/drivers/p2g/P2gWriter.cpp b/plugins/p2g/drivers/P2gWriter.cpp similarity index 98% rename from src/drivers/p2g/P2gWriter.cpp rename to plugins/p2g/drivers/P2gWriter.cpp index 76b8e005c1..d3f0113639 100644 --- a/src/drivers/p2g/P2gWriter.cpp +++ b/plugins/p2g/drivers/P2gWriter.cpp @@ -32,7 +32,7 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include +#include "P2gWriter.hpp" #include #include @@ -41,6 +41,7 @@ #include #include +CREATE_WRITER_PLUGIN(p2g, pdal::drivers::p2g::P2gWriter) namespace pdal { diff --git a/include/pdal/drivers/p2g/P2gWriter.hpp b/plugins/p2g/drivers/P2gWriter.hpp similarity index 97% rename from include/pdal/drivers/p2g/P2gWriter.hpp rename to plugins/p2g/drivers/P2gWriter.hpp index ac03e2c606..04fb3d2f55 100644 --- a/include/pdal/drivers/p2g/P2gWriter.hpp +++ b/plugins/p2g/drivers/P2gWriter.hpp @@ -35,16 +35,15 @@ #pragma once #include +#include #include #include -#ifdef PDAL_HAVE_P2G #include #include #include #include -#endif namespace pdal { @@ -71,11 +70,7 @@ class PDAL_DLL P2gWriter : public pdal::Writer public: SET_STAGE_NAME("drivers.p2g.writer", "Points2Grid Writer") SET_STAGE_LINK("http://pdal.io/stages/drivers.p2g.writer.html") -#ifdef PDAL_HAVE_P2G SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif P2gWriter() : Writer(), m_outputTypes(0), m_outputFormat(OUTPUT_FORMAT_ARC_ASCII) {}; ~P2gWriter() {}; diff --git a/plugins/pcl/CMakeLists.txt b/plugins/pcl/CMakeLists.txt index 1ad00c6fe6..93d5ae1813 100644 --- a/plugins/pcl/CMakeLists.txt +++ b/plugins/pcl/CMakeLists.txt @@ -22,10 +22,12 @@ #------------------------------------------------------------------------------ include_directories(${PROJECT_SOURCE_DIR}/include) -include_directories(${PROJECT_SOURCE_DIR}/plugin/pcl) +include_directories(${PROJECT_SOURCE_DIR}/plugins/pcl) find_package(PCL 1.7) if(PCL_FOUND) + message(STATUS "Building with PCL support") + set(PCL_LINKAGE "LINK_PUBLIC;general") include_directories(${PCL_INCLUDE_DIRS}) link_directories(${PCL_LIBRARY_DIRS}) @@ -35,10 +37,8 @@ if(PCL_FOUND) # PCL's configuration clobbers Boost find_package - do it again find_package(Boost 1.52 COMPONENTS program_options thread iostreams filesystem system unit_test_framework random) - message(STATUS "..building with PCL") - if (PCL_VISUALIZATION_FOUND) - message(STATUS "..building with PCL Visualization") + message(STATUS "Building with PCL Visualization support") # # PCLVisualizer Writer # @@ -51,11 +51,12 @@ if(PCL_FOUND) PCLConversions.hpp ) + set(deps ${PCL_LIBRARIES}) set(PCLVIZ_LIB_NAME pdal_plugin_writer_pclvisualizer) - PDAL_ADD_PLUGIN(${PCLVIZ_LIB_NAME} writer pclvisualizer ${srcs} ${incs}) - else() - message(STATUS "..building without PCL Visualization") - endif() + PDAL_ADD_PLUGIN(${PCLVIZ_LIB_NAME} writer pclvisualizer "${srcs}" "${incs}" "${deps}") +else() + message(STATUS "..building without PCL Visualization") +endif() # # PCD Reader @@ -72,9 +73,8 @@ if(PCL_FOUND) PCLConversions.hpp ) - set(PCD_READ_LIB_NAME pdal_plugin_reader_pcd) - PDAL_ADD_PLUGIN(${PCD_READ_LIB_NAME} reader pcd ${srcs} ${incs}) - target_link_libraries(${PCD_READ_LIB_NAME} ${PDAL_LINKAGE} ${PCL_LIBRARIES}) + set(deps ${PCL_LIBRARIES}) + PDAL_ADD_PLUGIN(pcd_reader_lib_name reader pcd "${srcs}" "${incs}" "${deps}") # # PCD Writer @@ -91,9 +91,8 @@ if(PCL_FOUND) PCLConversions.hpp ) - set(PCD_WRITE_LIB_NAME pdal_plugin_writer_pcd) - PDAL_ADD_PLUGIN(${PCD_WRITE_LIB_NAME} writer pcd ${srcs} ${incs}) - target_link_libraries(${PCD_WRITE_LIB_NAME} ${PDAL_LINKAGE} ${PCL_LIBRARIES}) + set(deps ${PCL_LIBRARIES}) + PDAL_ADD_PLUGIN(pcd_writer_lib_name writer pcd "${srcs}" "${incs}" "${deps}") # # PCLBlock Filter @@ -110,9 +109,9 @@ if(PCL_FOUND) PCLConversions.hpp ) - set(PCLBLOCK_LIB_NAME pdal_plugin_filter_pclblock) - PDAL_ADD_PLUGIN(${PCLBLOCK_LIB_NAME} filter pclblock ${srcs} ${incs}) - target_link_libraries(${PCLBLOCK_LIB_NAME} ${PDAL_LINKAGE} ${PCL_LIBRARIES}) + set(deps ${PCL_LIBRARIES}) + PDAL_ADD_PLUGIN(pclblock_filter_lib_name filter pclblock "${srcs}" "${incs}" "${deps}") + # # PCL Kernel # @@ -122,12 +121,10 @@ if(PCL_FOUND) set(incs kernel/PCL.hpp - #PCLConversions.hpp ) - set(PCL_KERNEL_LIB_NAME pdal_plugin_kernel_pcl) - PDAL_ADD_PLUGIN(${PCL_KERNEL_LIB_NAME} kernel pcl ${srcs} ${incs}) - target_link_libraries(${PCL_KERNEL_LIB_NAME} ${PCLBLOCK_LIB_NAME}) + set(deps ${PCL_LIBRARIES} ${pclblock_filter_lib_name}) + PDAL_ADD_PLUGIN(pcl_kernel_lib_name kernel pcl "${srcs}" "${incs}" "${deps}") # # Ground Kernel @@ -140,9 +137,8 @@ if(PCL_FOUND) kernel/Ground.hpp ) - set(GROUND_KERNEL_LIB_NAME pdal_plugin_kernel_ground) - PDAL_ADD_PLUGIN(${GROUND_KERNEL_LIB_NAME} kernel ground ${srcs} ${incs}) - target_link_libraries(${GROUND_KERNEL_LIB_NAME} ${PCLBLOCK_LIB_NAME}) + set(deps ${PCL_LIBRARIES} ${pclblock_filter_lib_name}) + PDAL_ADD_PLUGIN(ground_kernel_lib_name kernel ground "${srcs}" "${incs}" "${deps}") # # Smooth Kernel @@ -155,9 +151,8 @@ if(PCL_FOUND) kernel/Smooth.hpp ) - set(SMOOTH_KERNEL_LIB_NAME pdal_plugin_kernel_smooth) - PDAL_ADD_PLUGIN(${SMOOTH_KERNEL_LIB_NAME} kernel smooth ${srcs} ${incs}) - target_link_libraries(${SMOOTH_KERNEL_LIB_NAME} ${PCLBLOCK_LIB_NAME}) + set(deps ${PCL_LIBRARIES} ${pclblock_filter_lib_name}) + PDAL_ADD_PLUGIN(smooth_kernel_lib_name kernel smooth "${srcs}" "${incs}" "${deps}") # # View Kernel @@ -168,9 +163,20 @@ if(PCL_FOUND) set(incs kernel/View.hpp - #PCLConversions.hpp ) - set(VIEW_KERNEL_LIB_NAME pdal_plugin_kernel_view) - PDAL_ADD_PLUGIN(${VIEW_KERNEL_LIB_NAME} kernel view ${srcs} ${incs}) + set(deps ${PCL_LIBRARIES}) + PDAL_ADD_PLUGIN(view_kernel_lib_name kernel view "${srcs}" "${incs}" "${deps}") + + # + # PCL tests + # + set(srcs + test/PCLBlockFilterTest.cpp + ) + + set(deps ${pclvisualizer_lib_name} ${pcd_reader_lib_name} ${pcd_writer_lib_name} ${pclblock_filter_lib_name} ${pcl_kernel_lib_name} ${ground_kernel_lib_name} ${smooth_kernel_lib_name} ${view_kernel_lib_name}) + PDAL_ADD_TEST(pcltest "${srcs}" "${deps}") +else() + message(STATUS "Building without PCL support") endif() diff --git a/plugins/pcl/drivers/PCLVisualizer.hpp b/plugins/pcl/drivers/PCLVisualizer.hpp index 68e01cff8c..3b71d89974 100644 --- a/plugins/pcl/drivers/PCLVisualizer.hpp +++ b/plugins/pcl/drivers/PCLVisualizer.hpp @@ -38,12 +38,6 @@ #include -PDAL_C_START - -PDAL_DLL void PDALRegister_writer_pclvisualizer(void* factory); - -PDAL_C_END - namespace pdal { namespace drivers diff --git a/plugins/pcl/drivers/PcdReader.hpp b/plugins/pcl/drivers/PcdReader.hpp index 95ebc0fd45..8886a6d207 100644 --- a/plugins/pcl/drivers/PcdReader.hpp +++ b/plugins/pcl/drivers/PcdReader.hpp @@ -40,12 +40,6 @@ #include "PcdCommon.hpp" -PDAL_C_START - -PDAL_DLL void PDALRegister_writer_pcd(void* factory); - -PDAL_C_END - namespace pdal { namespace drivers diff --git a/plugins/pcl/drivers/PcdWriter.hpp b/plugins/pcl/drivers/PcdWriter.hpp index d8789f40bf..17adc2a8b5 100644 --- a/plugins/pcl/drivers/PcdWriter.hpp +++ b/plugins/pcl/drivers/PcdWriter.hpp @@ -41,12 +41,6 @@ #include #include -PDAL_C_START - -PDAL_DLL void PDALRegister_reader_pcd(void* factory); - -PDAL_C_END - namespace pdal { namespace drivers diff --git a/plugins/pcl/filters/PCLBlock.hpp b/plugins/pcl/filters/PCLBlock.hpp index 394d0fca17..bf55a2cf75 100644 --- a/plugins/pcl/filters/PCLBlock.hpp +++ b/plugins/pcl/filters/PCLBlock.hpp @@ -37,12 +37,6 @@ #include #include -PDAL_C_START - -PDAL_DLL void PDALRegister_filter_pclblock(void* factory); - -PDAL_C_END - namespace pdal { namespace filters diff --git a/plugins/pcl/kernel/Ground.hpp b/plugins/pcl/kernel/Ground.hpp index 1715ce2d72..4df9acaa72 100644 --- a/plugins/pcl/kernel/Ground.hpp +++ b/plugins/pcl/kernel/Ground.hpp @@ -39,12 +39,6 @@ #include -PDAL_C_START - -PDAL_DLL void PDALRegister_kernel_ground(void* factory); - -PDAL_C_END - namespace pdal { namespace kernel diff --git a/plugins/pcl/kernel/PCL.hpp b/plugins/pcl/kernel/PCL.hpp index 6435c5582a..84bb07c7ce 100644 --- a/plugins/pcl/kernel/PCL.hpp +++ b/plugins/pcl/kernel/PCL.hpp @@ -36,12 +36,6 @@ #include -PDAL_C_START - -PDAL_DLL void PDALRegister_kernel_pcl(void* factory); - -PDAL_C_END - namespace pdal { namespace kernel diff --git a/plugins/pcl/kernel/Smooth.hpp b/plugins/pcl/kernel/Smooth.hpp index 24262bb3a2..5aadbf9aa2 100644 --- a/plugins/pcl/kernel/Smooth.hpp +++ b/plugins/pcl/kernel/Smooth.hpp @@ -39,12 +39,6 @@ #include -PDAL_C_START - -PDAL_DLL void PDALRegister_kernel_smooth(void* factory); - -PDAL_C_END - namespace pdal { namespace kernel diff --git a/plugins/pcl/kernel/View.hpp b/plugins/pcl/kernel/View.hpp index 8b05b5d449..532b36c90b 100644 --- a/plugins/pcl/kernel/View.hpp +++ b/plugins/pcl/kernel/View.hpp @@ -39,12 +39,6 @@ #include -PDAL_C_START - -PDAL_DLL void PDALRegister_kernel_view(void* factory); - -PDAL_C_END - namespace pdal { namespace kernel diff --git a/test/unit/filters/PCLBlockFilterTest.cpp b/plugins/pcl/test/PCLBlockFilterTest.cpp similarity index 100% rename from test/unit/filters/PCLBlockFilterTest.cpp rename to plugins/pcl/test/PCLBlockFilterTest.cpp diff --git a/plugins/pgpointcloud/CMakeLists.txt b/plugins/pgpointcloud/CMakeLists.txt new file mode 100644 index 0000000000..b05d361393 --- /dev/null +++ b/plugins/pgpointcloud/CMakeLists.txt @@ -0,0 +1,73 @@ +# +# PgPointCloud plugin CMake configuration +# + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugins/pgpointcloud) + +find_package(PostgreSQL) +if (POSTGRESQL_FOUND) + message(STATUS "Building with PgPointCloud support") + + mark_as_advanced(CLEAR POSTGRESQL_INCLUDE_DIR) + mark_as_advanced(CLEAR POSTGRESQL_LIBRARIES) + include_directories(${POSTGRESQL_INCLUDE_DIR}) + + # + # PgPointCloud Reader + # + set(srcs + drivers/PgReader.cpp + ) + + set(incs + drivers/PgCommon.hpp + drivers/PgReader.hpp + ) + + set(deps ${POSTGRESQL_LIBRARIES}) + PDAL_ADD_PLUGIN(pgpointcloud_reader_lib_name reader pgpointcloud "${srcs}" "${incs}" "${deps}") + + # + # PgPointCloud Writer + # + set(srcs + drivers/PgWriter.cpp + ) + + set(incs + drivers/PgCommon.hpp + drivers/PgWriter.hpp + ) + + set(deps ${POSTGRESQL_LIBRARIES}) + PDAL_ADD_PLUGIN(pgpointcloud_writer_lib_name writer pgpointcloud "${srcs}" "${incs}" "${deps}") + + # + # PgPointCloud tests + # + if (BUILD_PGPOINTCLOUD_TESTS) + set(PGPOINTCLOUD_TEST_DB_HOST localhost CACHE STRING "Postgres test database host") + set(PGPOINTCLOUD_TEST_DB_PORT 5432 CACHE STRING "Postgres test database port") + set(PGPOINTCLOUD_TEST_DB_NAME pdal_test CACHE STRING + "Postgres test database name, must exist and must be able to create databases") + set(PGPOINTCLOUD_TEST_DB_TEMPNAME pdal_test_tmp CACHE STRING "Postgres test database temp database name") + + configure_file( + test/Pgtest-Support.hpp.in + ${CMAKE_CURRENT_BINARY_DIR}/Pgtest-Support.hpp + ) + + set(srcs + test/PgpointcloudWriterTest.cpp + ${CMAKE_CURRENT_BINARY_DIR}/Pgtest-Support.hpp + ) + + include_directories(${CMAKE_CURRENT_BINARY_DIR}) + + set(deps ${pgpointcloud_reader_lib_name} ${pgpointcloud_writer_lib_name}) + PDAL_ADD_TEST(pgpointcloudtest "${srcs}" "${deps}") + endif() +else() + message(STATUS "Building without PgPointCloud support") +endif() diff --git a/include/pdal/drivers/pgpointcloud/common.hpp b/plugins/pgpointcloud/drivers/PgCommon.hpp similarity index 89% rename from include/pdal/drivers/pgpointcloud/common.hpp rename to plugins/pgpointcloud/drivers/PgCommon.hpp index 2edebd72ea..8c01500a53 100644 --- a/include/pdal/drivers/pgpointcloud/common.hpp +++ b/plugins/pgpointcloud/drivers/PgCommon.hpp @@ -40,6 +40,7 @@ #include "libpq-fe.h" #include #include +#include namespace pdal { @@ -48,28 +49,16 @@ namespace drivers namespace pgpointcloud { -namespace CompressionType -{ - -enum Enum -{ - None = 0, - Ght = 1, - Dimensional = 2, - Unknown = 256 -}; - -} // namespace CompressionType - - -inline CompressionType::Enum getCompressionType( +inline pdal::compression::CompressionType::Enum getCompressionType( std::string const& compression_type) { if (boost::iequals(compression_type, "dimensional")) - return CompressionType::Dimensional; + return compression::CompressionType::Dimensional; else if (boost::iequals(compression_type, "ght")) - return CompressionType::Ght; - return CompressionType::None; + return compression::CompressionType::Ght; + else if (boost::iequals(compression_type, "laszperf")) + return compression::CompressionType::Lazperf; + return compression::CompressionType::None; } inline PGconn* pg_connect(std::string const& connection) @@ -86,17 +75,17 @@ inline PGconn* pg_connect(std::string const& connection) PQconninfoOption *connOptions = PQconninfoParse(connection.c_str(), &errstr); if ( ! connOptions ) { - throw pdal_error(errstr); + throw pdal_error(errstr); } #endif - + /* connect to database */ conn = PQconnectdb(connection.c_str()); if ( (!conn) || (PQstatus(conn) != CONNECTION_OK) ) { - throw pdal_error("unable to connect to database"); + throw pdal_error("unable to connect to database"); } - + return conn; } @@ -126,9 +115,9 @@ inline void pg_commit(PGconn* session) inline char* pg_query_once(PGconn* session, std::string const& sql) { PGresult *result = PQexec(session, sql.c_str()); - + if ( (!result) || - PQresultStatus(result) != PGRES_TUPLES_OK || + PQresultStatus(result) != PGRES_TUPLES_OK || PQntuples(result) == 0 ) { PQclear(result); @@ -149,7 +138,7 @@ inline PGresult* pg_query_result(PGconn* session, std::string const& sql) errmsg = std::string(PQerrorMessage(session)); throw pdal_error(errmsg); } - + if ( PQresultStatus(result) != PGRES_TUPLES_OK ) { errmsg = std::string(PQresultErrorMessage(result)); diff --git a/src/drivers/pgpointcloud/PgReader.cpp b/plugins/pgpointcloud/drivers/PgReader.cpp similarity index 97% rename from src/drivers/pgpointcloud/PgReader.cpp rename to plugins/pgpointcloud/drivers/PgReader.cpp index 9704b79d0b..e31e852c9c 100644 --- a/src/drivers/pgpointcloud/PgReader.cpp +++ b/plugins/pgpointcloud/drivers/PgReader.cpp @@ -33,16 +33,13 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include +#include "PgReader.hpp" #include #include #include -#ifdef USE_PDAL_PLUGIN_PGPOINTCLOUD -//MAKE_READER_CREATOR(pgpointcloudReader, pdal::drivers::pgpointcloud::PgReader) -CREATE_READER_PLUGIN(pgpointcloudReader, pdal::drivers::pgpointcloud::PgReader) -#endif +CREATE_READER_PLUGIN(pgpointcloud, pdal::drivers::pgpointcloud::PgReader) namespace pdal { diff --git a/include/pdal/drivers/pgpointcloud/PgReader.hpp b/plugins/pgpointcloud/drivers/PgReader.hpp similarity index 98% rename from include/pdal/drivers/pgpointcloud/PgReader.hpp rename to plugins/pgpointcloud/drivers/PgReader.hpp index 23158b0137..0a2f620bff 100644 --- a/include/pdal/drivers/pgpointcloud/PgReader.hpp +++ b/plugins/pgpointcloud/drivers/PgReader.hpp @@ -36,9 +36,10 @@ #include #include +#include #include -#include +#include "PgCommon.hpp" #include diff --git a/src/drivers/pgpointcloud/Writer.cpp b/plugins/pgpointcloud/drivers/PgWriter.cpp similarity index 93% rename from src/drivers/pgpointcloud/Writer.cpp rename to plugins/pgpointcloud/drivers/PgWriter.cpp index f82786c927..5e67c71a48 100644 --- a/src/drivers/pgpointcloud/Writer.cpp +++ b/plugins/pgpointcloud/drivers/PgWriter.cpp @@ -35,7 +35,7 @@ #include -#include +#include "PgWriter.hpp" #include #include @@ -43,10 +43,7 @@ #include #include -#ifdef USE_PDAL_PLUGIN_PGPOINTCLOUD -//MAKE_WRITER_CREATOR(pgpointcloudWriter, pdal::drivers::pgpointcloud::Writer) -CREATE_WRITER_PLUGIN(pgpointcloudWriter, pdal::drivers::pgpointcloud::Writer) -#endif +CREATE_WRITER_PLUGIN(pgpointcloud, pdal::drivers::pgpointcloud::PgWriter) // TO DO: // - change INSERT into COPY @@ -68,13 +65,13 @@ namespace drivers namespace pgpointcloud { -Writer::Writer() +PgWriter::PgWriter() : pdal::Writer() , m_session(0) , m_schema_name("") , m_table_name("") , m_column_name("") - , m_patch_compression_type(CompressionType::None) + , m_patch_compression_type(compression::CompressionType::None) , m_patch_capacity(400) , m_srid(0) , m_pcid(0) @@ -86,14 +83,14 @@ Writer::Writer() } -Writer::~Writer() +PgWriter::~PgWriter() { if (m_session) PQfinish(m_session); } -void Writer::processOptions(const Options& options) +void PgWriter::processOptions(const Options& options) { // If we don't know the table name, we're SOL m_table_name = options.getValueOrThrow("table"); @@ -121,7 +118,7 @@ void Writer::processOptions(const Options& options) } -void Writer::ready(PointContextRef ctx) +void PgWriter::ready(PointContextRef ctx) { m_pointSize = 0; m_dims = ctx.dims(); @@ -142,7 +139,7 @@ void Writer::ready(PointContextRef ctx) // Optional things you can defer or attempt to initialize // here. // -void Writer::initialize() +void PgWriter::initialize() { m_session = pg_connect(m_connection); } @@ -151,7 +148,7 @@ void Writer::initialize() // Called from somewhere (?) in PDAL core presumably to provide a user-friendly // means of editing the reader options. // -Options Writer::getDefaultOptions() +Options PgWriter::getDefaultOptions() { Options options; @@ -180,7 +177,7 @@ Options Writer::getDefaultOptions() return options; } -void Writer::writeInit() +void PgWriter::writeInit() { if (m_schema_is_initialized) return; @@ -224,14 +221,14 @@ void Writer::writeInit() m_schema_is_initialized = true; } -void Writer::write(const PointBuffer& buffer) +void PgWriter::write(const PointBuffer& buffer) { writeInit(); writeTile(buffer); } -void Writer::done(PointContextRef ctx) +void PgWriter::done(PointContextRef ctx) { if (m_create_index && m_have_postgis) { @@ -259,7 +256,7 @@ void Writer::done(PointContextRef ctx) } -uint32_t Writer::SetupSchema(uint32_t srid) +uint32_t PgWriter::SetupSchema(uint32_t srid) { // If the user has specified a PCID they want to use, @@ -299,6 +296,18 @@ uint32_t Writer::SetupSchema(uint32_t srid) // Create an XML output schema. schema::Writer writer(m_dims, m_types); + std::string compression; + /* If the writer specifies a compression, we should set that */ + if (m_patch_compression_type == compression::CompressionType::Dimensional) + compression = "dimensional"; + else if (m_patch_compression_type == compression::CompressionType::Ght) + compression = "ght"; + + Metadata metadata; + MetadataNode m = metadata.getNode(); + m.add("compression", compression); + + writer.setMetadata(m); std::string xml = writer.getXML(); // Do any of the existing schemas match the one we want to use? @@ -333,16 +342,7 @@ uint32_t Writer::SetupSchema(uint32_t srid) pcid = atoi(pcid_str); } - std::string compression; - /* If the writer specifies a compression, we should set that */ - if (m_patch_compression_type == CompressionType::Dimensional) - compression = "dimensional"; - else if (m_patch_compression_type == CompressionType::Ght) - compression = "ght"; - Metadata metadata; - MetadataNode m = metadata.getNode(); - m.add("compression", compression); const char* paramValues = xml.c_str(); oss << "INSERT INTO pointcloud_formats (pcid, srid, schema) " @@ -357,7 +357,7 @@ uint32_t Writer::SetupSchema(uint32_t srid) } -void Writer::DeleteTable(std::string const& schema_name, +void PgWriter::DeleteTable(std::string const& schema_name, std::string const& table_name) { std::ostringstream oss; @@ -374,7 +374,7 @@ void Writer::DeleteTable(std::string const& schema_name, } -bool Writer::CheckPointCloudExists() +bool PgWriter::CheckPointCloudExists() { log()->get(LogLevel::Debug) << "checking for pointcloud existence ... " << std::endl; @@ -392,7 +392,7 @@ bool Writer::CheckPointCloudExists() } -bool Writer::CheckPostGISExists() +bool PgWriter::CheckPostGISExists() { log()->get(LogLevel::Debug) << "checking for PostGIS existence ... " << std::endl; @@ -410,7 +410,7 @@ bool Writer::CheckPostGISExists() } -bool Writer::CheckTableExists(std::string const& name) +bool PgWriter::CheckTableExists(std::string const& name) { std::ostringstream oss; oss << "SELECT count(*) FROM pg_tables WHERE tablename ILIKE '" << @@ -434,7 +434,7 @@ bool Writer::CheckTableExists(std::string const& name) } -void Writer::CreateTable(std::string const& schema_name, +void PgWriter::CreateTable(std::string const& schema_name, std::string const& table_name, std::string const& column_name, boost::uint32_t pcid) { @@ -453,7 +453,7 @@ void Writer::CreateTable(std::string const& schema_name, // Make sure you test for the presence of PostGIS before calling this -void Writer::CreateIndex(std::string const& schema_name, +void PgWriter::CreateIndex(std::string const& schema_name, std::string const& table_name, std::string const& column_name) { std::ostringstream oss; @@ -529,7 +529,7 @@ void fillBuf(const PointBuffer& buf, char *pos, Dimension::Id::Enum d, } // anonymous namespace. -void Writer::writeTile(PointBuffer const& buffer) +void PgWriter::writeTile(PointBuffer const& buffer) { if (buffer.size() > m_patch_capacity) { @@ -594,7 +594,7 @@ void Writer::writeTile(PointBuffer const& buffer) uint32_t num_points = buffer.size(); int32_t pcid = m_pcid; - CompressionType::Enum compression_v = CompressionType::None; + compression::CompressionType::Enum compression_v = compression::CompressionType::None; uint32_t compression = static_cast(compression_v); #ifdef BOOST_LITTLE_ENDIAN diff --git a/include/pdal/drivers/pgpointcloud/Writer.hpp b/plugins/pgpointcloud/drivers/PgWriter.hpp similarity index 91% rename from include/pdal/drivers/pgpointcloud/Writer.hpp rename to plugins/pgpointcloud/drivers/PgWriter.hpp index 0f97d14205..d10403cb5b 100644 --- a/include/pdal/drivers/pgpointcloud/Writer.hpp +++ b/plugins/pgpointcloud/drivers/PgWriter.hpp @@ -36,7 +36,8 @@ #pragma once #include -#include +#include +#include "PgCommon.hpp" namespace pdal { @@ -46,26 +47,22 @@ namespace pgpointcloud { -class PDAL_DLL Writer : public pdal::Writer +class PDAL_DLL PgWriter : public pdal::Writer { public: SET_STAGE_NAME("drivers.pgpointcloud.writer", "PostgresSQL Pointcloud Database Writer") SET_STAGE_LINK("http://pdal.io/stages/drivers.pgpointcloud.writer.html") -#ifdef PDAL_HAVE_POSTGRESQL SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif - Writer(); - ~Writer(); + PgWriter(); + ~PgWriter(); static Options getDefaultOptions(); private: - Writer& operator=(const Writer&); // not implemented - Writer(const Writer&); // not implemented + PgWriter& operator=(const PgWriter&); // not implemented + PgWriter(const PgWriter&); // not implemented virtual void processOptions(const Options& options); virtual void ready(PointContextRef ctx); @@ -100,7 +97,7 @@ class PDAL_DLL Writer : public pdal::Writer std::string m_table_name; std::string m_column_name; std::string m_connection; - CompressionType::Enum m_patch_compression_type; + compression::CompressionType::Enum m_patch_compression_type; uint32_t m_patch_capacity; uint32_t m_srid; uint32_t m_pcid; diff --git a/test/unit/drivers/pgpointcloud/PgpointcloudWriterTest.cpp b/plugins/pgpointcloud/test/PgpointcloudWriterTest.cpp similarity index 71% rename from test/unit/drivers/pgpointcloud/PgpointcloudWriterTest.cpp rename to plugins/pgpointcloud/test/PgpointcloudWriterTest.cpp index 27eb0c8143..db9654814a 100644 --- a/test/unit/drivers/pgpointcloud/PgpointcloudWriterTest.cpp +++ b/plugins/pgpointcloud/test/PgpointcloudWriterTest.cpp @@ -35,12 +35,12 @@ #include "UnitTest.hpp" #include +#include #include -#include #include "Support.hpp" #include "Pgtest-Support.hpp" - +#include "../drivers/PgCommon.hpp" using namespace pdal; @@ -136,39 +136,65 @@ BOOST_FIXTURE_TEST_SUITE(PgpointcloudWriterTest, PgpointcloudWriterTestFixture) BOOST_AUTO_TEST_CASE(testWrite) { - pdal::drivers::las::Reader reader(Support::datapath("las/1.2-with-color.las")); - pdal::drivers::pgpointcloud::Writer writer(getWriterOptions()); - writer.setInput(&reader); + StageFactory f; + StageFactory::WriterCreator* wc = f.getWriterCreator("drivers.pgpointcloud.writer"); + if (wc) + { + BOOST_CHECK(wc); + const std::string file(Support::datapath("las/1.2-with-color.las")); - PointContext ctx; - writer.prepare(ctx); + const pdal::Option opt_filename("filename", file); + pdal::drivers::las::Reader reader; + pdal::Options options; + options.add(opt_filename); + reader.setOptions(options); + std::unique_ptr writer(wc()); + writer->setOptions(getWriterOptions()); + writer->setInput(&reader); - PointBufferSet written = writer.execute(ctx); + PointContext ctx; + writer->prepare(ctx); - point_count_t count(0); - for(auto i = written.begin(); i != written.end(); ++i) - { - count += (*i)->size(); + PointBufferSet written = writer->execute(ctx); + + point_count_t count(0); + for(auto i = written.begin(); i != written.end(); ++i) + { + count += (*i)->size(); + } + BOOST_CHECK_EQUAL(written.size(), 1); + // BOOST_CHECK_EQUAL(count, 0); + BOOST_CHECK_EQUAL(count, 1065); } - BOOST_CHECK_EQUAL(written.size(), 1); - // BOOST_CHECK_EQUAL(count, 0); - BOOST_CHECK_EQUAL(count, 1065); } BOOST_AUTO_TEST_CASE(testNoPointcloudExtension) { - executeOnTestDb("DROP EXTENSION pointcloud"); + StageFactory f; + StageFactory::WriterCreator* wc = f.getWriterCreator("drivers.pgpointcloud.writer"); + if (wc) + { + BOOST_CHECK(wc); - pdal::drivers::las::Reader reader(Support::datapath("las/1.2-with-color.las")); - pdal::drivers::pgpointcloud::Writer writer(getWriterOptions()); - writer.setInput(&reader); + executeOnTestDb("DROP EXTENSION pointcloud"); - PointContext ctx; - writer.prepare(ctx); + const std::string file(Support::datapath("las/1.2-with-color.las")); + const pdal::Option opt_filename("filename", file); + pdal::drivers::las::Reader reader; + pdal::Options options; + options.add(opt_filename); + reader.setOptions(options); + std::unique_ptr writer(wc()); + writer->setOptions(getWriterOptions()); + writer->setInput(&reader); - BOOST_CHECK_THROW(writer.execute(ctx), pdal::pdal_error); + PointContext ctx; + writer->prepare(ctx); + + BOOST_CHECK_THROW(writer->execute(ctx), pdal::pdal_error); + } } diff --git a/test/unit/drivers/pgpointcloud/Pgtest-Support.hpp.in b/plugins/pgpointcloud/test/Pgtest-Support.hpp.in similarity index 100% rename from test/unit/drivers/pgpointcloud/Pgtest-Support.hpp.in rename to plugins/pgpointcloud/test/Pgtest-Support.hpp.in diff --git a/plugins/rxp/CMakeLists.txt b/plugins/rxp/CMakeLists.txt new file mode 100644 index 0000000000..13f7e34f9b --- /dev/null +++ b/plugins/rxp/CMakeLists.txt @@ -0,0 +1,46 @@ +set(RXP_TEST_NAME rxptest) + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugin/rxp) + +find_package(RiVLib COMPONENTS scanlib REQUIRED) + +include_directories(${RiVLib_INCLUDE_DIRS}) +message(STATUS "Found RiVLib at: ${RiVLib_INCLUDE_DIRS}") + +set(incs + drivers/RxpReader.hpp + ) + +set(srcs + drivers/RxpReader.cpp + ) + +set(deps + ${RiVLib_SCANLIB_LIBRARY} + ) + +PDAL_ADD_PLUGIN(rxp_reader_lib_name reader rxp "${srcs}" "${incs}" "${deps}") + + +if (BUILD_RIVLIB_TESTS) + configure_file( + test/Config.hpp.in + "${CMAKE_CURRENT_BINARY_DIR}/test/Config.hpp" + ) + + include_directories( + "${CMAKE_CURRENT_BINARY_DIR}/test" + ) + + set(test_srcs + test/RxpReaderTest.cpp + ) + + set(test_deps + ${libname} + ) + + PDAL_ADD_TEST(${RXP_TEST_NAME} ${test_srcs} ${rxp_reader_lib_name}) + +endif (BUILD_RIVLIB_TESTS) diff --git a/plugins/rxp/drivers/RxpReader.cpp b/plugins/rxp/drivers/RxpReader.cpp new file mode 100644 index 0000000000..1a03142b8a --- /dev/null +++ b/plugins/rxp/drivers/RxpReader.cpp @@ -0,0 +1,397 @@ +/****************************************************************************** +* Copyright (c) 2014, Peter J. Gadomski (pete.gadomski@gmail.com) +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following +* conditions are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided +* with the distribution. +* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the +* names of its contributors may be used to endorse or promote +* products derived from this software without specific prior +* written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +* OF SUCH DAMAGE. +* +* This software has not been developed by RIEGL, and RIEGL will not provide any +* support for this driver. Please do not contact RIEGL with any questions or +* issues regarding this driver. RIEGL is not responsible for damages or other +* issues that arise from use of this driver. This driver has been tested +* against RiVLib version 1.39 on a Ubuntu 14.04 using gcc43. +****************************************************************************/ + +#include "RxpReader.hpp" + +#include + + +CREATE_READER_PLUGIN(rxp, pdal::drivers::rxp::RxpReader) + + +namespace pdal +{ +namespace drivers +{ +namespace rxp +{ + + +std::string extractRivlibURI(const Options& options) +{ + if (options.hasOption("filename")) + { + if (options.hasOption("rdtp")) + { + throw option_not_found("Cannot create URI when both filename and rdtp are provided"); + } + return "file:" + options.getValueOrThrow("filename"); + } + else + { + return "rdtp://" + options.getValueOrThrow("rdtp"); + } +} + + +Dimension::Id::Enum getTimeDimensionId(bool syncToPps) +{ + return syncToPps ? Dimension::Id::GpsTime : Dimension::Id::InternalTime; +} + + +Dimension::IdList getRxpDimensions(bool syncToPps, bool minimal) +{ + using namespace Dimension; + Dimension::IdList ids; + + ids.push_back(Id::X); + ids.push_back(Id::Y); + ids.push_back(Id::Z); + ids.push_back(getTimeDimensionId(syncToPps)); + if (!minimal) + { + ids.push_back(Id::ReturnNumber); + ids.push_back(Id::NumberOfReturns); + ids.push_back(Id::Amplitude); + ids.push_back(Id::Reflectance); + ids.push_back(Id::EchoRange); + ids.push_back(Id::Deviation); + ids.push_back(Id::BackgroundRadiation); + ids.push_back(Id::IsPpsLocked); + } + + return ids; +} + + +RotationMatrix makeRotationMatrix(float roll, float pitch) +{ + using namespace std; + return {{ + {cos(pitch), sin(roll) * sin(pitch), -cos(roll) * sin(pitch)}, + {0, cos(roll), sin(roll)}, + {sin(pitch), -sin(roll) * cos(pitch), cos(roll) * cos(pitch)} + }}; +} + + +Point rotatePoint(const Point& p, const RotationMatrix& m) +{ + return { + p.x * m[0][0] + p.y * m[0][1] + p.z * m[0][2], + p.x * m[1][0] + p.y * m[1][1] + p.z * m[1][2], + p.x * m[2][0] + p.y * m[2][1] + p.z * m[2][2] + }; +} + + +Options RxpReader::getDefaultOptions() +{ + Options options; + options.add("sync_to_pps", DEFAULT_SYNC_TO_PPS, ""); + options.add("inclination_fix", DEFAULT_INCL_FIX, ""); + options.add("minimal", DEFAULT_MINIMAL, ""); + return options; +} + + +void RxpReader::processOptions(const Options& options) +{ + m_uri = extractRivlibURI(options); + m_syncToPps = options.getValueOrDefault("sync_to_pps", + DEFAULT_SYNC_TO_PPS); + m_inclFix = options.getValueOrDefault("inclination_fix", + DEFAULT_INCL_FIX); + m_inclFixWindow = options.getValueOrDefault("inclination_fix_window", + DEFAULT_INCL_FIX_WINDOW); + m_minimal = options.getValueOrDefault("minimal", DEFAULT_MINIMAL); +} + + +void RxpReader::addDimensions(PointContext ctx) +{ + ctx.registerDims(getRxpDimensions(m_syncToPps, m_minimal)); +} + + +void RxpReader::ready(PointContext ctx) +{ + if (m_inclFix) + m_pointcloud = std::make_shared( + m_uri, m_syncToPps, m_minimal, ctx, m_inclFixWindow); + else + m_pointcloud = std::make_shared(m_uri, m_syncToPps, m_minimal, ctx); +} + + +point_count_t RxpReader::read(PointBuffer& buf, point_count_t count) +{ + point_count_t numRead = m_pointcloud->read(buf, count); + return numRead; +} + + +void RxpReader::done(PointContext ctx) +{ + m_pointcloud.reset(); +} + + +RxpPointcloud::RxpPointcloud(const std::string& uri, bool syncToPps, bool minimal, PointContext ctx) + : scanlib::pointcloud(syncToPps) + , m_buf(PointBufferPtr(new PointBuffer(ctx))) + , m_idx(0) + , m_syncToPps(syncToPps) + , m_minimal(minimal) + , m_rc(scanlib::basic_rconnection::create(uri)) + , m_dec(m_rc) +{} + + +RxpPointcloud::~RxpPointcloud() +{ + m_rc->close(); +} + + +point_count_t RxpPointcloud::read(PointBuffer& buf, point_count_t count) +{ + point_count_t numRead = 0; + + if (m_idx < m_buf->size()) + { + numRead += writeSavedPoints(buf, count); + if (numRead == count) + return numRead; + } + + for (m_dec.get(m_rxpbuf); !m_dec.eoi(); m_dec.get(m_rxpbuf)) + { + dispatch(m_rxpbuf.begin(), m_rxpbuf.end()); + if (m_buf->size() - m_idx + numRead >= count) break; + } + + numRead += writeSavedPoints(buf, count - numRead); + + return numRead; +} + + +point_count_t RxpPointcloud::writeSavedPoints(PointBuffer& buf, point_count_t count) +{ + point_count_t numRead = 0; + while (m_idx < m_buf->size() && numRead < count) + { + buf.appendPoint(*m_buf, m_idx); + ++m_idx, ++numRead; + } + return numRead; +}; + + +void RxpPointcloud::on_echo_transformed(echo_type echo) +{ + if (!(scanlib::pointcloud::single == echo || scanlib::pointcloud::last == echo)) + { + // Come back later, when we've got all the echos + return; + } + + using namespace Dimension; + + boost::uint32_t idx = m_buf->size(); + unsigned int returnNumber = 1; + for (auto t : targets) + { + m_buf->setField(Id::X, idx, t.vertex[0]); + m_buf->setField(Id::Y, idx, t.vertex[1]); + m_buf->setField(Id::Z, idx, t.vertex[2]); + m_buf->setField(getTimeDimensionId(m_syncToPps), idx, t.time); + if (!m_minimal) + { + m_buf->setField(Id::Amplitude, idx, t.amplitude); + m_buf->setField(Id::Reflectance, idx, t.reflectance); + m_buf->setField(Id::ReturnNumber, idx, returnNumber); + m_buf->setField(Id::NumberOfReturns, idx, targets.size()); + m_buf->setField(Id::EchoRange, idx, t.echo_range); + m_buf->setField(Id::Deviation, idx, t.deviation); + m_buf->setField(Id::BackgroundRadiation, idx, t.background_radiation); + m_buf->setField(Id::IsPpsLocked, idx, t.is_pps_locked); + } + ++idx, ++returnNumber; + } +} + + +RxpInclFixPointcloud::RxpInclFixPointcloud(const std::string& uri, + bool syncToPps, + bool minimal, + PointContext ctx, + InclinationVector::size_type windowSize) + : RxpPointcloud(uri, syncToPps, minimal, ctx) + , m_windowSize(windowSize) + , m_inclIdx(0) +{} + + +RxpInclFixPointcloud::~RxpInclFixPointcloud() +{} + + +point_count_t RxpInclFixPointcloud::writeSavedPoints(PointBuffer& buf, point_count_t count) +{ + using namespace Dimension; + + point_count_t numRead = 0; + auto timeDim = getTimeDimensionId(isSyncToPps()); + + // Skip all inclinations that don't have a point coming right afterwards. + // This is to prevent wonky inclination readings at the start from throwing + // off the whole game. + while (m_buf->getFieldAs(timeDim, m_idx) > m_incl[m_inclIdx + 1].time && + m_inclIdx < m_incl.size() - 2) + ++m_inclIdx; + auto firstUsableIncl = m_inclIdx; + + // Not enough inclinations to correct anything. + if (m_incl.size() < (m_windowSize * 2 + firstUsableIncl)) + { + std::ostringstream ss; + ss << "Not enough inclination readings around points. Needed " + << m_windowSize * 2 << ", got " << m_incl.size(); + throw pdal_error(ss.str()); + } + + // Skip forward until we have a full window of inclination readings. + while (m_inclIdx < m_windowSize + firstUsableIncl - 1) + ++m_inclIdx; + + // Don't write points that come before the first useful inclination + // window. + while (m_buf->getFieldAs(timeDim, m_idx) < m_incl[m_inclIdx].time) + ++m_idx; + + auto startingIncl = movingAverage(m_incl, m_inclIdx, m_windowSize); + Inclination movingAverageIncl; + auto startingIdx = m_inclIdx; + RotationMatrix mat; + + while (m_idx < m_buf->size() && numRead < count) + { + // If the next point is in the next inclination window, move along. + if (m_buf->getFieldAs(timeDim, m_idx) > m_incl[m_inclIdx + 1].time) + { + ++m_inclIdx; + if (m_inclIdx == m_incl.size() - m_windowSize) + break; + movingAverageIncl = movingAverage(m_incl, m_inclIdx, m_windowSize); + float dRoll = startingIncl.roll * 0.001 - + movingAverageIncl.roll * 0.001; + float dPitch = startingIncl.pitch * 0.001 - + movingAverageIncl.pitch * 0.001; + mat = makeRotationMatrix(dRoll * M_PI / 180, dPitch * M_PI / 180); + } + else + { + // Only bother correcting points if they're past the first + // inclination window + if (m_inclIdx > startingIdx) + { + Point p = { + m_buf->getFieldAs(Id::X, m_idx), + m_buf->getFieldAs(Id::Y, m_idx), + m_buf->getFieldAs(Id::Z, m_idx) + }; + Point pnew = rotatePoint(p, mat); + m_buf->setField(Id::X, m_idx, pnew.x); + m_buf->setField(Id::Y, m_idx, pnew.y); + m_buf->setField(Id::Z, m_idx, pnew.z); + } + buf.appendPoint(*m_buf, m_idx); + ++m_idx, ++numRead; + } + } + + return numRead; +} + + +void RxpInclFixPointcloud::on_hk_incl(const scanlib::hk_incl& incl) +{ + m_incl.push_back(Inclination{ time, incl.ROLL, incl.PITCH }); +} + + +Inclination movingAverage(const InclinationVector& incl, + InclinationVector::size_type idx, + InclinationVector::size_type halfWindowSize) +{ + auto middle = incl.begin() + idx; + double time = (incl[idx].time + incl[idx + 1].time) / 2; + long roll(0), pitch(0); + for (auto it = middle - halfWindowSize + 1; + it != middle + halfWindowSize + 1; + ++it) + { + roll += it->roll; + pitch += it->pitch; + } + try + { + return { + time, + boost::numeric_cast(roll + / (static_cast(halfWindowSize) * 2)), + boost::numeric_cast(pitch + / (static_cast(halfWindowSize) * 2)) + }; + } + catch (boost::numeric::bad_numeric_cast& e) + { + throw pdal_error("Unable to calculate inclination moving average due " + " to invalid roll or pitch value."); + } +} + + +} +} +} // namespace pdal::drivers::rxp diff --git a/plugins/rxp/drivers/RxpReader.hpp b/plugins/rxp/drivers/RxpReader.hpp new file mode 100644 index 0000000000..4d35e3bd7c --- /dev/null +++ b/plugins/rxp/drivers/RxpReader.hpp @@ -0,0 +1,184 @@ +/****************************************************************************** +* Copyright (c) 2014, Peter J. Gadomski (pete.gadomski@gmail.com) +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following +* conditions are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided +* with the distribution. +* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the +* names of its contributors may be used to endorse or promote +* products derived from this software without specific prior +* written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +* OF SUCH DAMAGE. +* +* +* This software has not been developed by RIEGL, and RIEGL will not provide any +* support for this driver. Please do not contact RIEGL with any questions or +* issues regarding this driver. RIEGL is not responsible for damages or other +* issues that arise from use of this driver. This driver has been tested +* against RiVLib version 1.39 on a Ubuntu 14.04 using gcc43. + ****************************************************************************/ + +#pragma once + +#include + +#include +#include + + + +namespace pdal +{ +namespace drivers +{ +namespace rxp +{ + + +struct Inclination +{ + double time; + int16_t roll; + int16_t pitch; +}; + +struct Point +{ + float x; + float y; + float z; +}; + +typedef std::vector InclinationVector; +typedef std::array< std::array, 3> RotationMatrix; + + +const bool DEFAULT_SYNC_TO_PPS = true; +const bool DEFAULT_MINIMAL = false; +const bool DEFAULT_INCL_FIX = false; +const InclinationVector::size_type DEFAULT_INCL_FIX_WINDOW = 100; + + +Dimension::Id::Enum getTimeDimensionId(bool syncToPps); +std::string extractRivlibURI(const Options& options); +Dimension::IdList getRxpDimensions(bool syncToPps, bool minimal); +RotationMatrix makeRotationMatrix(float roll, float pitch); +Point rotatePoint(const Point& point, const RotationMatrix& matrix); +Inclination movingAverage(const InclinationVector& incl, + InclinationVector::size_type idx, + InclinationVector::size_type halfWindowSize); + + +class PDAL_DLL RxpPointcloud : public scanlib::pointcloud +{ +public: + RxpPointcloud(const std::string& uri, bool isSyncToPps, bool m_minimal, PointContext ctx); + virtual ~RxpPointcloud(); + + point_count_t read(PointBuffer& buf, point_count_t count); + virtual point_count_t writeSavedPoints(PointBuffer& buf, point_count_t count); + + inline bool isSyncToPps() const + { + return m_syncToPps; + } + + PointBufferPtr m_buf; + point_count_t m_idx; + +protected: + void on_echo_transformed(echo_type echo); + +private: + bool m_syncToPps; + bool m_minimal; + std::shared_ptr m_rc; + scanlib::decoder_rxpmarker m_dec; + scanlib::buffer m_rxpbuf; + +}; + + +class PDAL_DLL RxpInclFixPointcloud : public RxpPointcloud +{ +public: + RxpInclFixPointcloud(const std::string& uri, bool isSyncToPps, bool minimal, + PointContext ctx, InclinationVector::size_type windowSize); + virtual ~RxpInclFixPointcloud(); + + virtual point_count_t writeSavedPoints(PointBuffer& buf, point_count_t count); + +protected: + void on_hk_incl(const scanlib::hk_incl& arg); + +private: + InclinationVector::size_type m_windowSize; + InclinationVector m_incl; + InclinationVector::size_type m_inclIdx; + +}; + + +class PDAL_DLL RxpReader : public pdal::Reader +{ +public: + SET_STAGE_NAME("drivers.rxp.reader", "RXP Reader") + SET_STAGE_LINK("http://pdal.io/stages/drivers.rxp.reader.html") + SET_STAGE_ENABLED(true) + + RxpReader() + : pdal::Reader() + , m_uri("") + , m_syncToPps(DEFAULT_SYNC_TO_PPS) + , m_inclFix(DEFAULT_INCL_FIX) + , m_inclFixWindow(DEFAULT_INCL_FIX_WINDOW) + , m_pointcloud(NULL) + {} + + static Options getDefaultOptions(); + static Dimension::IdList getDefaultDimensions() + { + return getRxpDimensions(DEFAULT_SYNC_TO_PPS, DEFAULT_MINIMAL); + } + +private: + virtual void processOptions(const Options& options); + virtual void addDimensions(PointContext ctx); + virtual void ready(PointContext ctx); + virtual point_count_t read(PointBuffer& buf, point_count_t count); + virtual void done(PointContext ctx); + + std::string m_uri; + bool m_syncToPps; + bool m_inclFix; + unsigned int m_inclFixWindow; + bool m_minimal; + std::shared_ptr m_pointcloud; + +}; + + +} +} +} // namespace pdal::drivers::rxp diff --git a/plugins/rxp/test/Config.hpp.in b/plugins/rxp/test/Config.hpp.in new file mode 100644 index 0000000000..f371116d76 --- /dev/null +++ b/plugins/rxp/test/Config.hpp.in @@ -0,0 +1,19 @@ +#pragma once + +namespace pdal +{ +namespace drivers +{ +namespace rxp +{ + + +inline std::string testDataPath() +{ + return "@CMAKE_SOURCE_DIR@/plugins/rxp/test/data/"; +} + + +} +} +} diff --git a/plugins/rxp/test/RxpReaderTest.cpp b/plugins/rxp/test/RxpReaderTest.cpp new file mode 100644 index 0000000000..8507e5d8c3 --- /dev/null +++ b/plugins/rxp/test/RxpReaderTest.cpp @@ -0,0 +1,235 @@ +/****************************************************************************** +* Copyright (c) 2014, Peter J. Gadomski (pete.gadomski@gmail.com) +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following +* conditions are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided +* with the distribution. +* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the +* names of its contributors may be used to endorse or promote +* products derived from this software without specific prior +* written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +* OF SUCH DAMAGE. +****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "../drivers/RxpReader.hpp" +#include "Config.hpp" + + +pdal::Options defaultRxpReaderOptions() +{ + pdal::Options options; + pdal::Option filename("filename", + pdal::drivers::rxp::testDataPath() + "130501_232206_cut.rxp", ""); + options.add(filename); + return options; +} + + +template +void checkDimensionClose(const pdal::PointBuffer& data, + std::size_t index, + pdal::Dimension::Id::Enum dim, + T expected) +{ + T actual = data.getFieldAs(dim, index); + BOOST_CHECK_CLOSE(expected, actual, 0.000001); +} + + +template +void checkDimensionEqual(const pdal::PointBuffer& data, + std::size_t index, + pdal::Dimension::Id::Enum dim, + T expected) +{ + T actual = data.getFieldAs(dim, index); + BOOST_CHECK_EQUAL(expected, actual); +} + + +void checkPoint(const pdal::PointBuffer& data, std::size_t index, + float x, float y, float z, + double time, double echoRange, float amplitude, + float reflectance, float deviation, + bool isPpsLocked, boost::uint8_t returnNumber, + boost::uint8_t numberOfReturns + ) +{ + using namespace pdal::Dimension; + checkDimensionClose(data, index, Id::X, x); + checkDimensionClose(data, index, Id::Y, y); + checkDimensionClose(data, index, Id::Z, z); + checkDimensionClose(data, + index, + pdal::drivers::rxp::getTimeDimensionId(isPpsLocked), + time); + checkDimensionClose(data, index, Id::EchoRange, echoRange); + checkDimensionClose(data, index, Id::Amplitude, amplitude); + checkDimensionClose(data, index, Id::Reflectance, reflectance); + checkDimensionClose(data, index, Id::Deviation, deviation); + checkDimensionEqual(data, index, Id::IsPpsLocked, isPpsLocked); + checkDimensionEqual(data, index, Id::ReturnNumber, returnNumber); + checkDimensionEqual(data, index, Id::NumberOfReturns, numberOfReturns); +} + + +BOOST_AUTO_TEST_SUITE(RxpReaderTest) + + +BOOST_AUTO_TEST_CASE(testConstructor) +{ + pdal::Options options = defaultRxpReaderOptions(); + pdal::drivers::rxp::RxpReader reader; + reader.setOptions(options); + BOOST_CHECK(reader.getDescription() == "RXP Reader"); + BOOST_CHECK_EQUAL(reader.getName(), "drivers.rxp.reader"); +} + + +BOOST_AUTO_TEST_CASE(testRead) +{ + pdal::Options options = defaultRxpReaderOptions(); + pdal::drivers::rxp::RxpReader reader; + reader.setOptions(options); + + pdal::PointContext ctx; + reader.prepare(ctx); + + pdal::PointBufferSet pbSet = reader.execute(ctx); + BOOST_CHECK_EQUAL(pbSet.size(), 1); + pdal::PointBufferPtr buf = *pbSet.begin(); + BOOST_CHECK_EQUAL(buf->size(), 177208); + + checkPoint(*buf, 0, 2.2630672454833984, -0.038407701998949051, -1.3249952793121338, 342656.34233957872, + 2.6865001276019029, 19.8699989, 5.70246553, 4, true, 1, 1); + checkPoint(*buf, 1, 2.2641847133636475, -0.038409631699323654, -1.3245694637298584, 342656.34235912003, + 2.687250127637526, 19.5299988, 5.36292124, 2, true, 1, 1); + checkPoint(*buf, 2, 2.26853346824646, -0.038410264998674393, -1.3260456323623657, 342656.34237866144, + 2.6917501278512646, 19.3699989, 5.2056551, 5, true, 1, 1); +} + + +BOOST_AUTO_TEST_CASE(testNoPpsSync) +{ + pdal::Options options = defaultRxpReaderOptions(); + pdal::Option syncToPps("sync_to_pps", "false", ""); + options.add(syncToPps); + pdal::drivers::rxp::RxpReader reader; + reader.setOptions(options); + + pdal::PointContext ctx; + reader.prepare(ctx); + + pdal::PointBufferSet pbSet = reader.execute(ctx); + pdal::PointBufferPtr buf = *pbSet.begin(); + + checkPoint(*buf, 0, 0.0705248788, -0.0417557284, 0.0304775704, 31.917255942733149, + 0.14050000667339191, 0.689999998, -14.4898596, 3, false, 1, 1); +} + + +BOOST_AUTO_TEST_CASE(testInclFix) +{ + pdal::Options options = defaultRxpReaderOptions(); + options.add("inclination_fix", "true", ""); + options.add("inclination_fix_window", "2", ""); + pdal::drivers::rxp::RxpReader reader; + reader.setOptions(options); + + pdal::PointContext ctx; + reader.prepare(ctx); + + pdal::PointBufferSet pbSet = reader.execute(ctx); + BOOST_CHECK_EQUAL(pbSet.size(), 1); + pdal::PointBufferPtr buf = *pbSet.begin(); + BOOST_CHECK_EQUAL(buf->size(), 136482); + + // TODO can we test any of the motion? Hard to say, that. +} + + + +BOOST_AUTO_TEST_CASE(testRotatePoint) +{ + using namespace pdal::drivers::rxp; + + Point p{1, 2, 3}; + + Point r1 = rotatePoint(p, makeRotationMatrix(0, 0)); + BOOST_CHECK_CLOSE(r1.x, 1, 0.001); + BOOST_CHECK_CLOSE(r1.y, 2, 0.001); + BOOST_CHECK_CLOSE(r1.z, 3, 0.001); + + Point r2 = rotatePoint(p, makeRotationMatrix(M_PI / 2, 0)); + BOOST_CHECK_CLOSE(r2.x, 1, 0.001); + BOOST_CHECK_CLOSE(r2.y, 3, 0.001); + BOOST_CHECK_CLOSE(r2.z, -2, 0.001); +} + + +BOOST_AUTO_TEST_CASE(testMovingAverage) +{ + using namespace pdal::drivers::rxp; + + InclinationVector incl; + incl.push_back(Inclination{0, 1, 2}); + incl.push_back(Inclination{2, 3, 4}); + + Inclination i1 = movingAverage(incl, 0, 1); + BOOST_CHECK_CLOSE(i1.time, 1, 0.0001); + BOOST_CHECK_EQUAL(i1.roll, 2); + BOOST_CHECK_EQUAL(i1.pitch, 3); +} + + +BOOST_AUTO_TEST_CASE(testURILogic) +{ + using namespace pdal::drivers::rxp; + + pdal::Option fileOption("filename", "foobar", ""); + pdal::Options fileOptions(fileOption); + BOOST_CHECK_EQUAL(extractRivlibURI(fileOptions), "file:foobar"); + + pdal::Option rdtpOption("rdtp", "192.168.0.33", ""); + pdal::Options rdtpOptions(rdtpOption); + BOOST_CHECK_EQUAL(extractRivlibURI(rdtpOptions), "rdtp://192.168.0.33"); + + pdal::Options emptyOptions; + BOOST_CHECK_THROW(extractRivlibURI(emptyOptions), pdal::option_not_found); + + pdal::Options bothOptions; + bothOptions.add(fileOption); + bothOptions.add(rdtpOption); + BOOST_CHECK_THROW(extractRivlibURI(bothOptions), pdal::option_not_found); +} + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/plugins/rxp/test/data/130501_232206_cut.rxp b/plugins/rxp/test/data/130501_232206_cut.rxp new file mode 100644 index 0000000000..13b0fd49b6 Binary files /dev/null and b/plugins/rxp/test/data/130501_232206_cut.rxp differ diff --git a/plugins/sqlite/CMakeLists.txt b/plugins/sqlite/CMakeLists.txt new file mode 100644 index 0000000000..2def88c3d9 --- /dev/null +++ b/plugins/sqlite/CMakeLists.txt @@ -0,0 +1,59 @@ +# +# SQLite plugin CMake configuration +# + +include_directories(${PROJECT_SOURCE_DIR}/include) +include_directories(${PROJECT_SOURCE_DIR}/plugins/sqlite) + +find_package(SQLite3) +if (SQLITE3_FOUND) + message(STATUS "Building with SQLite support") + + mark_as_advanced(CLEAR SQLITE3_INCLUDE_DIR) + mark_as_advanced(CLEAR SQLITE3_LIBRARY) + include_directories(${SQLITE3_INCLUDE_DIR}) + + # + # SQLite Reader + # + set(srcs + drivers/SQLiteReader.cpp + ) + + set(incs + drivers/SQLiteCommon.hpp + drivers/SQLiteReader.hpp + ) + + set(deps ${SQLITE3_LIBRARY}) + PDAL_ADD_PLUGIN(sqlite_reader_lib_name reader sqlite "${srcs}" "${incs}" "${deps}") + + # + # SQLite Writer + # + set(srcs + drivers/SQLiteWriter.cpp + ) + + set(incs + drivers/SQLiteCommon.hpp + drivers/SQLiteWriter.hpp + ) + + set(deps ${SQLITE3_LIBRARY}) + PDAL_ADD_PLUGIN(sqlite_writer_lib_name writer sqlite "${srcs}" "${incs}" "${deps}") + + # + # SQLite tests + # + if(BUILD_SQLITE_TESTS) + set(srcs + test/SQLiteTest.cpp + ) + + set(deps ${sqlite_reader_lib_name} ${sqlite_writer_lib_name}) + PDAL_ADD_TEST(sqlitetest "${srcs}" "${deps}") + endif() +else() + message(STATUS "Building without SQLite support") +endif() diff --git a/include/pdal/drivers/sqlite/SQLiteCommon.hpp b/plugins/sqlite/drivers/SQLiteCommon.hpp similarity index 92% rename from include/pdal/drivers/sqlite/SQLiteCommon.hpp rename to plugins/sqlite/drivers/SQLiteCommon.hpp index 3a01ff5adb..7db728729a 100644 --- a/include/pdal/drivers/sqlite/SQLiteCommon.hpp +++ b/plugins/sqlite/drivers/SQLiteCommon.hpp @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -115,17 +116,64 @@ typedef std::vector records; class Patch { public: - Patch() : count(0), remaining(0), byte_size(0), bytes(0) + Patch() : count(0), remaining(0), m_isCompressed(false), m_compVersion(""), idx(0) { }; point_count_t count; point_count_t remaining; - size_t byte_size; - std::vector bytes; pdal::schema::XMLSchema m_schema; PointContextRef m_ctx; + MetadataNode m_metadata; +// compression::CompressionStream m_compStream; + bool m_isCompressed; + std::string m_compVersion; + std::vector buf; + size_t idx; + + void putBytes(const unsigned char* b, size_t len) { + while(len --) { + buf.push_back(*b++); + } + } + + void putByte(const unsigned char b) { + buf.push_back(b); + } + + unsigned char getByte() { + return buf[idx++]; + } + + void getBytes(unsigned char *b, int len) { + for (int i = 0 ; i < len ; i ++) { + b[i] = getByte(); + } + } + + void setBytes(const std::vector& data) + { + buf = data; + } + + const std::vector& getBytes() const + { + return buf; + } + void decompress() + { + PointBufferPtr b = compression::Decompress(m_ctx, *this, count, compression::CompressionType::Lazperf); + buf = b->getBytes(); + } + + inline void compress(const PointBuffer& buffer) + { + compression::Compress(m_ctx, buffer, *this, compression::CompressionType::Lazperf, 0, buffer.size()); + } + size_t byte_size() + { return buf.size(); } + double xOffset() const { return m_schema.m_scale.m_x.m_offset; } double yOffset() const diff --git a/src/drivers/sqlite/SQLiteReader.cpp b/plugins/sqlite/drivers/SQLiteReader.cpp similarity index 77% rename from src/drivers/sqlite/SQLiteReader.cpp rename to plugins/sqlite/drivers/SQLiteReader.cpp index 209c2e0aaa..8fdd4283f6 100644 --- a/src/drivers/sqlite/SQLiteReader.cpp +++ b/plugins/sqlite/drivers/SQLiteReader.cpp @@ -32,14 +32,10 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include +#include "SQLiteReader.hpp" #include -#ifdef USE_PDAL_PLUGIN_SOCI -//MAKE_READER_CREATOR(sqliteReader, pdal::drivers::sqlite::Reader) -CREATE_READER_PLUGIN(sqliteReader, pdal::drivers::sqlite::Reader) -#endif - +CREATE_READER_PLUGIN(sqlite, pdal::drivers::sqlite::SQLiteReader) namespace pdal { @@ -115,7 +111,7 @@ pdal::SpatialReference SQLiteReader::fetchSpatialReference(std::string const& query) const { // Fetch the WKT for the SRID to set the coordinate system of this stage - log()->get(LogLevel::Debug) << "Fetching schema object" << std::endl; + log()->get(LogLevel::Debug) << "Fetching srid object" << std::endl; // ::soci::row r; // ::soci::indicator ind = ::soci::i_null; @@ -195,9 +191,23 @@ void SQLiteReader::addDimensions(PointContextRef ctx) column const& s = r->at(0); // First column is schema - m_patch->m_schema = schema::Reader(s.data).schema(); + if (m_schemaFile.size()) + { + std::ostream* out = FileUtils::createFile(m_schemaFile); + out->write(s.data.c_str(), s.data.size()); + FileUtils::closeFile(out); + } + + schema::Reader reader(s.data); + + m_patch->m_metadata = reader.getMetadata(); + m_patch->m_schema = reader.schema(); m_patch->m_ctx = ctx; + ctx.registerDim(Dimension::Id::X); + ctx.registerDim(Dimension::Id::Y); + ctx.registerDim(Dimension::Id::Z); + schema::DimInfoList& dims = m_patch->m_schema.m_dims; for (auto di = dims.begin(); di != dims.end(); ++di) di->m_id = ctx.registerOrAssignDim(di->m_name, di->m_type); @@ -234,23 +244,58 @@ point_count_t SQLiteReader::readPatch(PointBuffer& buffer, point_count_t numPts) // Availability of positions already validated int32_t position = columns.find("POINTS")->second; - auto bytes = (*r)[position].blobBuf; - size_t size = (*r)[position].blobLen; + + MetadataNode comp = m_patch->m_metadata.findChild("compression"); + m_patch->m_isCompressed = boost::iequals(comp.value(), "lazperf"); + m_patch->m_compVersion = m_patch->m_metadata.findChild("version").value(); + position = columns.find("NUM_POINTS")->second; int32_t count = boost::lexical_cast((*r)[position].data); - log()->get(LogLevel::Debug4) << "fetched patch with " << count << - " points and " << size << " bytes bytesize: " << size << std::endl; m_patch->remaining = count; m_patch->count = count; - m_patch->bytes = bytes; - m_patch->byte_size = size; + + + log()->get(LogLevel::Debug3) << "patch compression? " + << m_patch->m_isCompressed << std::endl; + + if (m_patch->m_isCompressed) + log()->get(LogLevel::Debug3) << "patch compression version: " + << m_patch->m_compVersion << std::endl; + + position = columns.find("POINTS")->second; + const uint8_t* bytes(0); + + size_t size (0); + if (m_patch->m_isCompressed) + { + m_patch->setBytes((*r)[position].blobBuf); + log()->get(LogLevel::Debug3) << "Compressed byte size: " + << m_patch->getBytes().size() << std::endl; + m_patch->decompress(); + bytes = &(m_patch->getBytes()[0]); + size = m_patch->getBytes().size(); + if (!size) + throw pdal_error("Compressed patch size was 0!"); + log()->get(LogLevel::Debug3) << "Uncompressed byte size: " << size << std::endl; + + } else + { + bytes = &((*r)[position].blobBuf[0]); + size = (*r)[position].blobLen; + } + + log()->get(LogLevel::Debug4) << "fetched patch with " + << count << " points and " + << m_patch->getBytes().size() + << " bytes size: " << size << std::endl; + point_count_t numRemaining = m_patch->remaining; PointId nextId = buffer.size(); point_count_t numRead = 0; size_t offset = ((m_patch->count - m_patch->remaining) * m_point_size); - uint8_t *pos = &(m_patch->bytes.front()) + offset; + uint8_t const* pos = bytes + offset; schema::DimInfoList& dims = m_patch->m_schema.m_dims; while (numRead < numPts && numRemaining > 0) @@ -263,17 +308,17 @@ point_count_t SQLiteReader::readPatch(PointBuffer& buffer, point_count_t numPts) } // Scale X, Y and Z - // double v = buffer.getFieldAs(Dimension::Id::X, nextId); - // v = v * m_patch->xScale() + m_patch->xOffset(); - // buffer.setField(Dimension::Id::X, nextId, v); - // - // v = buffer.getFieldAs(Dimension::Id::Y, nextId); - // v = v * m_patch->yScale() + m_patch->yOffset(); - // buffer.setField(Dimension::Id::Y, nextId, v); - // - // v = buffer.getFieldAs(Dimension::Id::Z, nextId); - // v = v * m_patch->zScale() + m_patch->zOffset(); - // buffer.setField(Dimension::Id::Z, nextId, v); + double v = buffer.getFieldAs(Dimension::Id::X, nextId); + v = v * m_patch->xScale() + m_patch->xOffset(); + buffer.setField(Dimension::Id::X, nextId, v); + + v = buffer.getFieldAs(Dimension::Id::Y, nextId); + v = v * m_patch->yScale() + m_patch->yOffset(); + buffer.setField(Dimension::Id::Y, nextId, v); + + v = buffer.getFieldAs(Dimension::Id::Z, nextId); + v = v * m_patch->zScale() + m_patch->zOffset(); + buffer.setField(Dimension::Id::Z, nextId, v); numRemaining--; nextId++; @@ -281,7 +326,7 @@ point_count_t SQLiteReader::readPatch(PointBuffer& buffer, point_count_t numPts) } m_patch->remaining = numRemaining; - +// std::cout << buffer << std::endl; return numRead; } diff --git a/include/pdal/drivers/sqlite/SQLiteReader.hpp b/plugins/sqlite/drivers/SQLiteReader.hpp similarity index 96% rename from include/pdal/drivers/sqlite/SQLiteReader.hpp rename to plugins/sqlite/drivers/SQLiteReader.hpp index 4d31cf3287..c37c38be3a 100644 --- a/include/pdal/drivers/sqlite/SQLiteReader.hpp +++ b/plugins/sqlite/drivers/SQLiteReader.hpp @@ -35,9 +35,10 @@ #pragma once #include +#include #include -#include +#include "SQLiteCommon.hpp" #include @@ -52,11 +53,7 @@ class PDAL_DLL SQLiteReader : public pdal::Reader { public: SET_STAGE_NAME("drivers.sqlite.reader", "SQLite3 Reader") -#ifdef PDAL_HAVE_SQLITE SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif SQLiteReader(); static Options getDefaultOptions(); diff --git a/src/drivers/sqlite/SQLiteWriter.cpp b/plugins/sqlite/drivers/SQLiteWriter.cpp similarity index 88% rename from src/drivers/sqlite/SQLiteWriter.cpp rename to plugins/sqlite/drivers/SQLiteWriter.cpp index 416bd8ed50..d7a8c7c544 100644 --- a/src/drivers/sqlite/SQLiteWriter.cpp +++ b/plugins/sqlite/drivers/SQLiteWriter.cpp @@ -32,23 +32,21 @@ * OF SUCH DAMAGE. ****************************************************************************/ -#include +#include "SQLiteWriter.hpp" #include +#include #include #include #include +#include #include #include #include -#ifdef USE_PDAL_PLUGIN_SQLITE -//MAKE_WRITER_CREATOR(sqliteWriter, pdal::drivers::sqlite::Writer) -CREATE_WRITER_PLUGIN(sqliteWriter, pdal::drivers::sqlite::Writer) -#endif - +CREATE_WRITER_PLUGIN(sqlite, pdal::drivers::sqlite::SQLiteWriter) namespace pdal { @@ -69,6 +67,7 @@ SQLiteWriter::SQLiteWriter() , m_pointSize(0) , m_orientation(Orientation::PointMajor) , m_is3d(false) + , m_doCompression(false) {} void SQLiteWriter::processOptions(const Options& options) @@ -95,6 +94,7 @@ void SQLiteWriter::processOptions(const Options& options) m_srid = m_options.getValueOrDefault("srid", 4326); m_is3d = m_options.getValueOrDefault("is3d", false); + m_doCompression = m_options.getValueOrDefault("compression", false); } @@ -124,10 +124,13 @@ void SQLiteWriter::initialize() oss << "Unable to connect to database with error '" << e.what() << "'"; throw pdal_error(oss.str()); } + + m_patch = PatchPtr(new Patch()); } void SQLiteWriter::ready(PointContextRef ctx) { + m_context = ctx; m_dims = ctx.dims(); // Determine types for the dimensions. We use the default types when // they exist, float otherwise. @@ -139,6 +142,7 @@ void SQLiteWriter::ready(PointContextRef ctx) m_types.push_back(type); m_pointSize += Dimension::size(type); } + m_patch->m_ctx = ctx; } void SQLiteWriter::write(const PointBuffer& buffer) @@ -453,6 +457,16 @@ void SQLiteWriter::CreateCloud() boost::to_lower_copy(m_block_table) << "',?) "; schema::Writer writer(m_dims, m_types); + pdal::Metadata metadata; + if (m_doCompression) + { + + Metadata metadata; + MetadataNode m = metadata.getNode(); + m.add("compression", "lazperf"); + m.add("version", "1.0"); + writer.setMetadata(m); + } std::string xml = writer.getXML(); records rs; @@ -497,66 +511,6 @@ void SQLiteWriter::CreateCloud() } -namespace -{ - -void fillBuf(const PointBuffer& buf, char *pos, Dimension::Id::Enum d, - Dimension::Type::Enum type, PointId id) -{ - union - { - float f; - double d; - int8_t s8; - int16_t s16; - int32_t s32; - int64_t s64; - uint8_t u8; - uint16_t u16; - uint32_t u32; - uint64_t u64; - } e; // e - for Everything. - - switch (type) - { - case Dimension::Type::Float: - e.f = buf.getFieldAs(d, id); - break; - case Dimension::Type::Double: - e.d = buf.getFieldAs(d, id); - break; - case Dimension::Type::Signed8: - e.s8 = buf.getFieldAs(d, id); - break; - case Dimension::Type::Signed16: - e.s16 = buf.getFieldAs(d, id); - break; - case Dimension::Type::Signed32: - e.s32 = buf.getFieldAs(d, id); - break; - case Dimension::Type::Signed64: - e.s64 = buf.getFieldAs(d, id); - break; - case Dimension::Type::Unsigned8: - e.u8 = buf.getFieldAs(d, id); - break; - case Dimension::Type::Unsigned16: - e.u16 = buf.getFieldAs(d, id); - break; - case Dimension::Type::Unsigned32: - e.u32 = buf.getFieldAs(d, id); - break; - case Dimension::Type::Unsigned64: - e.u64 = buf.getFieldAs(d, id); - break; - case Dimension::Type::None: - break; - } - memcpy(pos, &e, Dimension::size(type)); -} - -} // anonymous namespace. - void SQLiteWriter::writeTile(PointBuffer const& buffer) { using namespace std; @@ -565,20 +519,30 @@ void SQLiteWriter::writeTile(PointBuffer const& buffer) boost::uint32_t point_data_length(0); boost::uint32_t schema_byte_size(0); - size_t outbufSize = m_pointSize * buffer.size(); - std::unique_ptr outbuf(new char[outbufSize]); - char *pos = outbuf.get(); + size_t bufferSize = buffer.size() * m_context.pointSize(); - for (PointId id = 0; id < buffer.size(); ++id) + if (m_doCompression) { - auto ti = m_types.begin(); - for (auto di = m_dims.begin(); di != m_dims.end(); ++di, ++ti) - { - fillBuf(buffer, pos, *di, *ti, id); - pos += Dimension::size(*ti); - } - if (id % 100 == 0) - m_callback->invoke(id); + m_patch->compress(buffer); + + size_t newSize = m_patch->getBytes().size(); + double percent = (double) newSize/(double) bufferSize; + percent = percent * 100; + log()->get(LogLevel::Debug3) << "Compressing tile by " + << boost::str(boost::format("%.2f") % (100- percent)) + <<"%" << std::endl; + } + else + { + std::vector bytes; + bytes.resize(bufferSize); + Charbuf charstreambuf((char*)&bytes[0], bufferSize, 0); + std::ostream o(&charstreambuf); + buffer.getBytes(o, 0, buffer.size()); + + log()->get(LogLevel::Debug3) << "uncompressed size: " << bytes.size() << std::endl; + m_patch->setBytes(bytes); + log()->get(LogLevel::Debug3) << "uncompressed size: " << m_patch->getBytes().size() << std::endl; } records rs; @@ -595,7 +559,7 @@ void SQLiteWriter::writeTile(PointBuffer const& buffer) r.push_back(column(m_obj_id)); r.push_back(column(m_block_id)); r.push_back(column(buffer.size())); - r.push_back(blob(outbuf.get(), outbufSize)); + r.push_back(blob((const char*)(&m_patch->getBytes()[0]), m_patch->getBytes().size())); r.push_back(column(bounds)); r.push_back(column(m_srid)); r.push_back(column(box)); diff --git a/include/pdal/drivers/sqlite/SQLiteWriter.hpp b/plugins/sqlite/drivers/SQLiteWriter.hpp similarity index 95% rename from include/pdal/drivers/sqlite/SQLiteWriter.hpp rename to plugins/sqlite/drivers/SQLiteWriter.hpp index 102a61d1c0..e1e9f5881f 100644 --- a/include/pdal/drivers/sqlite/SQLiteWriter.hpp +++ b/plugins/sqlite/drivers/SQLiteWriter.hpp @@ -35,8 +35,9 @@ #pragma once #include -#include -#include +#include +#include +#include "SQLiteCommon.hpp" namespace pdal { @@ -50,11 +51,7 @@ class PDAL_DLL SQLiteWriter : public pdal::Writer { public: SET_STAGE_NAME("drivers.sqlite.writer", "SQLite Writer") -#ifdef PDAL_HAVE_SQLITE SET_STAGE_ENABLED(true) -#else - SET_STAGE_ENABLED(false) -#endif SQLiteWriter(); private: @@ -104,6 +101,9 @@ class PDAL_DLL SQLiteWriter : public pdal::Writer std::string m_connection; std::string m_modulename; bool m_is3d; + bool m_doCompression;; + PatchPtr m_patch; + PointContextRef m_context; }; diff --git a/test/unit/drivers/sqlite/SQLiteTest.cpp b/plugins/sqlite/test/SQLiteTest.cpp similarity index 68% rename from test/unit/drivers/sqlite/SQLiteTest.cpp rename to plugins/sqlite/test/SQLiteTest.cpp index e2c1d63be0..0aae374b5e 100644 --- a/test/unit/drivers/sqlite/SQLiteTest.cpp +++ b/plugins/sqlite/test/SQLiteTest.cpp @@ -40,8 +40,7 @@ #include #include -#include -#include +#include #include #include #include @@ -72,10 +71,10 @@ Options getSQLITEOptions() options.add(connection); Option debug("debug", true, "debug"); - // options.add(debug); + options.add(debug); Option verbose("verbose", 7, "verbose"); - // options.add(verbose); + options.add(verbose); Option block_table_name("block_table_name", "PDAL_TEST_BLOCKS", "block_table_name"); options.add(block_table_name); @@ -116,8 +115,8 @@ Options getSQLITEOptions() Option cloud_column("cloud_column_name", "CLOUD", ""); options.add(cloud_column); - // Option xml_schema_dump("xml_schema_dump", "sqlite-xml-schema-dump.xml", ""); - // options.add(xml_schema_dump); + Option xml_schema_dump("xml_schema_dump", "sqlite-xml-schema-dump.xml", ""); + options.add(xml_schema_dump); Option con_type("type", "sqlite", ""); options.add(con_type); @@ -149,7 +148,6 @@ BOOST_FIXTURE_TEST_SUITE(SQLiteTest, SQLiteTestFixture) BOOST_AUTO_TEST_CASE(SqliteTest_test_simple_las) { -#ifdef PDAL_HAVE_SQLITE // remove file from earlier run, if needed std::string temp_filename = getSQLITEOptions().getValueOrThrow("connection"); Options ops1; @@ -157,42 +155,66 @@ BOOST_AUTO_TEST_CASE(SqliteTest_test_simple_las) drivers::las::Reader reader; reader.setOptions(ops1); - { - pdal::drivers::las::Reader writer_reader; - writer_reader.setOptions(getSQLITEOptions()); - pdal::drivers::sqlite::SQLiteWriter writer_writer; - writer_writer.setOptions(getSQLITEOptions()); - writer_writer.setInput(&writer_reader); - - PointContext ctx; - writer_writer.prepare(ctx); - boost::uint64_t numPointsToRead = writer_reader.getNumPoints(); + Options sqliteOptions = getSQLITEOptions(); - BOOST_CHECK_EQUAL(numPointsToRead, 1065u); +#ifdef PDAL_HAVE_LAZPERF + Option compression("compression", true, ""); + sqliteOptions.add(compression); +#endif - writer_writer.execute(ctx); + StageFactory f; + StageFactory::WriterCreator* wc = f.getWriterCreator("drivers.sqlite.writer"); + StageFactory::ReaderCreator* rc = f.getReaderCreator("drivers.sqlite.reader"); + if (wc) + { + BOOST_CHECK(wc); + BOOST_CHECK(rc); + + // remove file from earlier run, if needed + std::string temp_filename = getSQLITEOptions().getValueOrThrow("connection"); + Options ops1; + ops1.add("filename", Support::datapath("las/1.2-with-color.las")); + drivers::las::Reader reader; + reader.setOptions(ops1); + + { + pdal::drivers::las::Reader writer_reader; + writer_reader.setOptions(getSQLITEOptions()); + std::unique_ptr writer_writer(wc()); + writer_writer->setOptions(getSQLITEOptions()); + writer_writer->setInput(&writer_reader); + + PointContext ctx; + writer_writer->prepare(ctx); + boost::uint64_t numPointsToRead = writer_reader.getNumPoints(); + + BOOST_CHECK_EQUAL(numPointsToRead, 1065u); + + writer_writer->execute(ctx); + } + + { + // Read the data + +// pdal::drivers::sqlite::SQLiteReader reader; + std::unique_ptr reader(rc()); + reader->setOptions(getSQLITEOptions()); + PointContext ctx; + reader->prepare(ctx); + + PointBufferSet pbSet = reader->execute(ctx); + BOOST_CHECK_EQUAL(pbSet.size(), 1); + + PointBufferPtr buffer = *pbSet.begin(); + + boost::uint16_t r = buffer->getFieldAs(Dimension::Id::Red, 10); + BOOST_CHECK_EQUAL(r, 64u); + boost::int32_t x = buffer->getFieldAs(Dimension::Id::X, 10); + BOOST_CHECK_EQUAL(x, 636038); + double xd = buffer->getFieldAs(Dimension::Id::X, 10); + BOOST_CHECK_CLOSE(xd, 636037.53, 0.001); + } } - -// { -// // Read the data -// -// pdal::drivers::sqlite::SQLiteReader reader(getSQLITEOptions()); -// PointContext ctx; -// reader.prepare(ctx); -// PointBuffer buffer(ctx); -// -// PointBufferSet pbSet = reader.execute(ctx); -// BOOST_CHECK_EQUAL(pbSet.size(), 1); -// -// boost::uint16_t r = buffer.getFieldAs(Dimension::Id::Red, 0); -// BOOST_CHECK_EQUAL(r, 68u); -// boost::int32_t x = buffer.getFieldAs(Dimension::Id::X, 0); -// BOOST_CHECK_EQUAL(x, 637012); -// double xd = buffer.getFieldAs(Dimension::Id::X, 0); -// BOOST_CHECK_CLOSE(xd, 637012.240, 0.001); -// } - // FileUtils::deleteFile(temp_filename); -#endif } diff --git a/scripts/ci/before_install.sh b/scripts/ci/before_install.sh index 89c70bd09e..7946b61b14 100755 --- a/scripts/ci/before_install.sh +++ b/scripts/ci/before_install.sh @@ -12,12 +12,14 @@ sudo apt-get install python-software-properties -y sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable -y sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y sudo add-apt-repository ppa:boost-latest/ppa -y +sudo add-apt-repository ppa:kalakris/cmake -y sudo apt-get update -qq # Install g++-4.8 (even if we're building clang) for updated libstdc++ sudo apt-get install g++-4.8 sudo apt-get install boost1.55 +sudo apt-get install cmake if [[ $PDAL_CMAKE_GENERATOR == "Ninja" ]] then diff --git a/scripts/ci/script.sh b/scripts/ci/script.sh index 1768de183b..1ed762ee98 100755 --- a/scripts/ci/script.sh +++ b/scripts/ci/script.sh @@ -8,15 +8,9 @@ cd _build || exit 1 case "$PDAL_OPTIONAL_COMPONENTS" in all) OPTIONAL_COMPONENT_SWITCH=ON - STUBS_SWITCH=OFF ;; -# stubs_only) -# OPTIONAL_COMPONENT_SWITCH=OFF -# STUBS_SWITCH=ON -# ;; none) OPTIONAL_COMPONENT_SWITCH=OFF - STUBS_SWITCH=OFF ;; *) echo "Unrecognized value for PDAL_OPTIONAL_COMPONENTS=$PDAL_OPTIONAL_COMPONENTS" @@ -29,21 +23,20 @@ then fi cmake \ + -DBUILD_PLUGIN_ICEBRIDGE=OFF \ + -DBUILD_PLUGIN_NITF=OFF \ + -DBUILD_PLUGIN_OCI=$OPTIONAL_COMPONENT_SWITCH \ + -DBUILD_PLUGIN_PGPOINTCLOUD=OFF\ + -DBUILD_PLUGIN_SQLITE=OFF \ + -DENABLE_CTEST=OFF \ -DWITH_APPS=ON \ - -DWITH_TESTS=ON \ - -DWITH_PKGCONFIG=ON \ + -DWITH_CARIS=OFF \ -DWITH_GEOTIFF=$OPTIONAL_COMPONENT_SWITCH \ - -DWITH_ORACLE=$OPTIONAL_COMPONENT_SWITCH \ -DWITH_ICONV=$OPTIONAL_COMPONENT_SWITCH \ -DWITH_LASZIP=$OPTIONAL_COMPONENT_SWITCH \ - -DWITH_NITRO=$OPTIONAL_COMPONENT_SWITCH \ - -DWITH_PGPOINTCLOUD=OFF\ + -DWITH_PKGCONFIG=ON \ -DWITH_PYTHON=$OPTIONAL_COMPONENT_SWITCH \ - -DWITH_CARIS=OFF \ - -DWITH_SQLITE=OFF \ - -DENABLE_CTEST=OFF \ - -DWITH_HDF5=OFF \ - -DWITH_STUBS=$STUBS_SWITCH \ + -DWITH_TESTS=ON \ -G "$PDAL_CMAKE_GENERATOR" \ .. diff --git a/scripts/vagrant/pcl.sh b/scripts/vagrant/pcl.sh index b5f09a0c2f..586bc02daa 100755 --- a/scripts/vagrant/pcl.sh +++ b/scripts/vagrant/pcl.sh @@ -7,11 +7,12 @@ fi export NUMTHREADS -git clone https://github.com/chambbj/pcl.git pcl +git clone https://github.com/PointCloudLibrary/pcl.git cd pcl mkdir build cd build -git checkout pipeline +git fetch origin --tags +git checkout tags/pcl-1.7.2 cmake .. \ -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE=Release \ @@ -23,7 +24,7 @@ cmake .. \ -DWITH_CUDA:BOOL=OFF \ -DWITH_LIBUSB:BOOL=OFF \ -DBUILD_people:BOOL=OFF \ - -DBUILD_surface:BOOL=OFF \ + -DBUILD_surface:BOOL=ON \ -DBUILD_tools:BOOL=OFF \ -DBUILD_visualization:BOOL=OFF \ -DBUILD_sample_consensus:BOOL=ON \ diff --git a/scripts/vagrant/pdal.sh b/scripts/vagrant/pdal.sh index f260a1a9d1..9f4e690dc9 100755 --- a/scripts/vagrant/pdal.sh +++ b/scripts/vagrant/pdal.sh @@ -14,7 +14,7 @@ cd build cmake -G "Unix Makefiles" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ - -DWITH_PCL=ON \ + -DBUILD_PLUGIN_PCL=ON \ .. make -j $NUMTHREADS diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5aae0fc765..a6ae56f441 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ set(PDAL_BASE_HPP "${PDAL_HEADERS_DIR}/pdal_types.hpp" "${PDAL_HEADERS_DIR}/Bounds.hpp" "${PDAL_HEADERS_DIR}/Charbuf.hpp" + "${PDAL_HEADERS_DIR}/Compression.hpp" "${PDAL_HEADERS_DIR}/Dimension.hpp" "${PDAL_HEADERS_DIR}/Drivers.hpp" "${PDAL_HEADERS_DIR}/FileUtils.hpp" @@ -105,6 +106,7 @@ set(PDAL_BASE_CPP Writer.cpp third/md5-pdal.c ${PDAL_XML_SRC} + ${PDAL_LAZPERF_SRC} ${PDAL_KERNEL_SRC}/Kernel.cpp ${PDAL_KERNEL_SRC}/KernelFactory.cpp ${PDAL_KERNEL_SRC}/KernelInfo.cpp @@ -199,26 +201,6 @@ list (APPEND PDAL_CPP ${PDAL_DRIVERS_BPF_CPP} ) list (APPEND PDAL_HPP ${PDAL_DRIVERS_BPF_HPP} ) -# -# drivers/mrsid -# -set(PDAL_MRSID_PATH drivers/mrsid) -set(PDAL_MRSID_HEADERS "${PDAL_HEADERS_DIR}/${PDAL_MRSID_PATH}") -set(PDAL_MRSID_SRC "${PROJECT_SOURCE_DIR}/src/${PDAL_MRSID_PATH}") - -set(PDAL_DRIVERS_MRSID_HPP - "${PDAL_MRSID_HEADERS}/Reader.hpp" -) - -set (PDAL_DRIVERS_MRSID_CPP - "${PDAL_MRSID_SRC}/Reader.cpp" -) - -if (MRSID_FOUND) - list (APPEND PDAL_CPP ${PDAL_DRIVERS_MRSID_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_MRSID_HPP} ) -endif() - # # drivers/caris @@ -247,35 +229,6 @@ if (CARIS_FOUND) endif() -# -# drivers/oci -# -set(PDAL_ORACLE_PATH drivers/oci) -set(PDAL_ORACLE_HEADERS "${PDAL_HEADERS_DIR}/${PDAL_ORACLE_PATH}") -set(PDAL_ORACLE_SRC "${PROJECT_SOURCE_DIR}/src/${PDAL_ORACLE_PATH}") - -set(PDAL_DRIVERS_OCI_HPP - "${PDAL_ORACLE_HEADERS}/Writer.hpp" - "${PDAL_ORACLE_HEADERS}/OciReader.hpp" - "${PDAL_ORACLE_HEADERS}/oci_wrapper.h" - "${PDAL_ORACLE_HEADERS}/common.hpp" -) - -set (PDAL_DRIVERS_OCI_CPP - "${PDAL_ORACLE_SRC}/oci_wrapper.cpp" - "${PDAL_ORACLE_SRC}/common.cpp" - "${PDAL_ORACLE_SRC}/OciReader.cpp" - "${PDAL_ORACLE_SRC}/Writer.cpp" -) - -if (ORACLE_FOUND) -if (NOT USE_PDAL_PLUGIN_OCI) - list (APPEND PDAL_CPP ${PDAL_DRIVERS_OCI_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_OCI_HPP} ) -endif() -endif() - - # # drivers/qfit # @@ -312,25 +265,6 @@ set (PDAL_DRIVERS_TERRASOLID_CPP list (APPEND PDAL_CPP ${PDAL_DRIVERS_TERRASOLID_CPP} ) list (APPEND PDAL_HPP ${PDAL_DRIVERS_TERRASOLID_HPP} ) -# -# drivers/p2g -# -set(PDAL_P2G_PATH drivers/p2g) -set(PDAL_P2G_HEADERS "${PDAL_HEADERS_DIR}/${PDAL_P2G_PATH}") -set(PDAL_P2G_SRC "${PROJECT_SOURCE_DIR}/src/${PDAL_P2G_PATH}") - -set(PDAL_DRIVERS_P2G_HPP - "${PDAL_P2G_HEADERS}/P2gWriter.hpp" -) - -set (PDAL_DRIVERS_P2G_CPP - "${PDAL_P2G_SRC}/P2gWriter.cpp" -) - -if (P2G_FOUND) - list (APPEND PDAL_CPP ${PDAL_DRIVERS_P2G_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_P2G_HPP} ) -endif() # # drivers/text @@ -347,105 +281,8 @@ set (PDAL_DRIVERS_TEXT_CPP ${PDAL_TEXT_SRC}/Writer.cpp ) -if (NOT USE_PDAL_PLUGIN_TEXT) - list (APPEND PDAL_CPP ${PDAL_DRIVERS_TEXT_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_TEXT_HPP} ) -endif() - -# -# drivers/nitf -# -set(PDAL_NITF_PATH drivers/nitf) -set(PDAL_NITF_HEADERS "${PDAL_HEADERS_DIR}/${PDAL_NITF_PATH}") -set(PDAL_NITF_SRC "${PROJECT_SOURCE_DIR}/src/${PDAL_NITF_PATH}") - -set(PDAL_DRIVERS_NITF_READER_HPP - "${PDAL_NITF_SRC}/MetadataReader.hpp" - "${PDAL_NITF_SRC}/NitfFile.hpp" - "${PDAL_NITF_HEADERS}/Reader.hpp" - "${PDAL_NITF_SRC}/tre_plugins.hpp" -) - -set (PDAL_DRIVERS_NITF_READER_CPP - "${PDAL_NITF_SRC}/MetadataReader.cpp" - "${PDAL_NITF_SRC}/NitfFile.cpp" - "${PDAL_NITF_SRC}/Reader.cpp" - "${PDAL_NITF_SRC}/tre_plugins.cpp" -) - -if (NITRO_FOUND) - list (APPEND PDAL_CPP ${PDAL_DRIVERS_NITF_READER_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_NITF_READER_HPP} ) -endif() - -set(PDAL_DRIVERS_NITF_WRITER_HPP - "${PDAL_NITF_HEADERS}/Writer.hpp" -) - -set (PDAL_DRIVERS_NITF_WRITER_CPP - "${PDAL_NITF_SRC}/Writer.cpp" -) - -if (NITRO_FOUND) - list (APPEND PDAL_CPP ${PDAL_DRIVERS_NITF_WRITER_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_NITF_WRITER_HPP} ) -endif() - - -# -# drivers/sqlite -# -set(PDAL_SQLITE_PATH drivers/sqlite) -set(PDAL_SQLITE_HEADERS "${PDAL_HEADERS_DIR}/${PDAL_SQLITE_PATH}") -set(PDAL_SQLITE_SRC "${PROJECT_SOURCE_DIR}/src/${PDAL_SQLITE_PATH}") - -set(PDAL_DRIVERS_SQLITE_HPP - "${PDAL_SQLITE_HEADERS}/SQLiteCommon.hpp" - "${PDAL_SQLITE_HEADERS}/SQLiteReader.hpp" - "${PDAL_SQLITE_HEADERS}/SQLiteWriter.hpp" -) - -set (PDAL_DRIVERS_SQLITE_CPP - "${PDAL_SQLITE_SRC}/SQLiteReader.cpp" - "${PDAL_SQLITE_SRC}/SQLiteWriter.cpp" -) - -if (WITH_SQLITE) - if (NOT USE_PDAL_PLUGIN_SQLITE) - list (APPEND PDAL_CPP ${PDAL_DRIVERS_SQLITE_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_SQLITE_HPP} ) - endif() -endif() - - -# -# drivers/pgpointcloud -# we require PostgreSQL -# -set(PDAL_PGPOINTCLOUD_PATH drivers/pgpointcloud) -set(PDAL_PGPOINTCLOUD_HEADERS "${PDAL_HEADERS_DIR}/${PDAL_PGPOINTCLOUD_PATH}") -set(PDAL_PGPOINTCLOUD_SRC "${PROJECT_SOURCE_DIR}/src/${PDAL_PGPOINTCLOUD_PATH}") - -set(PDAL_DRIVERS_PGPOINTCLOUD_HPP - "${PDAL_PGPOINTCLOUD_HEADERS}/common.hpp" - "${PDAL_PGPOINTCLOUD_HEADERS}/Writer.hpp" - "${PDAL_PGPOINTCLOUD_HEADERS}/PgReader.hpp" -) - -set (PDAL_DRIVERS_PGPOINTCLOUD_CPP - "${PDAL_PGPOINTCLOUD_SRC}/Writer.cpp" - "${PDAL_PGPOINTCLOUD_SRC}/PgReader.cpp" -) - -# no provision is made for building as a plugin -if (POSTGRESQL_FOUND) - if ( USE_PDAL_PLUGIN_PGPOINTCLOUD ) - message(FATAL_ERROR, "PgPointCloud plugin support unimplemented") - else() - list (APPEND PDAL_CPP ${PDAL_DRIVERS_PGPOINTCLOUD_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_PGPOINTCLOUD_HPP} ) - endif() -endif() +list (APPEND PDAL_CPP ${PDAL_DRIVERS_TEXT_CPP} ) +list (APPEND PDAL_HPP ${PDAL_DRIVERS_TEXT_HPP} ) # @@ -470,43 +307,6 @@ set (PDAL_DRIVERS_SBET_CPP list (APPEND PDAL_CPP ${PDAL_DRIVERS_SBET_CPP} ) list (APPEND PDAL_HPP ${PDAL_DRIVERS_SBET_HPP} ) -# -# HDF5 -# -set(PDAL_HDF5_HANDLER_HPP - "${PDAL_HEADERS_DIR}/Hdf5Handler.hpp" -) - -set(PDAL_HDF5_HANDLER_CPP - "${PDAL_SOURCE_DIR}/src/Hdf5Handler.cpp" -) - -if (HDF5_FOUND) - list (APPEND PDAL_CPP ${PDAL_HDF5_HANDLER_CPP}) - list (APPEND PDAL_HPP ${PDAL_HDF5_HANDLER_HPP}) -endif() - - -# -# drivers/icebridge -# -set(PDAL_ICEBRIDGE_PATH drivers/icebridge) -set(PDAL_ICEBRIDGE_HEADERS "${PDAL_HEADERS_DIR}/${PDAL_ICEBRIDGE_PATH}") -set(PDAL_ICEBRIDGE_SRC "${PROJECT_SOURCE_DIR}/src/${PDAL_ICEBRIDGE_PATH}") - -set(PDAL_DRIVERS_ICEBRIDGE_HPP - "${PDAL_ICEBRIDGE_HEADERS}/Reader.hpp" -) - -set(PDAL_DRIVERS_ICEBRIDGE_CPP - "${PDAL_ICEBRIDGE_SRC}/Reader.cpp" -) - -if (HDF5_FOUND) - list (APPEND PDAL_CPP ${PDAL_DRIVERS_ICEBRIDGE_CPP} ) - list (APPEND PDAL_HPP ${PDAL_DRIVERS_ICEBRIDGE_HPP} ) -endif() - # # filters @@ -523,7 +323,6 @@ set(PDAL_FILTERS_HPP "${PDAL_FILTERS_HEADERS}/Crop.hpp" "${PDAL_FILTERS_HEADERS}/Decimation.hpp" "${PDAL_FILTERS_HEADERS}/Ferry.hpp" - "${PDAL_FILTERS_HEADERS}/HexBin.hpp" "${PDAL_FILTERS_HEADERS}/InPlaceReprojection.hpp" "${PDAL_FILTERS_HEADERS}/Merge.hpp" "${PDAL_FILTERS_HEADERS}/MortonOrder.hpp" @@ -540,7 +339,6 @@ set (PDAL_FILTERS_CPP "${PDAL_FILTERS_SRC}/Crop.cpp" "${PDAL_FILTERS_SRC}/Decimation.cpp" "${PDAL_FILTERS_SRC}/Ferry.cpp" - "${PDAL_FILTERS_SRC}/HexBin.cpp" "${PDAL_FILTERS_SRC}/MortonOrder.cpp" "${PDAL_FILTERS_SRC}/Reprojection.cpp" "${PDAL_FILTERS_SRC}/Splitter.cpp" @@ -666,13 +464,10 @@ source_group("Header Files\\config" FILES ${PDAL_CONFIG_HPP}) source_group("Header Files\\drivers\\faux" FILES ${PDAL_DRIVERS_FAUX_HPP}) source_group("Header Files\\drivers\\caris" FILES ${PDAL_DRIVERS_CARIS_HPP}) source_group("Header Files\\drivers\\las" FILES ${PDAL_DRIVERS_LAS_HPP}) -source_group("Header Files\\drivers\\nitf" FILES ${PDAL_DRIVERS_NITF_HPP}) -source_group("Header Files\\drivers\\oci" FILES ${PDAL_DRIVERS_OCI_HPP}) source_group("Header Files\\drivers\\qfit" FILES ${PDAL_DRIVERS_QFIT_HPP}) source_group("Header Files\\drivers\\sbet" FILES ${PDAL_DRIVERS_SBET_HPP}) source_group("Header Files\\drivers\\terrasolid" FILES ${PDAL_DRIVERS_TERRASOLID_HPP}) source_group("Header Files\\drivers\\text" FILES ${PDAL_DRIVERS_TEXT_HPP}) -source_group("Header Files\\drivers\\pgpointcloud" FILES ${PDAL_DRIVERS_PGPOINTCLOUD_HPP}) source_group("Header Files\\filters" FILES ${PDAL_FILTERS_HPP}) source_group("Header Files\\plang" FILES ${PDAL_PLANG_HPP}) @@ -681,13 +476,10 @@ source_group("Source Files\\config" FILES ${PDAL_CONFIG_CPP}) source_group("Source Files\\drivers\\faux" FILES ${PDAL_DRIVERS_FAUX_CPP}) source_group("Source Files\\drivers\\caris" FILES ${PDAL_DRIVERS_CARIS_CPP}) source_group("Source Files\\drivers\\las" FILES ${PDAL_DRIVERS_LAS_CPP}) -source_group("Source Files\\drivers\\nitf" FILES ${PDAL_DRIVERS_NITF_CPP}) -source_group("Source Files\\drivers\\oci" FILES ${PDAL_DRIVERS_OCI_CPP}) source_group("Source Files\\drivers\\qfit" FILES ${PDAL_DRIVERS_QFIT_CPP}) source_group("Source Files\\drivers\\sbet" FILES ${PDAL_DRIVERS_SBET_CPP}) source_group("Source Files\\drivers\\terrasolid" FILES ${PDAL_DRIVERS_TERRASOLID_CPP}) source_group("Source Files\\drivers\\text" FILES ${PDAL_DRIVERS_TEXT_CPP}) -source_group("Source Files\\drivers\\pgpointcloud" FILES ${PDAL_DRIVERS_PGPOINTCLOUD_CPP}) source_group("Source Files\\filters" FILES ${PDAL_FILTERS_CPP}) source_group("Source Files\\plang" FILES ${PDAL_PLANG_CPP}) @@ -722,32 +514,6 @@ endif() PDAL_ADD_LIBRARY(${PDAL_LIB_NAME} ${PDAL_SOURCES}) -set (SQLITE_LIBRARIES ${SQLITE3_LIBRARY}) - -if (WITH_SQLITE) -if (NOT USE_PDAL_PLUGIN_SQLITE) -target_link_libraries(${PDAL_LIB_NAME} ${PDAL_LINKAGE} ${SQLITE_LIBRARIES} ) -endif() -endif() - -if (WITH_PGPOINTCLOUD) -if (NOT USE_PDAL_PLUGIN_PGPOINTCLOUD) -target_link_libraries(${PDAL_LIB_NAME} ${PDAL_LINKAGE} ${POSTGRESQL_LIBRARIES}) -endif() -endif() - -if (WITH_ORACLE) -if (NOT USE_PDAL_PLUGIN_OCI) -target_link_libraries(${PDAL_LIB_NAME} ${PDAL_LINKAGE} "${ORACLE_LIBRARY}") -endif() -endif() - -if (WITH_NITRO) -if (NOT USE_PDAL_PLUGIN_NITRO) -target_link_libraries(${PDAL_LIB_NAME} ${PDAL_LINKAGE} ${NITRO_LIBRARIES} ) -endif() -endif() - if (WITH_LASZIP) target_link_libraries(${PDAL_LIB_NAME} ${PDAL_LINKAGE} "${LASZIP_LIBRARY}") endif() @@ -760,20 +526,12 @@ if (WITH_LIBXML2) target_link_libraries(${PDAL_LIB_NAME} ${PDAL_LINKAGE} ${LIBXML2_LIBRARIES}) endif() -if (WITH_HDF5) - target_link_libraries(${PDAL_LIB_NAME} ${PDAL_LINKAGE} ${HDF5_LIBRARIES}) -endif() - target_link_libraries(${PDAL_LIB_NAME} ${PDAL_LINKAGE} "${CMAKE_THREAD_LIBS_INIT}" "${CMAKE_DL_LIBS}" - "${MRSID_LIBRARY}" "${GEOTIFF_LIBRARY}" "${GDAL_LIBRARY}" - "${P2G_LIBRARY}" "${GEOS_LIBRARY}" - "${HEXER_LIBRARY}" - "${ORACLE_LIBRARY}" "${ZLIB_LIBRARIES}" ) @@ -787,48 +545,6 @@ set_target_properties(${PDAL_LIB_NAME} PROPERTIES SOVERSION "${PDAL_LIB_SOVERSION}" ) -if (USE_PDAL_PLUGIN_TEXT) - set(PDAL_TEXT_WRITER_LIB_NAME pdal_plugin_writer_text) - add_library(${PDAL_TEXT_WRITER_LIB_NAME} SHARED "${PDAL_DRIVERS_TEXT_CPP}" "${PDAL_DRIVERS_TEXT_HPP}") - target_link_libraries(${PDAL_TEXT_WRITER_LIB_NAME} INTERFACE general - ${PDAL_LIB_NAME}) - set_target_properties("${PDAL_TEXT_WRITER_LIB_NAME}" - PROPERTIES SOVERSION "${PDAL_LIB_SOVERSION}" ) -endif() - -if (WITH_SQLITE) -if (USE_PDAL_PLUGIN_SQLITE) - set(PDAL_SQLITE_WRITER_LIB_NAME pdal_plugin_writer_sqlite) - add_library(${PDAL_SQLITE_WRITER_LIB_NAME} SHARED "${PDAL_SQLITE_SRC}/Writer.cpp") - target_link_libraries(${PDAL_SQLITE_WRITER_LIB_NAME} INTERFACE general - "${PDAL_LIB_NAME}" - ${SQLITE_LIBRARIES}) - set_target_properties(${PDAL_SQLITE_WRITER_LIB_NAME} - PROPERTIES SOVERSION "${PDAL_LIB_SOVERSION}" ) - - set(PDAL_SQLITE_READER_LIB_NAME pdal_plugin_reader_sqlite) - add_library(${PDAL_SQLITE_READER_LIB_NAME} SHARED ${PDAL_SQLITE_SRC}/Reader.cpp) - target_link_libraries(${PDAL_SQLITE_READER_LIB_NAME} INTERFACE general - "${PDAL_LIB_NAME}" - ${SQLITE_LIBRARIES}) - set_target_properties(${PDAL_SQLITE_READER_LIB_NAME} - PROPERTIES SOVERSION "${PDAL_LIB_SOVERSION}" ) -endif() -endif() - -if (WITH_ORACLE) -if (USE_PDAL_PLUGIN_OCI) - set(PDAL_OCI_WRITER_LIB_NAME pdal_plugin_writer_oci) - add_library(${PDAL_OCI_WRITER_LIB_NAME} SHARED "${PDAL_ORACLE_SRC}/oci_wrapper.cpp" - "${PDAL_ORACLE_SRC}/common.cpp" - "${PDAL_ORACLE_SRC}/Writer.cpp") - target_link_libraries(${PDAL_OCI_WRITER_LIB_NAME} INTERFACE general - "${PDAL_LIB_NAME}" - "${ORACLE_LIBRARY}") - set_target_properties(${PDAL_OCI_WRITER_LIB_NAME} - PROPERTIES SOVERSION "${PDAL_LIB_SOVERSION}" ) -endif() -endif() ############################################################################### # Targets installation diff --git a/src/Charbuf.cpp b/src/Charbuf.cpp index 40030f726b..4df0e9c766 100644 --- a/src/Charbuf.cpp +++ b/src/Charbuf.cpp @@ -40,7 +40,7 @@ namespace pdal { -void Charbuf::initialize(char *buf, size_t count, pos_type bufOffset) +void Charbuf::initialize(char *buf, size_t count, std::ios::pos_type bufOffset) { m_bufOffset = bufOffset; m_buf = buf; @@ -49,7 +49,7 @@ void Charbuf::initialize(char *buf, size_t count, pos_type bufOffset) } -Charbuf::pos_type Charbuf::seekpos(pos_type pos, std::ios_base::openmode which) +std::ios::pos_type Charbuf::seekpos(std::ios::pos_type pos, std::ios_base::openmode which) { pos -= m_bufOffset; if (which & std::ios_base::in) @@ -69,11 +69,11 @@ Charbuf::pos_type Charbuf::seekpos(pos_type pos, std::ios_base::openmode which) return pos; } -Charbuf::pos_type -Charbuf::seekoff(off_type off, std::ios_base::seekdir dir, +std::ios::pos_type +Charbuf::seekoff(std::ios::off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which) { - Charbuf::pos_type pos; + std::ios::pos_type pos; char *cpos = nullptr; if (which & std::ios_base::in) { diff --git a/src/Compression.cpp b/src/Compression.cpp new file mode 100644 index 0000000000..10805caba3 --- /dev/null +++ b/src/Compression.cpp @@ -0,0 +1,34 @@ +/****************************************************************************** +* Copyright (c) 2014, Howard Butler (howard@hobu.co) +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following +* conditions are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided +* with the distribution. +* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the +* names of its contributors may be used to endorse or promote +* products derived from this software without specific prior +* written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +* OF SUCH DAMAGE. +****************************************************************************/ + diff --git a/src/PointBuffer.cpp b/src/PointBuffer.cpp index a388108116..29dd6279c7 100644 --- a/src/PointBuffer.cpp +++ b/src/PointBuffer.cpp @@ -121,25 +121,55 @@ void PointBuffer::dump(std::ostream& ostr) const switch (dd->type()) { case Dimension::Type::Signed8: - ostr << (int)(getFieldInternal(d, idx)); + { + ostr << (int)(getFieldInternal(d, idx)); + break; + } case Dimension::Type::Signed16: - ostr << getFieldInternal(d, idx); + { + ostr << getFieldInternal(d, idx); + break; + } case Dimension::Type::Signed32: - ostr << getFieldInternal(d, idx); + { + ostr << getFieldInternal(d, idx); + break; + } case Dimension::Type::Signed64: - ostr << getFieldInternal(d, idx); + { + ostr << getFieldInternal(d, idx); + break; + } case Dimension::Type::Unsigned8: - ostr << (unsigned)(getFieldInternal(d, idx)); + { + ostr << (unsigned)(getFieldInternal(d, idx)); + break; + } case Dimension::Type::Unsigned16: - ostr << getFieldInternal(d, idx); + { + ostr << getFieldInternal(d, idx); + break; + } case Dimension::Type::Unsigned32: - ostr << getFieldInternal(d, idx); + { + ostr << getFieldInternal(d, idx); + break; + } case Dimension::Type::Unsigned64: - ostr << getFieldInternal(d, idx); + { + ostr << getFieldInternal(d, idx); + break; + } case Dimension::Type::Float: - ostr << getFieldInternal(d, idx); + { + ostr << getFieldInternal(d, idx); + break; + } case Dimension::Type::Double: - ostr << getFieldInternal(d, idx); + { + ostr << getFieldInternal(d, idx); + break; + } default: throw; } diff --git a/src/QuadIndex.cpp b/src/QuadIndex.cpp index ebafbd65a3..3252cbf667 100644 --- a/src/QuadIndex.cpp +++ b/src/QuadIndex.cpp @@ -60,9 +60,9 @@ struct Point const double y; }; -struct PointRef +struct PtRef { - PointRef(const Point& point, std::size_t pbIndex) + PtRef(const Point& point, std::size_t pbIndex) : point(point) , pbIndex(pbIndex) { } @@ -137,7 +137,7 @@ namespace pdal // Recursive quadtree implementation. struct Tree { - Tree(BBox bbox, const PointRef* data = 0) + Tree(BBox bbox, const PtRef* data = 0) : bbox(bbox) , data(data) , nw() @@ -149,7 +149,7 @@ struct Tree void getFills(std::vector& fills, std::size_t level = 0) const; // Returns depth resulting from the insertion of this point. - std::size_t addPoint(const PointRef* toAdd, std::size_t curDepth = 0); + std::size_t addPoint(const PtRef* toAdd, std::size_t curDepth = 0); void getPoints( std::vector& results, @@ -200,7 +200,7 @@ struct Tree } const BBox bbox; - const PointRef* data; + const PtRef* data; std::unique_ptr nw; std::unique_ptr ne; @@ -233,7 +233,7 @@ struct Tree std::size_t curDepth) const; }; -std::size_t Tree::addPoint(const PointRef* toAdd, const std::size_t curDepth) +std::size_t Tree::addPoint(const PtRef* toAdd, const std::size_t curDepth) { if (data) { @@ -589,7 +589,7 @@ struct QuadIndex::QImpl std::size_t depthEnd) const; const PointBuffer& m_pointBuffer; - std::vector > m_pointRefVec; + std::vector > m_pointRefVec; std::unique_ptr m_tree; std::size_t m_depth; std::vector m_fills; @@ -616,13 +616,13 @@ void QuadIndex::QImpl::build() for (std::size_t i(0); i < m_pointBuffer.size(); ++i) { m_pointRefVec[i].reset( - new PointRef( + new PtRef( Point( m_pointBuffer.getFieldAs(Dimension::Id::X, i), m_pointBuffer.getFieldAs(Dimension::Id::Y, i)), i)); - const PointRef* pointRef(m_pointRefVec[i].get()); + const PtRef* pointRef(m_pointRefVec[i].get()); if (pointRef->point.x < xMin) xMin = pointRef->point.x; if (pointRef->point.x > xMax) xMax = pointRef->point.x; if (pointRef->point.y < yMin) yMin = pointRef->point.y; diff --git a/src/Stage.cpp b/src/Stage.cpp index 74ba9f74ae..e6648457e1 100644 --- a/src/Stage.cpp +++ b/src/Stage.cpp @@ -111,9 +111,6 @@ PointBufferSet Stage::execute(PointContextRef ctx ) void Stage::l_initialize(PointContextRef ctx) { m_metadata = ctx.metadata().add(getName()); - if (m_inputs.size()) { - Stage& prevStage = *m_inputs[0]; - } } @@ -193,7 +190,10 @@ void Stage::setSpatialReference(MetadataNode& m, MetadataNode spatialNode = m.findChild(pred); if (spatialNode.empty()) - m.add("spatialreference", spatialRef, "SRS of this stage"); + { + m.add("spatialreference", spatialRef.getWKT(SpatialReference::eHorizontalOnly, false), "SRS of this stage"); + m.add("comp_spatialreference", spatialRef.getWKT(SpatialReference::eCompoundOK, false), "SRS of this stage"); + } } std::vector Stage::findStage(std::string name) diff --git a/src/StageFactory.cpp b/src/StageFactory.cpp index d461a27fe0..4ff482f9cc 100644 --- a/src/StageFactory.cpp +++ b/src/StageFactory.cpp @@ -63,38 +63,10 @@ MAKE_READER_CREATOR(FauxReader, pdal::drivers::faux::Reader) MAKE_READER_CREATOR(LasReader, pdal::drivers::las::Reader) MAKE_READER_CREATOR(BpfReader, pdal::BpfReader) MAKE_READER_CREATOR(BufferReader, drivers::buffer::BufferReader) - -#ifdef PDAL_HAVE_ORACLE -#ifndef USE_PDAL_PLUGIN_OCI -MAKE_READER_CREATOR(OciReader, pdal::drivers::oci::OciReader) -#endif -#endif - -#ifdef PDAL_HAVE_NITRO -MAKE_READER_CREATOR(NITFReader, pdal::drivers::nitf::NitfReader) -#endif - -#ifdef PDAL_HAVE_SQLITE -#ifndef USE_PDAL_PLUGIN_SQLITE -MAKE_READER_CREATOR(SqliteReader, pdal::drivers::sqlite::SQLiteReader) -#endif -#endif - -#ifdef PDAL_HAVE_POSTGRESQL -#ifndef USE_PDAL_PLUGIN_PGPOINTCLOUD -MAKE_READER_CREATOR(PgPcReader, pdal::drivers::pgpointcloud::PgReader) -#endif -#endif - MAKE_READER_CREATOR(QfitReader, pdal::drivers::qfit::Reader) MAKE_READER_CREATOR(TerrasolidReader, pdal::drivers::terrasolid::Reader) - MAKE_READER_CREATOR(SbetReader, pdal::drivers::sbet::SbetReader) -#ifdef PDAL_HAVE_HDF5 -MAKE_READER_CREATOR(IcebridgeReader, pdal::drivers::icebridge::Reader) -#endif - // // define the functions to create the filters // @@ -106,7 +78,6 @@ MAKE_FILTER_CREATOR(Colorization, pdal::filters::Colorization) MAKE_FILTER_CREATOR(Crop, pdal::filters::Crop) MAKE_FILTER_CREATOR(Decimation, pdal::filters::Decimation) MAKE_FILTER_CREATOR(Ferry, pdal::filters::Ferry) -MAKE_FILTER_CREATOR(HexBin, pdal::filters::HexBin) MAKE_FILTER_CREATOR(Merge, pdal::filters::Merge) MAKE_FILTER_CREATOR(Reprojection, pdal::filters::Reprojection) MAKE_FILTER_CREATOR(Sort, pdal::filters::Sort) @@ -122,38 +93,7 @@ MAKE_FILTER_CREATOR(Programmable, pdal::filters::Programmable) // define the functions to create the writers // MAKE_WRITER_CREATOR(LasWriter, pdal::drivers::las::Writer) - -#ifndef USE_PDAL_PLUGIN_TEXT MAKE_WRITER_CREATOR(TextWriter, pdal::drivers::text::Writer) -#endif - -#ifdef PDAL_HAVE_ORACLE -#ifndef USE_PDAL_PLUGIN_OCI -MAKE_WRITER_CREATOR(OciWriter, pdal::drivers::oci::Writer) -#endif -#endif - -#ifdef PDAL_HAVE_P2G -MAKE_WRITER_CREATOR(P2GWriter, pdal::drivers::p2g::P2gWriter) -#endif - -#ifdef PDAL_HAVE_SQLITE -#ifndef USE_PDAL_PLUGIN_SQLITE -MAKE_WRITER_CREATOR(SqliteWriter, pdal::drivers::sqlite::SQLiteWriter) -#endif -#endif - -#ifdef PDAL_HAVE_POSTGRESQL -#ifndef USE_PDAL_PLUGIN_PGPOINTCLOUD -MAKE_WRITER_CREATOR(PgPcWriter, pdal::drivers::pgpointcloud::Writer) -#endif -#endif - -#ifdef PDAL_HAVE_NITRO -#ifndef USE_PDAL_PLUGIN_NITF -MAKE_WRITER_CREATOR(NitfWriter, pdal::drivers::nitf::Writer) -#endif -#endif StageFactory::StageFactory() { @@ -180,18 +120,23 @@ std::string StageFactory::inferReaderDriver(const std::string& filename) drivers["las"] = "drivers.las.reader"; drivers["laz"] = "drivers.las.reader"; drivers["bin"] = "drivers.terrasolid.reader"; - if (f.getReaderCreator("drivers.greyhound.reader")) drivers["greyhound"] = "drivers.greyhound.reader"; drivers["qi"] = "drivers.qfit.reader"; - drivers["nitf"] = "drivers.nitf.reader"; - drivers["ntf"] = "drivers.nitf.reader"; - drivers["nsf"] = "drivers.nitf.reader"; + if (f.getReaderCreator("drivers.nitf.reader")) + { + drivers["nitf"] = "drivers.nitf.reader"; + drivers["ntf"] = "drivers.nitf.reader"; + drivers["nsf"] = "drivers.nitf.reader"; + } drivers["bpf"] = "drivers.bpf.reader"; drivers["sbet"] = "drivers.sbet.reader"; drivers["icebridge"] = "drivers.icebridge.reader"; drivers["sqlite"] = "drivers.sqlite.reader"; - + + if (f.getReaderCreator("drivers.rxp.reader")) + drivers["rxp"] = "drivers.rxp.reader"; + if (f.getReaderCreator("drivers.pcd.reader")) drivers["pcd"] = "drivers.pcd.reader"; @@ -223,7 +168,8 @@ std::string StageFactory::inferWriterDriver(const std::string& filename) drivers["json"] = "drivers.text.writer"; drivers["xyz"] = "drivers.text.writer"; drivers["txt"] = "drivers.text.writer"; - drivers["ntf"] = "drivers.nitf.writer"; + if (f.getWriterCreator("drivers.nitf.writer")) + drivers["ntf"] = "drivers.nitf.writer"; drivers["sqlite"] = "drivers.sqlite.writer"; if (boost::algorithm::iequals(filename, "STDOUT")) @@ -360,35 +306,11 @@ void StageFactory::registerKnownReaders() REGISTER_READER(FauxReader, pdal::drivers::faux::Reader); REGISTER_READER(BufferReader, pdal::drivers::buffer::BufferReader); REGISTER_READER(LasReader, pdal::drivers::las::Reader); -#ifdef PDAL_HAVE_ORACLE -#ifndef USE_PDAL_PLUGIN_OCI - REGISTER_READER(OciReader, pdal::drivers::oci::OciReader); -#endif -#endif -#ifdef PDAL_HAVE_NITRO - REGISTER_READER(NITFReader, pdal::drivers::nitf::NitfReader); -#endif - -#ifdef PDAL_HAVE_SQLITE -#ifndef USE_PDAL_PLUGIN_SQLITE - REGISTER_READER(SqliteReader, pdal::drivers::sqlite::SQLiteReader); -#endif -#endif - -#ifdef PDAL_HAVE_POSTGRESQL -#ifndef USE_PDAL_PLUGIN_PGPOINTCLOUD - REGISTER_READER(PgPcReader, pdal::drivers::pgpointcloud::PgReader); -#endif -#endif REGISTER_READER(QfitReader, pdal::drivers::qfit::Reader); REGISTER_READER(TerrasolidReader, pdal::drivers::terrasolid::Reader); REGISTER_READER(BpfReader, pdal::BpfReader); REGISTER_READER(SbetReader, pdal::drivers::sbet::SbetReader); - -#ifdef PDAL_HAVE_HDF5 - REGISTER_READER(IcebridgeReader, pdal::drivers::icebridge::Reader); -#endif } @@ -402,7 +324,6 @@ void StageFactory::registerKnownFilters() REGISTER_FILTER(Crop, pdal::filters::Crop); REGISTER_FILTER(Decimation, pdal::filters::Decimation); REGISTER_FILTER(Ferry, pdal::filters::Ferry); - REGISTER_FILTER(HexBin, pdal::filters::HexBin); REGISTER_FILTER(Merge, pdal::filters::Merge); REGISTER_FILTER(Reprojection, pdal::filters::Reprojection); REGISTER_FILTER(Sort, pdal::filters::Sort); @@ -419,38 +340,7 @@ void StageFactory::registerKnownFilters() void StageFactory::registerKnownWriters() { REGISTER_WRITER(LasWriter, pdal::drivers::las::Writer); - -#ifndef USE_PDAL_PLUGIN_TEXT REGISTER_WRITER(TextWriter, pdal::drivers::text::Writer); -#endif - -#ifdef PDAL_HAVE_ORACLE -#ifndef USE_PDAL_PLUGIN_OCI - REGISTER_WRITER(OciWriter, pdal::drivers::oci::Writer); -#endif -#endif - -#ifdef PDAL_HAVE_P2G - REGISTER_WRITER(P2GWriter, pdal::drivers::p2g::P2gWriter); -#endif - -#ifdef PDAL_HAVE_SQLITE -#ifndef USE_PDAL_PLUGIN_SQLITE - REGISTER_WRITER(SqliteWriter, pdal::drivers::sqlite::SQLiteWriter); -#endif -#endif - -#ifdef PDAL_HAVE_POSTGRESQL -#ifndef USE_PDAL_PLUGIN_PGPOINTCLOUD - REGISTER_WRITER(PgPcWriter, pdal::drivers::pgpointcloud::Writer); -#endif -#endif - -#ifdef PDAL_HAVE_NITRO -#ifndef USE_PDAL_PLUGIN_NITF - REGISTER_WRITER(NitfWriter, pdal::drivers::nitf::Writer); -#endif -#endif } void StageFactory::loadPlugins() @@ -564,11 +454,11 @@ void StageFactory::registerPlugin(std::string const& filename) } std::string base = basename.string(); + std::string pluginName = boost::algorithm::ireplace_first_copy(base, "libpdal_plugin_", ""); - std::string registerMethodName = "PDALRegister_" + \ - boost::algorithm::ireplace_first_copy(base, "libpdal_plugin_", ""); + std::string registerMethodName = "PDALRegister_" + pluginName; - std::string versionMethodName = "PDALRegister_version_" + base.substr(base.find_last_of("_")+1, base.size()); + std::string versionMethodName = "PDALRegister_version_" + pluginName; Utils::registerPlugin((void*)this, filename, registerMethodName, versionMethodName); diff --git a/src/XMLSchema.cpp b/src/XMLSchema.cpp index 1d6205ff0f..ac2b377efa 100644 --- a/src/XMLSchema.cpp +++ b/src/XMLSchema.cpp @@ -33,9 +33,11 @@ #include #include +#include #include #include +#include #include #include #include @@ -370,21 +372,21 @@ Reader::~Reader() // print_element_names(xmlNode * a_node) // { // #ifdef PDAL_HAVE_LIBXML2 -// +// // // xmlNode *cur_node = NULL; -// +// // // for (cur_node = a_node; cur_node; cur_node = cur_node->next) // { // if (cur_node->type == XML_ELEMENT_NODE) // { // printf("node type: Element, name: %s\n", cur_node->name); // } -// +// // // print_element_names(cur_node->children); // } // #endif // } - +// std::string Reader::remapOldNames(std::string const& input) { if (boost::iequals(input, "Unnamed field 512") || boost::iequals(input, "Chipper Point ID")) @@ -397,63 +399,47 @@ std::string Reader::remapOldNames(std::string const& input) } #ifdef PDAL_HAVE_LIBXML2 -pdal::Metadata Reader::LoadMetadata(xmlNode* startNode) +MetadataNode Reader::LoadMetadata(xmlNode* startNode, MetadataNode& input) { - - pdal::Metadata output; +// Expect metadata in the following form +// We are going to skipp the root element because we are +// expecting to be given one with our input +// +// +// lazperf +// 1.0 +// +// xmlNode* node = startNode; - - -// xmlChar* name = xmlGetProp(node, (const xmlChar*) "name"); -// xmlChar* etype = xmlGetProp(node, (const xmlChar*) "type"); -// print_element_names(node); - // std::cout << "node name: " << (const char*)node->name << std::endl; -// std::cout << "prop type: " << (const char*) etype << std::endl; - - // pdal::Metadata m((const char*) node->name); - // if (boost::iequals((const char*)etype, "blank")) - // { - // // blank denotes a new Metadata instance. - // if (node->children) - // output.addMetadata(LoadMetadata(node->children)); - // } - - // - - while (node != NULL) + for (node = startNode; node; node=node->next) { - - // std::cout << "node name: " << (const char*)node->name << std::endl; - - if (node->properties) - { -// xmlChar* name = xmlGetProp(node, (const xmlChar *)"name"); -// xmlChar* etype = xmlGetProp(node, (const xmlChar *)"type"); -// std::cout << "property name: " << (const char*)name << std::endl; - // std::cout << "proper type: " << (const char*)etype << std::endl; - - } - - // pdal::Metadata m((const char*) node->name); - // if (boost::iequals((const char*)etype.get(), "blank")) - // { - // // blank denotes a new Metadata instance. - // m.addMetadata(LoadMetadata(node)); - // } - - - // output.addMetadata(m); - if (node->type == XML_ELEMENT_NODE) { - node = node->children; + if (boost::equals((const char*)node->name, "Metadata")) + { + const char* fieldname = (const char*) xmlGetProp(node, (const xmlChar*) "name"); + const char* etype = (const char*) xmlGetProp(node, (const xmlChar*) "type"); + const char* description = (const char*) xmlGetProp(node, (const xmlChar*) "description"); + const char* text = (const char*) xmlNodeGetContent(node); + + if (!boost::iequals(fieldname, "root")) + { + if (!fieldname) + { + std::ostringstream oss; + oss << "Unable to read metadata for node '" << (const char*)node->name<<"' no \"name\" was given"; + throw pdal_error(oss.str()); + } + input.add(fieldname, text ? text : "", description ? description : ""); + } + } + LoadMetadata(node->children, input); } - else - node = node->next; } - return output; + + return input; } #endif @@ -493,17 +479,15 @@ void Reader::Load() dimension = dimension->next; continue; } - - // printf("node name: %s\n", (const char*)dimension->name); - // if (boost::equals((const char*)dimension->name, "metadata")) - // { - // printf("metadata node name: %s\n", (const char*)dimension->name); - // - // - // metadata.addMetadata(LoadMetadata(dimension)); - // dimension = dimension->next; - // continue; - // } + + if (boost::equals((const char*)dimension->name, "metadata")) + { + m_metadata = MetadataNode("root"); + m_metadata = LoadMetadata(dimension, m_metadata); + + dimension = dimension->next; + continue; + } if (dimension->type != XML_ELEMENT_NODE || !boost::iequals((const char*)dimension->name, "dimension")) @@ -685,25 +669,9 @@ void Writer::write(TextWriterPtr writer) writeSchema(writer); - if (!m_metadata.empty()) - { - xmlTextWriterStartElementNS(w, (const xmlChar*) "pc", - (const xmlChar*) "metadata", NULL); - - boost::property_tree::ptree output; - PipelineWriter::writeMetadata(output, m_metadata); - std::ostringstream oss; - boost::property_tree::xml_parser::write_xml(oss, output); - std::string xml = oss.str(); - - // wipe off write_xml's xml declaration - boost::algorithm::erase_all(xml, ""); - xmlTextWriterWriteRawLen(w, (const xmlChar*) xml.c_str(), xml.size()); - xmlTextWriterEndElement(w); - } - xmlTextWriterEndElement(w); xmlTextWriterEndDocument(w); + xmlTextWriterFlush(w); #endif } @@ -761,9 +729,27 @@ void Writer::writeSchema(TextWriterPtr writer) if (m_orientation == Orientation::DimensionMajor) orientation << "dimension"; xmlTextWriterWriteElementNS(w, (const xmlChar*) "pc", (const xmlChar*) "orientation", NULL, (const xmlChar*) orientation.str().c_str()); + + if (!m_metadata.empty()) + { + xmlTextWriterStartElementNS(w, (const xmlChar*) "pc", + (const xmlChar*) "metadata", NULL); + + boost::property_tree::ptree output; + PipelineWriter::writeMetadata(output, m_metadata); + std::ostringstream oss; + boost::property_tree::xml_parser::write_xml(oss, output); + std::string xml = oss.str(); + + // wipe off write_xml's xml declaration + boost::algorithm::erase_all(xml, ""); + xmlTextWriterWriteRawLen(w, (const xmlChar*) xml.c_str(), xml.size()); + xmlTextWriterEndElement(w); + } + xmlTextWriterEndElement(w); xmlTextWriterFlush(w); - + #endif } diff --git a/src/drivers/bpf/BpfReader.cpp b/src/drivers/bpf/BpfReader.cpp index af23112330..8a9e9977b5 100644 --- a/src/drivers/bpf/BpfReader.cpp +++ b/src/drivers/bpf/BpfReader.cpp @@ -83,6 +83,9 @@ void BpfReader::initialize() readPolarData(); } + // Read thing after the standard header as metadata. + readHeaderExtraData(); + // Fast forward file to end of header as reported by base header. std::streampos pos = m_stream.position(); if (pos > m_header.m_len) @@ -117,6 +120,7 @@ bool BpfReader::readUlemData() return (bool)m_stream; } + bool BpfReader::readUlemFiles() { BpfUlemFile file; @@ -126,6 +130,19 @@ bool BpfReader::readUlemFiles() return (bool)m_stream; } + +/// Encode all data that follows the headers as metadata. +/// \return Whether the stream is still valid. +bool BpfReader::readHeaderExtraData() +{ + std::streampos size = m_header.m_len - m_stream.position(); + std::vector buf(size); + m_stream.get(buf); + m_metadata.addEncoded("header_data", buf.data(), buf.size()); + return (bool)m_stream; +} + + bool BpfReader::readPolarData() { if (!m_polarHeader.read(m_stream)) diff --git a/src/drivers/las/Writer.cpp b/src/drivers/las/Writer.cpp index 907fe8edf1..7e4bf19f66 100644 --- a/src/drivers/las/Writer.cpp +++ b/src/drivers/las/Writer.cpp @@ -382,40 +382,6 @@ void Writer::addVlr(const std::string& userId, uint16_t recordId, } } -/// Find the approriate value for the specified header field. -/// \param name - Name of header field. -/// \return Value of header field. -template -T Writer::headerVal(const std::string& name) -{ - // The header values either come from options, or are overriden in - // the metadata for options which had the value FORWARD. For those, - // grab the value from metadata if it exists, or use the default value, - // which was stuck on following the FORWARD value when processing options. - auto pred = [name](MetadataNode n) - { - return n.name() == name; - }; - - std::string val = m_headerVals[name]; - if (val.find("FORWARD") == 0) - { - MetadataNode m = m_metadata.findChild(pred); - val = m.empty() ? val.substr(strlen("FORWARD")) : m.value(); - } - try - { - return boost::lexical_cast(val); - } - catch (boost::bad_lexical_cast ex) - { - std::stringstream out; - out << "Couldn't convert option \"" << name << "\" with value \"" << - val << "\" from string as necessary."; - throw pdal_error(out.str()); - } -} - /// Fill the LAS header with values as provided in options or forwarded /// metadata. @@ -436,32 +402,7 @@ void Writer::fillHeader(PointContextRef ctx) m_lasHeader.setSoftwareId(headerVal("software_id")); m_lasHeader.setSystemId(headerVal("system_id")); m_lasHeader.setProjectId(headerVal("project_id")); - - uint16_t reserved(0); - - try - { - reserved = headerVal("global_encoding"); - } catch (boost::bad_lexical_cast&) - { - // Try decoding base64 - std::string global_encoding_data = headerVal("global_encoding"); - std::vector data = Utils::base64_decode(global_encoding_data); - if (data.size() == 0) - ; - else if (data.size() == 1 ) - reserved = data[0]; - else if (data.size() == 2 ) - memcpy(&reserved, data.data(), data.size()); - else - { - std::ostringstream oss; - oss << "size of global_encoding bytes should == 2, not " << - data.size(); - throw pdal_error(oss.str()); - } - } - m_lasHeader.setGlobalEncoding(reserved); + m_lasHeader.setGlobalEncoding(headerVal("global_encoding")); m_lasHeader.setFileSourceId(headerVal("filesource_id")); if (!m_lasHeader.pointFormatSupported()) diff --git a/src/drivers/pgpointcloud/Reader.cpp b/src/drivers/pgpointcloud/Reader.cpp deleted file mode 100644 index 88cdb9428e..0000000000 --- a/src/drivers/pgpointcloud/Reader.cpp +++ /dev/null @@ -1,651 +0,0 @@ -/****************************************************************************** -* Copyright (c) 2012, Howard Butler, hobu.inc@gmail.com -* Copyright (c) 2013, Paul Ramsey, pramsey@cleverelephant.ca -* -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following -* conditions are met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided -* with the distribution. -* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the -* names of its contributors may be used to endorse or promote -* products derived from this software without specific prior -* written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -* OF SUCH DAMAGE. -****************************************************************************/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - - - -#ifdef USE_PDAL_PLUGIN_PGPOINTCLOUD -//MAKE_READER_CREATOR(pgpointcloudReader, pdal::drivers::pgpointcloud::Reader) -CREATE_READER_PLUGIN(pgpointcloudReader, pdal::drivers::pgpointcloud::Reader) -#endif - - -namespace pdal -{ -namespace drivers -{ -namespace pgpointcloud -{ - -//********************************************************************************* -// pdal.drivers.pgpointcloud.Reader -// -// The iterator downbelow controls the actual reading, the Reader just does some -// basic setup and returning of metadata to the Writer at the other end of -// the chain. -// -// The core of PDAL only calls the following methods: -// -// Options Reader::getDefaultOptions() -// void Reader::initialize() -// boost::uint64_t Reader::getNumPoints() const -// pdal::StageSequentialIterator* Reader::createSequentialIterator(PointBuffer& buffer) const -// -//********************************************************************************* - - -Reader::Reader(const Options& options) - : pdal::Reader(options) - , m_session(NULL) - , m_connection("") - , m_table_name("") - , m_schema_name("") - , m_column_name("") - , m_where("") - , m_pcid(0) - , m_cached_point_count(0) - , m_cached_max_points(0) -{} - -Reader::~Reader() -{ - if (m_session) - PQfinish(m_session); - - return; -} - -Options Reader::getDefaultOptions() -{ - Options options; - - Option connection("connection", "", "Connection string to connect to database"); - Option table("table", "", "Table to read out of"); - Option schema("schema", "", "Schema to read out of"); - Option column("column", "", "Column to read out of"); - Option where("where", "", "SQL where clause to filter query"); - Option spatialreference("spatialreference", "", "override the source data spatialreference"); - - options.add(connection); - options.add(table); - options.add(schema); - options.add(column); - options.add(where); - options.add(spatialreference); - - return options; -} - - -void Reader::initialize() -{ - pdal::Reader::initialize(); - - // If we don't know the table name, we're SOL - m_table_name = getOptions().getValueOrThrow("table"); - - // Connection string needs to exist and actually work - m_connection = getOptions().getValueOrThrow("connection"); - - // Schema and column name can be defaulted safely - m_column_name = getOptions().getValueOrDefault("column", "pa"); - m_schema_name = getOptions().getValueOrDefault("schema", ""); - - // Read other preferences - m_where = getOptions().getValueOrDefault("where", ""); - - // Database connection - m_session = pg_connect(m_connection); - - // Read schema from pointcloud_formats if possible - m_schema = fetchSchema(); - - // Allow spatialreference override if desired - try - { - setSpatialReference(getOptions().getValueOrThrow("spatialreference")); - } - catch (pdal::option_not_found const&) - { - // Read from pointcloud_formats otherwise - setSpatialReference(fetchSpatialReference()); - } - -} - -boost::uint64_t Reader::getNumPoints() const -{ - if (m_cached_point_count == 0) - { - std::ostringstream oss; - oss << "SELECT Sum(PC_NumPoints(" << m_column_name << ")) AS numpoints, "; - oss << "Max(PC_NumPoints(" << m_column_name << ")) AS maxpoints FROM "; - if (m_schema_name.size()) - { - oss << m_schema_name << "."; - } - oss << m_table_name; - if (m_where.size()) - { - oss << " WHERE " << m_where; - } - - PGresult *result = pg_query_result(m_session, oss.str()); - - if (PQresultStatus(result) != PGRES_TUPLES_OK) - { - throw pdal_error("unable to get point count"); - } - m_cached_point_count = atoi(PQgetvalue(result, 0, 0)); - m_cached_max_points = atoi(PQgetvalue(result, 0, 1)); - PQclear(result); - } - - return m_cached_point_count; -} - -std::string Reader::getDataQuery() const -{ - std::ostringstream oss; - oss << "SELECT text(PC_Uncompress(" << m_column_name << ")) AS pa, "; - oss << "PC_NumPoints(" << m_column_name << ") AS npoints FROM "; - if (m_schema_name.size()) - { - oss << m_schema_name << "."; - } - oss << m_table_name; - if (m_where.size()) - { - oss << " WHERE " << m_where; - } - - log()->get(logDEBUG) << "Constructed data query " << oss.str() << std::endl; - return oss.str(); -} - -boost::uint64_t Reader::getMaxPoints() const -{ - if (m_cached_point_count == 0) - { - boost::uint64_t npoints = getNumPoints(); - } - return m_cached_max_points; -} - - -boost::uint32_t Reader::fetchPcid() const -{ - boost::uint32_t pcid = 0; - - if (m_pcid) return m_pcid; - - log()->get(logDEBUG) << "Fetching pcid ..." << std::endl; - - std::ostringstream oss; - oss << "SELECT PC_Typmod_Pcid(a.atttypmod) AS pcid "; - oss << "FROM pg_class c, pg_attribute a "; - oss << "WHERE c.relname = '" << m_table_name << "' "; - oss << "AND a.attname = '" << m_column_name << "' "; - oss << "AND c.oid = a.attrelid"; - - char *pcid_str(0); - pcid_str = pg_query_once(m_session, oss.str()); - - if (! pcid_str) - { - std::ostringstream oss; - oss << "Unable to fetch pcid with column '" - << m_column_name <<"' and table '" - << m_table_name <<"'"; - throw pdal_error(oss.str()); - } - - pcid = atoi(pcid_str); - free(pcid_str); - - if (! pcid) - { - // Are pcid == 0 valid? - std::ostringstream oss; - oss << "Unable to fetch pcid with column '" - << m_column_name <<"' and table '" - << m_table_name <<"'"; - throw pdal_error(oss.str()); - } - - - log()->get(logDEBUG) << " got pcid = " << pcid << std::endl; - - m_pcid = pcid; - return pcid; -} - -pdal::Schema Reader::fetchSchema() const -{ - log()->get(logDEBUG) << "Fetching schema object" << std::endl; - - boost::uint32_t pcid = fetchPcid(); - - std::ostringstream oss; - oss << "SELECT schema FROM pointcloud_formats WHERE pcid = " << pcid; - - char *xml_str = pg_query_once(m_session, oss.str()); - if (!xml_str) - { - throw pdal_error("Unable to fetch schema from `pointcloud_formats`"); - } - std::string xml = std::string(xml_str); - free(xml_str); - - Schema schema = Schema::from_xml(xml); - - schema::index_by_index const& dims = schema.getDimensions().get(); - - for (schema::index_by_index::const_iterator iter = dims.begin(); iter != dims.end(); ++iter) - { - // For dimensions that do not have namespaces, we'll set the namespace - // to the namespace of the current stage - - if (iter->getNamespace().size() == 0) - { - log()->get(logDEBUG4) << "setting namespace for dimension " << iter->getName() << " to " << getName() << std::endl; - - - Dimension d(*iter); - if (iter->getUUID().is_nil()) - { - d.createUUID(); - } - d.setNamespace(getName()); - schema.setDimension(d); - } - } - - return schema; -} - -pdal::SpatialReference Reader::fetchSpatialReference() const -{ - // Fetch the WKT for the SRID to set the coordinate system of this stage - log()->get(logDEBUG) << "Fetching SRID ..." << std::endl; - - boost::uint32_t pcid = fetchPcid(); - - // query_oss << "select ST_SRID(query.extent)::integer as code from (" << query << ") as query"; - // query_oss << "SELECT ST_SRID(extent)::integer as code from cloud"; - - std::ostringstream oss; - oss << "SELECT srid FROM pointcloud_formats WHERE pcid = " << pcid; - - char *srid_str = pg_query_once(m_session, oss.str()); - if (! srid_str) - throw pdal_error("Unable to fetch srid for this table and column"); - - boost::int32_t srid = atoi(srid_str); - - log()->get(logDEBUG) << " got SRID = " << srid << std::endl; - - oss.str(""); - oss << "EPSG:" << srid; - - if (srid >= 0) - return pdal::SpatialReference(oss.str()); - else - return pdal::SpatialReference(); -} - - -pdal::StageSequentialIterator* Reader::createSequentialIterator(PointBuffer& buffer) const -{ - return new pdal::drivers::pgpointcloud::iterators::sequential::Iterator(*this, buffer); -} - -//********************************************************************************* -// pdal.drivers.pgpointcloud.iterators.sequential.Iterator -// -// The iterator controls the actual reading of features, via calls to -// -// boost::uint64_t skipImpl(boost::uint64_t count) -// bool atEndImpl() const -// boost::uint32_t readBufferImpl(PointBuffer& data) -// -//********************************************************************************* - -namespace iterators -{ -namespace sequential -{ - -Iterator::Iterator(const pdal::drivers::pgpointcloud::Reader& reader, PointBuffer& buffer) - : pdal::StageSequentialIterator(buffer) - , m_reader(reader) - , m_at_end(false) - , m_buffer(NULL) - , m_buffer_position(0) - , m_cursor(false) - , m_patch_hex(0) - , m_patch_npoints(0) - , m_session(NULL) - , m_dimension_map(NULL) - , m_cur_row(0) - , m_cur_nrows(0) - , m_cur_result(NULL) -{ - pdal::Options const& options = reader.getOptions(); - std::string const& connection = options.getValueOrThrow("connection"); - m_session = pg_connect(connection); - return; -} - -Iterator::~Iterator() -{ - if (m_session) - { - PQfinish(m_session); - m_session = NULL; - } - - if (m_cur_result) - { - PQclear(m_cur_result); - m_cur_result = NULL; - } - - if (m_dimension_map) - delete m_dimension_map; - - if (m_buffer) - delete m_buffer; -} - - -const pdal::drivers::pgpointcloud::Reader& Iterator::getReader() const -{ - return m_reader; -} - - -boost::uint64_t Iterator::skipImpl(boost::uint64_t count) -{ - uint64_t skipped = 0; - do - { - uint32_t bufferCount = m_buffer->getNumPoints() - m_buffer_position; - - // This may advance the position past the end of the buffer, but - // that causes no problems. - m_buffer_position += count; - - // The most we can skip this time through the loop is the amount left - // in the buffer. - bufferCount = std::min(count, (uint64_t)bufferCount); - skipped += bufferCount; - count -= bufferCount; - - // Refill the buffer and try again. - if (count && !NextBuffer()) - break; - } while (count); - return skipped; -} - - -bool Iterator::atEndImpl() const -{ - getReader().log()->get(logDEBUG) << "atEndImpl called" << std::endl; - // return true; - return m_at_end; -} - -bool Iterator::CursorSetup() -{ - std::ostringstream oss; - oss << "DECLARE cur CURSOR FOR " << getReader().getDataQuery(); - pg_begin(m_session); - pg_execute(m_session, oss.str()); - m_cursor = true; - - getReader().log()->get(logDEBUG) << "SQL cursor prepared: " << oss.str() << std::endl; - return true; -} - -bool Iterator::CursorTeardown() -{ - pg_execute(m_session, "CLOSE cur"); - pg_commit(m_session); - m_cursor = false; - getReader().log()->get(logDEBUG) << "SQL cursor closed." << std::endl; - return true; -} - -bool Iterator::NextBuffer() -{ - m_buffer_position = 0; - if (! m_cursor) - CursorSetup(); - - if (m_cur_row >= m_cur_nrows || ! m_cur_result) - { - static std::string fetch = "FETCH 2 FROM cur"; - if (m_cur_result) PQclear(m_cur_result); - m_cur_result = pg_query_result(m_session, fetch); - bool logOutput = getReader().log()->getLevel() > logDEBUG3; - if (logOutput) - getReader().log()->get(logDEBUG3) << "SQL: " << fetch << std::endl; - if (PQresultStatus(m_cur_result) != PGRES_TUPLES_OK || PQntuples(m_cur_result) == 0) - { - PQclear(m_cur_result); - m_cur_result = NULL; - CursorTeardown(); - return false; - } - - m_cur_row = 0; - m_cur_nrows = PQntuples(m_cur_result); - } - - m_patch_hex = PQgetvalue(m_cur_result, m_cur_row, 0); - m_patch_npoints = atoi(PQgetvalue(m_cur_result, m_cur_row, 1)); - - m_cur_row++; - return true; -} - -static inline void hex_string_to_binary(char const* source, - std::vector& output, - std::string::size_type offset) -{ - // Stolen from http://stackoverflow.com/questions/7363774/c-converting-binary-data-to-a-hex-string-and-back - static int nibbles[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15 }; - std::vector retval; - - std::size_t len = std::strlen(source); - for (std::size_t i = offset; i < len; i+=2) { - // for (std::string::const_iterator it = source.begin()+offset; it < source.end(); it += 2) { - unsigned char v = 0; - if (::isxdigit(source[i])) - v = (unsigned char)nibbles[source[i] - '0'] << 4; - if (i + 1 < len && ::isxdigit(source[i+1])) - v += (unsigned char)nibbles[source[i+1] - '0']; - output.push_back(v); - } -} - -boost::uint32_t Iterator::readBufferImpl(PointBuffer& user_buffer) -{ - getReader().log()->get(logDEBUG) << "readBufferImpl called with PointBuffer filled to (" << user_buffer.getNumPoints() << "/" << user_buffer.getCapacity() << ") points" << std::endl; - - // First time through, create the SQL statement, allocate holding pens - // and fire it off! - if (! m_cursor) - { - CursorSetup(); - } - - std::vector binary_data; - // Is the cache for patches ready? - if (! m_buffer) - { - uint32_t max_points = getReader().getMaxPoints(); - m_buffer = new pdal::PointBuffer(getReader().getSchema(), max_points); - m_buffer->setNumPoints(0); - m_buffer_position = 0; - binary_data.reserve(max_points * getReader().getSchema().getByteSize()); - getReader().log()->get(logDEBUG2) << "allocated a cached point buffer with capacity of " << max_points << std::endl; - } - - // Create a dimension map if we don't already have one - if (m_buffer && ! m_dimension_map) - { - m_dimension_map = m_buffer->getSchema().mapDimensions(user_buffer.getSchema()); - } - - boost::uint32_t num_loops = 0; - // Read from the SQL statement until we run out of blocks, or break the loop - // when we've filled up the user data buffer. - - while (true) - { - // User buffer is full? We need to get out of this loop and - // let the writer decide what to do next. - if (user_buffer.getNumPoints() == user_buffer.getCapacity()) - { - getReader().log()->get(logDEBUG2) << "User buffer is full, returning control to pdal core" << std::endl; - break; - } - - // If we've read all the contents of the cache buffer, get a fresh - // patch from the database - if (m_buffer_position >= m_buffer->getNumPoints()) - { - // No more patches! We're done! - if (! NextBuffer()) - { - m_at_end = true; - break; - } - bool logOutput = getReader().log()->getLevel() > logDEBUG3; - if (logOutput) - getReader().log()->get(logDEBUG3) << "Fetched a patch from the database" << std::endl; - - // Copy data from the hex WKB string obtained by the database - // into a pdal::PointBuffer for transfer to the user data buffer later - // - // Note: pointcloud hex WKB has some header matter we need to trim off - // before we can copy the raw data into the pdal::PointBuffer - // endian (2) + pcid (8) + compression (8) + npoints (8) = 26 characters - const boost::uint32_t trim = 26; - schema::size_type point_size = m_buffer->getSchema().getByteSize(); - - // resize our vector to 0, but we've reserved max_points * getByteSize - // for the vector so the next push_back won't have allocation costs. - binary_data.resize(0); - hex_string_to_binary(m_patch_hex, binary_data, trim); - unsigned char* data = (unsigned char*) &(binary_data.front()); - - m_buffer->setDataStride(data, 0, m_patch_npoints * point_size); - m_buffer->setNumPoints(m_patch_npoints); - - if (logOutput) - getReader().log()->get(logDEBUG3) << "Copied patch into cache, npoints = " << m_patch_npoints << std::endl; - } - - // Much many more points do we have to process in this cache? - boost::uint32_t points_in_cache = m_buffer->getNumPoints() - m_buffer_position; - // How much space is left in the user buffer? - boost::uint32_t space_in_user_buffer = user_buffer.getCapacity() - user_buffer.getNumPoints(); - boost::uint32_t points_to_copy = 0; - // If there's space, put the whole cache into the user buffer, - if (space_in_user_buffer > points_in_cache) - { - points_to_copy = points_in_cache; - } - // otherwise, just fill the buffer to full. - else - { - points_to_copy = space_in_user_buffer; - } - - bool logOutput = getReader().log()->getLevel() > logDEBUG3; - - if (logOutput) - { - getReader().log()->get(logDEBUG3) << "space_in_user_buffer = " << space_in_user_buffer << std::endl; - getReader().log()->get(logDEBUG3) << "points_in_cache = " << points_in_cache << std::endl; - getReader().log()->get(logDEBUG3) << "points_to_copy = " << points_to_copy << std::endl; - getReader().log()->get(logDEBUG3) << "m_buffer_position = " << m_buffer_position << std::endl; - getReader().log()->get(logDEBUG3) << "user_buffer.getNumPoints() = " << user_buffer.getNumPoints() << std::endl; - } - - // Do the copying from cache to user buffer - // To do: this should be more tolerant of variations in source/dest schema - PointBuffer::copyLikeDimensions(*m_buffer, user_buffer, - *m_dimension_map, - m_buffer_position, user_buffer.getNumPoints(), - points_to_copy); - - // Update the buffers regarding how full/empty they are - m_buffer_position += points_to_copy; - user_buffer.setNumPoints(user_buffer.getNumPoints()+points_to_copy); - - num_loops++; - getReader().log()->get(logDEBUG2) << "User buffer filling loop, iteration " << num_loops << std::endl; - } - - return user_buffer.getNumPoints(); -} - - - -} -} // pdal.drivers.pgpointcloud.iterators.sequential.Iterator - -} // pgpointcloud -} // drivers -} // pdal diff --git a/src/drivers/text/Writer.cpp b/src/drivers/text/Writer.cpp index ea4c6376e0..6b07d0b1e2 100644 --- a/src/drivers/text/Writer.cpp +++ b/src/drivers/text/Writer.cpp @@ -45,11 +45,6 @@ #include #include -#ifdef USE_PDAL_PLUGIN_TEXT -//MAKE_WRITER_CREATOR(textWriter, pdal::drivers::text::Writer) -CREATE_WRITER_PLUGIN(textWriter, pdal::drivers::text::Writer) -#endif - namespace pdal { diff --git a/src/kernel/KernelFactory.cpp b/src/kernel/KernelFactory.cpp index 70dd258cdc..9ab359c9a8 100644 --- a/src/kernel/KernelFactory.cpp +++ b/src/kernel/KernelFactory.cpp @@ -229,14 +229,13 @@ void KernelFactory::registerPlugin(std::string const& filename) std::string base = basename.string(); - std::string foo = boost::algorithm::ireplace_first_copy(base, "libpdal_plugin_", ""); - std::string foobar = foo.substr(0, foo.find_last_of("_")); - if (boost::iequals(foobar, "kernel")) + std::string pluginName = boost::algorithm::ireplace_first_copy(base, "libpdal_plugin_", ""); + std::string pluginType = pluginName.substr(0, pluginName.find_last_of("_")); + if (boost::iequals(pluginType, "kernel")) { - std::string registerMethodName = "PDALRegister_" + \ - boost::algorithm::ireplace_first_copy(base, "libpdal_plugin_", ""); + std::string registerMethodName = "PDALRegister_" + pluginName; - std::string versionMethodName = "PDALRegister_version_" + base.substr(base.find_last_of("_")+1, base.size()); + std::string versionMethodName = "PDALRegister_version_" + pluginName; Utils::registerPlugin((void*)this, filename, registerMethodName, versionMethodName); } diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 4952c4d851..656fe1250a 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -5,233 +5,120 @@ # Copyright (c) 2009 Mateusz Loskot # ############################################################################### -SET(PDAL_UNIT_TEST pdal_test) configure_file( TestConfig.hpp.in - "${CMAKE_CURRENT_BINARY_DIR}/TestConfig.hpp") - + "${CMAKE_CURRENT_BINARY_DIR}/TestConfig.hpp" +) -if (LIBXML2_FOUND) -SET (PDAL_UNITTEST_XMLSCHEMA_TEST XMLSchemaTest.cpp) +if (PDAL_HAVE_LAZPERF) + SET(PDAL_LAZPERF_SRC CompressionTest.cpp) endif() SET(PDAL_UNITTEST_TEST_SRC +======= +# +# sources for the base library +# +set(PDAL_UNITTEST_BASE_SRCS BoundsTest.cpp - drivers/bpf/BPFTest.cpp - drivers/buffer/BufferTest.cpp -# drivers/caris/CarisReaderTest.cpp - filters/ChipperTest.cpp ConfigTest.cpp - filters/CropFilterTest.cpp - filters/DecimationFilterTest.cpp - filters/FerryFilterTest.cpp EnvironmentTest.cpp - drivers/faux/FauxReaderTest.cpp FileUtilsTest.cpp - filters/HexbinFilterTest.cpp - filters/MergeTest.cpp - drivers/las/LasReaderTest.cpp - drivers/las/LasWriterTest.cpp + GDALUtilsTest.cpp LogTest.cpp MetadataTest.cpp OptionsTest.cpp PipelineManagerTest.cpp - PointContextTest.cpp PointBufferTest.cpp - drivers/qfit/QFITReaderTest.cpp - filters/ReprojectionFilterTest.cpp - filters/SortFilterTest.cpp - drivers/sbet/SbetReaderTest.cpp - drivers/sbet/SbetWriterTest.cpp + PointContextTest.cpp SpatialReferenceTest.cpp - filters/SplitterTest.cpp # StageFactoryTest.cpp - filters/StatsFilterTest.cpp StreamFactoryTest.cpp SupportTest.cpp -# drivers/terrasolid/TerraSolidReaderTest.cpp -# drivers/text/TextWriterTest.cpp UserCallbackTest.cpp UtilsTest.cpp ${PDAL_UNITTEST_XMLSCHEMA_TEST} + ${PDAL_LAZPERF_SRC} ) +) -if(WITH_APPS) - if(LIBXML2_FOUND) - list(APPEND PDAL_UNITTEST_TEST_SRC -# apps/pcinfoTest.cpp - ) - endif(LIBXML2_FOUND) +# +# sources for the native drivers +# +set(PDAL_UNITTEST_DRIVERS_SRCS + drivers/bpf/BPFTest.cpp + drivers/buffer/BufferTest.cpp +# drivers/caris/CarisReaderTest.cpp + drivers/faux/FauxReaderTest.cpp + drivers/las/LasReaderTest.cpp + drivers/las/LasWriterTest.cpp + drivers/qfit/QFITReaderTest.cpp + drivers/sbet/SbetReaderTest.cpp + drivers/sbet/SbetWriterTest.cpp +# drivers/terrasolid/TerraSolidReaderTest.cpp +# drivers/text/TextWriterTest.cpp +) - list(APPEND PDAL_UNITTEST_TEST_SRC - apps/pc2pcTest.cpp -# apps/pcpipelineTest.cpp - ) -endif(WITH_APPS) +# +# sources for the native filters +# +set(PDAL_UNITTEST_FILTERS_SRCS + filters/ChipperTest.cpp + filters/ColorizationFilterTest.cpp + filters/CropFilterTest.cpp + filters/DecimationFilterTest.cpp + filters/FerryFilterTest.cpp + filters/MergeTest.cpp + filters/ReprojectionFilterTest.cpp + filters/SortFilterTest.cpp + filters/SplitterTest.cpp + filters/StatsFilterTest.cpp +) +# +# sources for plang +# set(PDAL_PLANG_TEST_SRC plang/PLangTest.cpp plang/PredicateFilterTest.cpp plang/ProgrammableFilterTest.cpp ) -SET(PDAL_UNITTEST_TEST_INC - ) - -SET(PDAL_UNITTEST_CONFIG_SRC - Support.cpp - TestConfig.cpp - main.cpp - ) - -SET(PDAL_UNITTEST_CONFIG_INC -# Support.hpp -# TestConfig.hpp - ) - - -if (WITH_ORACLE) -if (NOT USE_PDAL_PLUGIN_OCI) - set(PDAL_OCI_TEST_CPP drivers/oci/OCITest.cpp) - - FOREACH(file ${PDAL_OCI_TEST_CPP}) - SET(PDAL_UNITTEST_TEST_SRC "${PDAL_UNITTEST_TEST_SRC};${file}" CACHE INTERNAL "source files for test") - ENDFOREACH(file) -endif() - -endif (WITH_ORACLE) - -if (WITH_SQLITE) - if (NOT USE_PDAL_PLUGIN_SQLITE) - set(PDAL_SQLITE_TEST_CPP drivers/sqlite/SqliteTest.cpp) - - FOREACH(file ${PDAL_SQLITE_TEST_CPP}) - SET(PDAL_UNITTEST_TEST_SRC "${PDAL_UNITTEST_TEST_SRC};${file}" - CACHE INTERNAL "source files for test") - ENDFOREACH(file) - endif() -endif (WITH_SQLITE) - -if (WITH_NITRO) - set(PDAL_GDAL_TEST_CPP - GDALUtilsTest.cpp - filters/ColorizationFilterTest.cpp - drivers/nitf/NitfReaderTest.cpp - ) - - FOREACH(file ${PDAL_GDAL_TEST_CPP}) - SET(PDAL_UNITTEST_TEST_SRC "${PDAL_UNITTEST_TEST_SRC};${file}" - CACHE INTERNAL "source files for test") - ENDFOREACH(file) - set(PDAL_NITRO_TEST_CPP - drivers/nitf/NitfWriterTest.cpp - ) - - FOREACH(file ${PDAL_NITRO_TEST_CPP}) - SET(PDAL_UNITTEST_TEST_SRC "${PDAL_UNITTEST_TEST_SRC};${file}" - CACHE INTERNAL "source files for test") - ENDFOREACH(file) -endif (WITH_NITRO) - - -# Removed WITH_PCL/WITH_PCL_TEST conditional - StageFactory now tests for PCL -# internally. This will eventually be moved to plugins/pcl/test. -set(PDAL_PCL_TEST_CPP - filters/PCLBlockFilterTest.cpp +# +# the combined test sources +# +set(PDAL_UNITTEST_SRCS + ${PDAL_UNITTEST_BASE_SRCS} + ${PDAL_UNITTEST_DRIVERS_SRCS} + ${PDAL_UNITTEST_FILTERS_SRCS} + ${PDAL_PLANG_TEST_SRC} ) -FOREACH(file ${PDAL_PCL_TEST_CPP}) - SET(PDAL_UNITTEST_TEST_SRC "${PDAL_UNITTEST_TEST_SRC};${file}" - CACHE INTERNAL "source files for test") -ENDFOREACH(file) - -if (WITH_HDF5) - set(PDAL_ICEBRIDGE_TEST_CPP - drivers/icebridge/IcebridgeReaderTest.cpp - ) - - FOREACH(file ${PDAL_ICEBRIDGE_TEST_CPP}) - SET(PDAL_UNITTEST_TEST_SRC "${PDAL_UNITTEST_TEST_SRC};${file}" - CACHE INTERNAL "source files for test") - ENDFOREACH(file) -endif(WITH_HDF5) - -if (WITH_PGPOINTCLOUD AND WITH_PGPOINTCLOUD_TESTS) - set(PDAL_PGPOINTCLOUD_TEST_CPP - drivers/pgpointcloud/PgpointcloudWriterTest.cpp - ) - - set(PGPOINTCLOUD_TEST_DB_HOST localhost CACHE STRING "Postgres test database host") - set(PGPOINTCLOUD_TEST_DB_PORT 5432 CACHE STRING "Postgres test database port") - set(PGPOINTCLOUD_TEST_DB_NAME pdal_test CACHE STRING - "Postgres test database name, must exist and must be able to create databases") - set(PGPOINTCLOUD_TEST_DB_TEMPNAME pdal_test_tmp CACHE STRING "Postgres test database temp database name") - - configure_file( - drivers/pgpointcloud/Pgtest-Support.hpp.in - ${CMAKE_CURRENT_BINARY_DIR}/drivers/pgpointcloud/Pgtest-Support.hpp - ) - - set(PDAL_UNITTEST_TEST_SRC - ${PDAL_UNITTEST_TEST_SRC} - ${PDAL_PGPOINTCLOUD_TEST_CPP} - CACHE INTERNAL "source files for test" +# +# conditionally append apps/libxml2 sources +# +if(WITH_APPS) + if(LIBXML2_FOUND) + list(APPEND PDAL_UNITTEST_SRCS +# apps/pcinfoTest.cpp ) -endif (WITH_PGPOINTCLOUD AND WITH_PGPOINTCLOUD_TESTS) - -set(PDAL_UNITTEST_SOURCES "") -FOREACH(file ${PDAL_UNITTEST_TEST_SRC}) - SET(PDAL_UNITTEST_SOURCES "${PDAL_UNITTEST_SOURCES};${file}" - CACHE INTERNAL "source files for test") -ENDFOREACH(file) + endif(LIBXML2_FOUND) -FOREACH(file ${PDAL_PLANG_TEST_SRC}) - SET(PDAL_UNITTEST_SOURCES "${PDAL_UNITTEST_SOURCES};${file}" - CACHE INTERNAL "source files for test") -ENDFOREACH(file) - -FOREACH(file ${PDAL_UNITTEST_CONFIG_SRC}) - SET(PDAL_UNITTEST_SOURCES "${PDAL_UNITTEST_SOURCES};${file}" - CACHE INTERNAL "source files for test") -ENDFOREACH(file) - -FOREACH(file ${PDAL_UNITTEST_CONFIG_INC}) - SET(PDAL_UNITTEST_SOURCES "${PDAL_UNITTEST_SOURCES};${file}" - CACHE INTERNAL "source files for test") -ENDFOREACH(file) + list(APPEND PDAL_UNITTEST_SRCS + apps/pc2pcTest.cpp +# apps/pcpipelineTest.cpp + ) +endif(WITH_APPS) -source_group("Header Files" FILES ${PDAL_UNITTEST_TEST_INC}) -source_group("Header Files\\config" FILES ${PDAL_UNITTEST_CONFIG_INC}) -source_group("Source Files" FILES ${PDAL_UNITTEST_TEST_SRC}) -source_group("Source Files\\config" FILES ${PDAL_UNITTEST_CONFIG_SRC}) +if(LIBXML2_FOUND) + list(APPEND PDAL_UNITTEST_SRCS XMLSchemaTest.cpp) +endif() -INCLUDE_DIRECTORIES( - . - ${CMAKE_CURRENT_BINARY_DIR} - ../../include +include_directories( + ${PROJECT_SOURCE_DIR}/include ${GDAL_INCLUDE_DIR} ${GEOTIFF_INCLUDE_DIR} - ${ORACLE_INCLUDE_DIR}) - -ADD_EXECUTABLE(${PDAL_UNIT_TEST} ${PDAL_UNITTEST_SOURCES}) - -set_target_properties(${PDAL_UNIT_TEST} PROPERTIES COMPILE_DEFINITIONS - PDAL_DLL_IMPORT) - -if(WIN32) - add_definitions("-DPDAL_DLL_EXPORT=1") - if (MSVC) - #add_definitions("-DBOOST_TEST_DYN_LINK") - endif() -else() - add_definitions("-DBOOST_TEST_DYN_LINK") -endif() - -TARGET_LINK_LIBRARIES( ${PDAL_UNIT_TEST} ${PDAL_LINKAGE} - ${PDAL_LIB_NAME} ) - -TARGET_LINK_LIBRARIES( ${PDAL_UNIT_TEST} ${BOOST_LINKAGE} - ${Boost_LIBRARIES} ) - -ADD_TEST(pdal_test "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/pdal_test" "${PROJECT_SOURCE_DIR}/test/data" --catch_system_errors=no) +) +set(deps ${PDAL_LIB_NAME}) +PDAL_ADD_TEST(pdal_test "${PDAL_UNITTEST_SRCS}" "${deps}") diff --git a/test/unit/CompressionTest.cpp b/test/unit/CompressionTest.cpp new file mode 100644 index 0000000000..43d1394c22 --- /dev/null +++ b/test/unit/CompressionTest.cpp @@ -0,0 +1,219 @@ +/****************************************************************************** +* Copyright (c) 2014, Howard Butler (howard@hobu.co) +* +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following +* conditions are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in +* the documentation and/or other materials provided +* with the distribution. +* * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the +* names of its contributors may be used to endorse or promote +* products derived from this software without specific prior +* written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +* OF SUCH DAMAGE. +****************************************************************************/ + +#include "UnitTest.hpp" + +#include +#include +#include + +#include "Support.hpp" +#include +#include +#include +#include +#include +#include + +struct SQLiteTestStream { + SQLiteTestStream() : buf(), idx(0) {} + + void putBytes(const unsigned char* b, size_t len) { + while(len --) { + buf.push_back(*b++); + } + } + + void putByte(const unsigned char b) { + buf.push_back(b); + } + + unsigned char getByte() { + return buf[idx++]; + } + + void getBytes(unsigned char *b, int len) { + for (int i = 0 ; i < len ; i ++) { + b[i] = getByte(); + } + } + + std::vector buf; + size_t idx; +}; + +BOOST_AUTO_TEST_SUITE(CompressionTest) + + + +BOOST_AUTO_TEST_CASE(test_compress_file) +{ + using namespace pdal; + + const std::string file(Support::datapath("las/1.2-with-color.las")); + + const pdal::Option opt_filename("filename", file); + pdal::Options opts; + opts.add(opt_filename); + + pdal::drivers::las::Reader reader; + reader.setOptions(opts); + + PointContext ctx; + reader.prepare(ctx); + PointBufferSet buffers = reader.execute(ctx); + PointBufferPtr buffer = *buffers.begin(); + + BOOST_CHECK_EQUAL(ctx.pointSize(), 52); + SQLiteTestStream s; + compression::Compress(ctx, *buffer, s, compression::CompressionType::Lazperf, 0, 0); + BOOST_CHECK_EQUAL(buffer->getBytes().size(), 55380); + BOOST_CHECK_EQUAL(s.buf.size(), 30945); + + SQLiteTestStream s2; + s2.buf = s.buf; + PointBufferPtr b = compression::Decompress(ctx, s2, 11, compression::CompressionType::Lazperf); + + BOOST_CHECK_EQUAL(b->size(), 11); + BOOST_CHECK_EQUAL(b->getBytes().size(), 52 * 11); + + boost::uint16_t r = b->getFieldAs(Dimension::Id::Red, 10); + BOOST_CHECK_EQUAL(r, 64u); + boost::int32_t x = b->getFieldAs(Dimension::Id::X, 10); + BOOST_CHECK_EQUAL(x, 636038); + double xd = b->getFieldAs(Dimension::Id::X, 10); + BOOST_CHECK_CLOSE(xd, 636037.53, 0.001); + boost::int32_t y = b->getFieldAs(Dimension::Id::Y, 10); + BOOST_CHECK_EQUAL(y, 849338); +} + + +BOOST_AUTO_TEST_CASE(test_compress_copied_buffer) +{ + using namespace pdal; + + + const std::string file(Support::datapath("las/1.2-with-color.las")); + const pdal::Option opt_filename("filename", file); + pdal::Options opts; + opts.add(opt_filename); + pdal::drivers::las::Reader reader; + reader.setOptions(opts); + PointContext fctx; + reader.prepare(fctx); + PointBufferSet buffers = reader.execute(fctx); + PointBufferPtr buffer = *buffers.begin(); + + PointContext ctx; + ctx.registerDim(Dimension::Id::X); + ctx.registerDim(Dimension::Id::Y); + ctx.registerDim(Dimension::Id::Z); + PointBuffer new_buffer(ctx); +// + for (PointId i = 0; i < buffer->size(); ++i) + { + new_buffer.setField(Dimension::Id::X, i, buffer->getFieldAs(Dimension::Id::X, i)); + new_buffer.setField(Dimension::Id::Y, i, buffer->getFieldAs(Dimension::Id::Y, i)); + new_buffer.setField(Dimension::Id::Z, i, buffer->getFieldAs(Dimension::Id::Z, i)); + } + SQLiteTestStream s; + compression::Compress(ctx, new_buffer, s, compression::CompressionType::Lazperf, 0, 0); + SQLiteTestStream s2; + s2.buf = s.buf; + PointBufferPtr b = compression::Decompress(ctx, s2, 11, compression::CompressionType::Lazperf); + + boost::int32_t y = b->getFieldAs(Dimension::Id::Y, 10); + BOOST_CHECK_EQUAL(y, 849338); + boost::int32_t x = b->getFieldAs(Dimension::Id::X, 10); + BOOST_CHECK_EQUAL(x, 636038); + double xd = b->getFieldAs(Dimension::Id::X, 10); + BOOST_CHECK_CLOSE(xd, 636037.53, 0.001); + +} + + + +BOOST_AUTO_TEST_CASE(test_compress_simple_buffer) +{ + using namespace pdal; + + PointContext ctx; + ctx.registerDim(Dimension::Id::X); + ctx.registerDim(Dimension::Id::Y); + ctx.registerDim(Dimension::Id::Z); + ctx.registerDim(Dimension::Id::GpsTime); + ctx.registerDim(Dimension::Id::Intensity); + ctx.registerDim(Dimension::Id::PointSourceId); + ctx.registerDim(Dimension::Id::ScanAngleRank); + ctx.registerDim(Dimension::Id::Red); + ctx.registerDim(Dimension::Id::Green); + ctx.registerDim(Dimension::Id::Blue); + ctx.registerDim(Dimension::Id::ReturnNumber); + ctx.registerDim(Dimension::Id::NumberOfReturns); + ctx.registerDim(Dimension::Id::ScanDirectionFlag); + ctx.registerDim(Dimension::Id::EdgeOfFlightLine); + ctx.registerDim(Dimension::Id::Classification); + ctx.registerDim(Dimension::Id::UserData); + PointBuffer buffer(ctx); + for (PointId i = 0; i < 100; ++i) + { + buffer.setField(Dimension::Id::X, i, i); + buffer.setField(Dimension::Id::Y, i, i+100); + buffer.setField(Dimension::Id::Z, i, i+1000); + buffer.setField(Dimension::Id::GpsTime, i, i+10000); + buffer.setField(Dimension::Id::Intensity, i, 600); + buffer.setField(Dimension::Id::PointSourceId, i, 60); + buffer.setField(Dimension::Id::ScanAngleRank, i, 1003.23); + buffer.setField(Dimension::Id::Red, i, 26); + buffer.setField(Dimension::Id::Green, i, 42); + buffer.setField(Dimension::Id::Blue, i, 255); + buffer.setField(Dimension::Id::ReturnNumber, i, 2); + buffer.setField(Dimension::Id::NumberOfReturns, i, 2); + buffer.setField(Dimension::Id::ScanDirectionFlag, i, 1); + buffer.setField(Dimension::Id::EdgeOfFlightLine, i, 1); + buffer.setField(Dimension::Id::Classification, i, 2); + buffer.setField(Dimension::Id::UserData, i, 25); + } + + SQLiteTestStream s; + compression::Compress(ctx, buffer, s, compression::CompressionType::Lazperf, 0, 0); + SQLiteTestStream s2; + s2.buf = s.buf; + PointBufferPtr b = compression::Decompress(ctx, s2, 11, compression::CompressionType::Lazperf); +// std::cout << *b << std::endl; + boost::uint16_t r = b->getFieldAs(Dimension::Id::Red, 10); + BOOST_CHECK_EQUAL(r, 26u); +} +BOOST_AUTO_TEST_SUITE_END() + diff --git a/test/unit/MetadataTest.cpp b/test/unit/MetadataTest.cpp index 18d84f3988..a3a31a6db7 100644 --- a/test/unit/MetadataTest.cpp +++ b/test/unit/MetadataTest.cpp @@ -142,6 +142,26 @@ BOOST_AUTO_TEST_CASE(test_construction) } } +BOOST_AUTO_TEST_CASE(typed_value) +{ + MetadataNode m; + MetadataNode m2 = m.add("name", 127); + + BOOST_CHECK_EQUAL(127, m2.value()); + + double d = 123.45; + MetadataNode m3 = m.addEncoded("name", (unsigned char *)&d, sizeof(d)); + BOOST_CHECK_CLOSE(d, m3.value(), .00001); + BOOST_CHECK_EQUAL("zczMzMzcXkA=", m3.value()); + + MetadataNode m4 = m.add("name", "65539"); + BOOST_CHECK_EQUAL(65539, m4.value()); + + auto ctx = Utils::redirect(std::cerr); + BOOST_CHECK_EQUAL(0, m4.value()); + Utils::restore(std::cerr, ctx); +} + BOOST_AUTO_TEST_CASE(test_construction_with_srs) { diff --git a/test/unit/drivers/las/LasWriterTest.cpp b/test/unit/drivers/las/LasWriterTest.cpp index f5c6e53ce7..155472eda9 100644 --- a/test/unit/drivers/las/LasWriterTest.cpp +++ b/test/unit/drivers/las/LasWriterTest.cpp @@ -41,14 +41,29 @@ #include #include -#include +#include #include +#include #include #include "StageTester.hpp" #include "Support.hpp" +namespace pdal +{ + +//ABELL - Should probably be moved to its own file. +class LasTester +{ +public: + template + static T headerVal(drivers::las::Writer& w, const std::string& s) + { return w.headerVal(s); } +}; + +} // namespace pdal + using namespace pdal; BOOST_AUTO_TEST_SUITE(LasWriterTest) @@ -100,6 +115,47 @@ BOOST_AUTO_TEST_CASE(auto_offset) FileUtils::deleteFile(FILENAME); } +BOOST_AUTO_TEST_CASE(metadata_options) +{ + Options ops; + + Option metadataOp("metadata", ""); + + Options metadataOps; + metadataOps.add("format", 4); + metadataOps.add("software_id", "MySoftwareId"); + metadataOps.add("system_id", "FORWARD"); + metadataOps.add("minor_version", "forward"); + metadataOp.setOptions(metadataOps); + ops.add(metadataOp); + + drivers::las::Writer writer; + writer.setOptions(ops); + + PointContext ctx; + writer.prepare(ctx); + + MetadataNode m = writer.getMetadata(); + m.add("minor_version", 56); + + uint8_t format = + (uint8_t)LasTester::headerVal(writer, "format"); + BOOST_CHECK_EQUAL(format, 4); + std::string softwareId = + LasTester::headerVal(writer, "software_id"); + BOOST_CHECK_EQUAL(softwareId, "MySoftwareId"); + std::string systemId = + LasTester::headerVal(writer, "system_id"); + + // Since the option specifies forward and there is not associated + // metadata, the value should be the default. + BOOST_CHECK_EQUAL(systemId, drivers::las::LasHeader::SYSTEM_IDENTIFIER); + + // In this case, we should have metadata to override the default. + uint8_t minorVersion = + (uint8_t)LasTester::headerVal(writer, "minor_version"); + BOOST_CHECK_EQUAL(minorVersion, 56); +} //ABELL /** diff --git a/test/unit/drivers/text/TextWriterTest.cpp b/test/unit/drivers/text/TextWriterTest.cpp index a820ae3ba1..a2b7069bdc 100644 --- a/test/unit/drivers/text/TextWriterTest.cpp +++ b/test/unit/drivers/text/TextWriterTest.cpp @@ -48,7 +48,6 @@ using namespace pdal; BOOST_AUTO_TEST_SUITE(TextWriterTest) -#ifndef USE_PDAL_PLUGIN_TEXT BOOST_AUTO_TEST_CASE(TextWriterTest_test_1) { @@ -140,6 +139,5 @@ BOOST_AUTO_TEST_CASE(TextWriterTest_geojson) FileUtils::deleteFile(Support::temppath(output)); } } -#endif BOOST_AUTO_TEST_SUITE_END()