Catalina 10.15:
VMIMAGE: 'macOS-10.15'
OSX_VERSION: '10.15'
- Mojave 10.14:
- VMIMAGE: 'macOS-10.14'
- OSX_VERSION: '10.14'
+ Big Sur 11:
+ VMIMAGE: 'macOS-11'
+ OSX_VERSION: '11'
timeoutInMinutes: 0
variables:
BUILD_DIR: '$(Agent.WorkFolder)/build'
PLATFORM: x86
TAG: winx86
GENERATOR: "'Visual Studio 16 2019' -A Win32"
- VCPKGCOMMIT: 2bc10eae2fb0b8c7c098325c4e9d82aa5d0329d9
+ VCPKGCOMMIT: 5568f110b509a9fd90711978a7cb76bae75bb092
Winx64:
PLATFORM: x64
TAG: winx64
- Regex: '^<(OpenGL|(GL(UT)?/))'
Priority: 450
# Matches all std includes. Match them before any unknown include, so we can order them behind.
- - Regex: '^<[a-z]+>$'
+ - Regex: '^<[a-z_]+>$'
Priority: 900
# Any unknown include
- Regex: '.*'
RUN cd ${workspace} \
&& . "/opt/ros/${flavor}/setup.sh" \
&& catkin config --install --link-devel \
- && catkin build -j2 libpcl-all-dev --cmake-args -DWITH_OPENGL:BOOL=OFF \
+ && catkin build --no-status --verbose --summary -j2 libpcl-all-dev --cmake-args -DWITH_OPENGL:BOOL=OFF \
&& rm -fr build/libpcl-all-dev \
- && catkin build --start-with pcl_msgs
+ && catkin build --no-status --verbose --summary --start-with pcl_msgs
-Wait -PassThru; `
del c:\temp\vs_buildtools.exe;
-RUN iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')); `
- choco install cmake git --installargs 'ADD_CMAKE_TO_PATH=System' -y --no-progress
+# VCPKG requires update if Cmake version is > 3.20.5 see: https://github.com/microsoft/vcpkg-tool/pull/107
+RUN iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')); `
+ choco install cmake --version=3.20.5 --installargs 'ADD_CMAKE_TO_PATH=System' -y --no-progress; `
+ choco install git -y --no-progress
RUN git clone https://github.com/microsoft/vcpkg.git; cd vcpkg; git checkout $Env:VCPKGCOMMIT;
format() {
# don't use a directory with whitespace
- local whitelist="apps/3d_rec_framework apps/include apps/modeler apps/src benchmarks 2d geometry ml octree simulation stereo tracking registration gpu/containers"
+ local whitelist="apps/3d_rec_framework apps/include apps/modeler apps/src benchmarks 2d geometry ml octree simulation stereo tracking registration gpu/containers gpu/segmentation"
local PCL_DIR="${2}"
local formatter="${1}"
--- /dev/null
+# These are supported funding model platforms
+
+github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Reolace with a single Ko Fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: PointCloudLibrary
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
# ChangeList
+## = 1.12.1 (2021.12.21) =
+
+This minor release brings in a lot of enhancements in CMake thanks to @larshg and @SunBlack.
+Enjoy a lot of bug-fixes and improvements in IO and Filters.
+
+### Notable changes
+
+**New features** *added to PCL*
+
+* **[io]** Add a grabber for SICK 2D LiDAR: TiM [[#4429](https://github.com/PointCloudLibrary/pcl/pull/4429)]
+
+**Deprecation** *of public APIs, scheduled to be removed after two minor releases*
+
+* **[cuda][filters]** Add deprecation for filter getters with bool reference [[#4861](https://github.com/PointCloudLibrary/pcl/pull/4861)]
+* **[filters]** Fix keep_organized behavior in CropHull filter [[#4855](https://github.com/PointCloudLibrary/pcl/pull/4855)]
+
+**Behavior changes** *in classes, apps, or tools*
+
+* **[registration]** Fix typo in the hessian representation of NDT [[#4889](https://github.com/PointCloudLibrary/pcl/pull/4889)]
+* **[cmake]** Update PCLConfig.cmake.in to 3.10 for default policy. [[#4996](https://github.com/PointCloudLibrary/pcl/pull/4996)]
+
+**ABI changes** *that are still API compatible*
+
+* **[ml]** Wrap QMatrix in namespace pcl to resolve linker conflict with Qt6 [[#4858](https://github.com/PointCloudLibrary/pcl/pull/4858)]
+
+### Changes grouped by module
+
+#### CMake:
+
+* Add AVX for Linux & macos [[#4698](https://github.com/PointCloudLibrary/pcl/pull/4698)]
+* Update cmake to 3.10 and add CUDA language support [[#4619](https://github.com/PointCloudLibrary/pcl/pull/4619)]
+* Fix CUDA Compute Capability version detection [[#4900](https://github.com/PointCloudLibrary/pcl/pull/4900)]
+* Update pcl_find_boost to allow compilation with Boost 1.77 and 1.78 [[#4972](https://github.com/PointCloudLibrary/pcl/pull/4972)] [[#5067](https://github.com/PointCloudLibrary/pcl/pull/5067)]
+* Allow boost to be found by config files. [[#4952](https://github.com/PointCloudLibrary/pcl/pull/4952)]
+* **[behavior change]** Update PCLConfig.cmake.in to 3.10 for default policy. [[#4996](https://github.com/PointCloudLibrary/pcl/pull/4996)]
+* Allow PCL to have non-static dependencies for static builds and vice-versa [[#4390](https://github.com/PointCloudLibrary/pcl/pull/4390)]
+* Enhance finding of qhull [[#4923](https://github.com/PointCloudLibrary/pcl/pull/4923)]
+
+#### libpcl_common:
+
+* Fix: max_id size should be equal to histogram.size() - 1 [[#4934](https://github.com/PointCloudLibrary/pcl/pull/4934)]
+* Remove casts, use more auto and uindex_t in conversions.h [[#4935](https://github.com/PointCloudLibrary/pcl/pull/4935)]
+* Fix inaccurate covariance matrix computation [[#4983](https://github.com/PointCloudLibrary/pcl/pull/4983)]
+
+#### libpcl_cuda:
+
+* **[deprecation]** Add deprecation for filter getters with bool reference [[#4861](https://github.com/PointCloudLibrary/pcl/pull/4861)]
+
+#### libpcl_features:
+
+* Add `isNormalFinite` check in `ShapeContext3DEstimation` [[#4883](https://github.com/PointCloudLibrary/pcl/pull/4883)]
+
+#### libpcl_filters:
+
+* Clear the output indices in function `CropHull::applyFilters` [[#4851](https://github.com/PointCloudLibrary/pcl/pull/4851)]
+* Fix unresolved linking to Convolution [[#4845](https://github.com/PointCloudLibrary/pcl/pull/4845)]
+* **[deprecation]** Add deprecation for filter getters with bool reference [[#4861](https://github.com/PointCloudLibrary/pcl/pull/4861)]
+* NormalSpaceSampling filter: add constructor to specify `extract_removed_indices` [[#4846](https://github.com/PointCloudLibrary/pcl/pull/4846)]
+* **[deprecation]** Fix keep_organized behavior in CropHull filter [[#4855](https://github.com/PointCloudLibrary/pcl/pull/4855)]
+* Added reserve function before storing points in PointCloud in VoxelGr… [[#4938](https://github.com/PointCloudLibrary/pcl/pull/4938)]
+
+#### libpcl_io:
+
+* Higher flexibility regarding which PLY files can be read [[#4963](https://github.com/PointCloudLibrary/pcl/pull/4963)]
+* **[new feature]** Add a grabber for SICK 2D LiDAR: TiM [[#4429](https://github.com/PointCloudLibrary/pcl/pull/4429)]
+
+#### libpcl_keypoints:
+
+* Bugfix: Number of OpenMP threads was not validated, ... [[#4863](https://github.com/PointCloudLibrary/pcl/pull/4863)]
+
+#### libpcl_ml:
+
+* **[ABI break]** Wrap QMatrix in namespace pcl to resolve linker conflict with Qt6 [[#4858](https://github.com/PointCloudLibrary/pcl/pull/4858)]
+
+#### libpcl_registration:
+
+* **[behavior change]** Fix typo in the hessian representation of NDT [[#4889](https://github.com/PointCloudLibrary/pcl/pull/4889)]
+* Fix discretization bug in PPFRegistration [[#4975](https://github.com/PointCloudLibrary/pcl/pull/4975)]
+
+#### libpcl_sample_consensus:
+
+* Fix SampleConsensusModelCylinder.projectPoints and verify with test [[#4881](https://github.com/PointCloudLibrary/pcl/pull/4881)]
+
+#### libpcl_search:
+
+* Add missing include of hpp file in flann_search.h [[#4848](https://github.com/PointCloudLibrary/pcl/pull/4848)]
+
+#### libpcl_surface:
+
+* Improve logging in `multi_grid_octree_data.hpp` [[#4844](https://github.com/PointCloudLibrary/pcl/pull/4844)]
+* Fix duplicate definition error in mls [[#5049](https://github.com/PointCloudLibrary/pcl/pull/5049)]
+
+#### libpcl_visualization:
+
+* Use pixel ratio to scale mouse events on HiDpi monitors [[#4411](https://github.com/PointCloudLibrary/pcl/pull/4411)]
+* Remove declaration of updateCamera [[#4921](https://github.com/PointCloudLibrary/pcl/pull/4921)]
+
+#### PCL Docs:
+
+* Require sphinx>=3 to fix errors on readthedocs [[#5037](https://github.com/PointCloudLibrary/pcl/pull/5037)]
+
## = 1.12.0 (2021.07.07) =
PCL 1.12.0 enables custom index size and type, from `int16_t` to `uint64_t`, allowing
### ---[ PCL global CMake
-cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
if(POLICY CMP0074)
# 1. Remove with 3.12.4.
set(CMAKE_CXX_STANDARD 14 CACHE STRING "The target C++ standard. PCL requires C++14 or higher.")
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
-if(CMAKE_VERSION VERSION_LESS 3.8)
- # CMake did not have cxx_std_14 compile feature prior to 3.8
- # We use cxx_attribute_deprecated as a proxy because this feature is a part of c++14 standard
- set(PCL_CXX_COMPILE_FEATURES cxx_attribute_deprecated)
-else()
- set(PCL_CXX_COMPILE_FEATURES cxx_std_14)
-endif()
+set(PCL_CXX_COMPILE_FEATURES cxx_std_14)
+
+set(CMAKE_CUDA_STANDARD 14 CACHE STRING "The target CUDA/C++ standard. PCL requires CUDA/C++ 14 or higher.")
+set(CMAKE_CUDA_STANDARD_REQUIRED ON)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "possible configurations" FORCE)
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "build type default to RelWithDebInfo, set to Release to improve performance" FORCE)
endif()
-project(PCL VERSION 1.12.0)
+project(PCL VERSION 1.12.1)
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
### ---[ Find universal dependencies
PCL_CHECK_FOR_SSE()
endif()
-# check for AVX flags for windows
+# check for AVX flags
if(PCL_ENABLE_AVX AND "${CMAKE_CXX_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}")
include("${PCL_SOURCE_DIR}/cmake/pcl_find_avx.cmake")
PCL_CHECK_FOR_AVX()
else()
string(APPEND CMAKE_CXX_FLAGS " -Wabi")
endif()
- string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -Wno-unknown-pragmas -fno-strict-aliasing -Wno-format-extra-args -Wno-sign-compare -Wno-invalid-offsetof -Wno-conversion ${SSE_FLAGS}")
+ string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -Wno-unknown-pragmas -fno-strict-aliasing -Wno-format-extra-args -Wno-sign-compare -Wno-invalid-offsetof -Wno-conversion ${SSE_FLAGS} ${AVX_FLAGS}")
endif()
if(PCL_WARNINGS_ARE_ERRORS)
if(CMAKE_COMPILER_IS_MSVC)
add_definitions("-DBOOST_ALL_NO_LIB -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -DNOMINMAX -DPCL_ONLY_CORE_POINT_TYPES ${SSE_DEFINITIONS}")
- add_compile_options(/bigobj)
-
if("${CMAKE_CXX_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}")
- string(APPEND CMAKE_CXX_FLAGS " /fp:precise /wd4800 /wd4521 /wd4251 /wd4275 /wd4305 /wd4355 ${SSE_FLAGS} ${AVX_FLAGS}")
+ string(APPEND CMAKE_CXX_FLAGS " /fp:precise /wd4800 /wd4521 /wd4251 /wd4275 /wd4305 /wd4355 ${SSE_FLAGS} ${AVX_FLAGS} /bigobj")
# Add extra code generation/link optimizations
if(CMAKE_MSVC_CODE_LINK_OPTIMIZATION AND (NOT BUILD_CUDA) AND (NOT BUILD_GPU))
string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /LTCG /OPT:REF")
string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " /LTCG")
else()
+ set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=/bigobj")
+
message("Global optimizations /GL has been turned off, as it doesn't work with nvcc/thrust")
endif()
# /MANIFEST:NO") # please, don't disable manifest generation, otherwise crash at start for vs2008
ProcessorCount(CPUCores)
set(MSVC_MP ${CPUCores} CACHE STRING "Number of simultaneously running compilers (0 = automatic detection by MSVC). See documentation of /MP flag.")
if (CMAKE_VERSION VERSION_LESS 3.11.0)
- # Usage of COMPILE_LANGUAGE generator expression for MSVC in add_compile_options requires at least CMake 3.11, see https://gitlab.kitware.com/cmake/cmake/issues/17435
+ # Usage of COMPILE_LANGUAGE generator expression for MSVC in add_compile_options requires at least CMake 3.11, see https://gitlab.kitware.com/cmake/cmake/issues/17435
if(MSVC_MP EQUAL 0)
# MSVC_MP is 0 in case the information cannot be determined by ProcessorCount => fallback
string(APPEND CMAKE_C_FLAGS " /MP")
set(CMAKE_C_FLAGS "-Qunused-arguments")
endif()
if("${CMAKE_CXX_FLAGS}" STREQUAL "")
- set(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Qunused-arguments -Wno-invalid-offsetof ${SSE_FLAGS_STR}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args
+ set(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Qunused-arguments -Wno-invalid-offsetof ${SSE_FLAGS} ${AVX_FLAGS}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args
if(APPLE AND WITH_CUDA AND CUDA_FOUND)
string(APPEND CMAKE_CXX_FLAGS " -stdlib=libstdc++")
endif()
set(OPENMP_DLL VCOMP140)
elseif(MSVC_VERSION MATCHES "^192[0-9]$")
set(OPENMP_DLL VCOMP140)
+ elseif(MSVC_VERSION MATCHES "^193[0-9]$")
+ set(OPENMP_DLL VCOMP140)
endif()
if(OPENMP_DLL)
string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /DELAYLOAD:${OPENMP_DLL}D.dll")
# libusb
option(WITH_LIBUSB "Build USB RGBD-Camera drivers" TRUE)
if(WITH_LIBUSB)
- find_package(libusb)
+ include("${PCL_SOURCE_DIR}/cmake/pcl_find_libusb.cmake")
endif()
# Dependencies for different grabbers
# Qhull
option(WITH_QHULL "Include convex-hull operations" TRUE)
if(WITH_QHULL)
- if(NOT PCL_SHARED_LIBS OR ((WIN32 AND NOT MINGW) AND NOT PCL_BUILD_WITH_QHULL_DYNAMIC_LINKING_WIN32))
- set(QHULL_USE_STATIC ON)
- endif()
find_package(Qhull)
- if(QHULL_FOUND)
- include_directories(SYSTEM ${QHULL_INCLUDE_DIRS})
+ if(NOT (${QHULL_LIBRARY_TYPE} MATCHES ${PCL_QHULL_REQUIRED_TYPE}) AND NOT (${PCL_QHULL_REQUIRED_TYPE} MATCHES "DONTCARE"))
+ message(FATAL_ERROR "Qhull was selected with ${PCL_QHULL_REQUIRED_TYPE} but found as ${QHULL_LIBRARY_TYPE}")
endif()
endif()
endif()
endif()
-#VTK can depend on Qt and search for its required version, so search after so we can overwrite Qt5_FOUND if the version we require is not found.
-option(WITH_QT "Build QT Front-End" TRUE)
+# VTK can depend on Qt and search for its required version, so search after so we can overwrite Qt5_FOUND/Qt6_FOUND if the version we require is not found.
+set(WITH_QT "AUTO" CACHE STRING "Build QT Front-End (AUTO|YES|QT6|QT5|NO)")
+set_property(CACHE WITH_QT PROPERTY STRINGS "AUTO" "YES" "QT6" "QT5" "NO")
if(WITH_QT)
- find_package(Qt5 5.9.5 COMPONENTS Concurrent OpenGL Widgets)
- set(QT_DISABLE_PRECATED_BEFORE_VAL "0x050900")
-
- if(Qt5_FOUND)
- message(STATUS "Qt5 version: ${Qt5_VERSION}")
- set(QT5_FOUND ${Qt5_FOUND})
- #Set Cmake Auto features to skip .hh files
- if(POLICY CMP0100)
- cmake_policy(SET CMP0100 OLD)
- endif()
-
- get_property(core_def TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_DEFINITIONS)
- list(APPEND core_def "QT_DISABLE_DEPRECATED_BEFORE=${QT_DISABLE_PRECATED_BEFORE_VAL}")
- set_property(TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_DEFINITIONS ${core_def})
-
- else()
- message(STATUS "Qt5 is not found.")
- endif()
-else()
- set(Qt5_FOUND FALSE)
+ include("${PCL_SOURCE_DIR}/cmake/pcl_find_qt.cmake")
endif()
#Find PCAP
#------------------------------------------------------------------------------------
# Set default policy behavior similar to minimum requirement version
-cmake_policy(VERSION 3.5)
+cmake_policy(VERSION 3.10)
# explicitly set policies we already support in newer cmake versions
if(POLICY CMP0074)
elseif(NOT BOOST_INCLUDEDIR)
set(BOOST_INCLUDEDIR "@Boost_INCLUDE_DIR@")
endif()
- # use static Boost in Windows
- if(WIN32)
- set(Boost_USE_STATIC_LIBS @Boost_USE_STATIC_LIBS@)
- set(Boost_USE_STATIC @Boost_USE_STATIC@)
- set(Boost_USE_MULTITHREAD @Boost_USE_MULTITHREAD@)
- endif()
+
set(Boost_ADDITIONAL_VERSIONS
"@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@.@Boost_SUBMINOR_VERSION@" "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@"
- "1.76.0" "1.76" "1.75.0" "1.75"
+ "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75"
"1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70"
"1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65")
- # Disable the config mode of find_package(Boost)
- set(Boost_NO_BOOST_CMAKE ON)
+
find_package(Boost 1.65.0 ${QUIET_} COMPONENTS @PCLCONFIG_AVAILABLE_BOOST_MODULES@)
set(BOOST_FOUND ${Boost_FOUND})
get_filename_component(QHULL_ROOT "@QHULL_INCLUDE_DIRS@" PATH)
endif()
- set(QHULL_USE_STATIC @QHULL_USE_STATIC@)
+ set(PCL_QHULL_REQUIRED_TYPE @PCL_QHULL_REQUIRED_TYPE@)
find_package(Qhull)
endmacro()
set(FLANN_ROOT "@FLANN_ROOT@")
endif()
- set(FLANN_USE_STATIC @FLANN_USE_STATIC@)
+ set(PCL_FLANN_REQUIRED_TYPE @PCL_FLANN_REQUIRED_TYPE@)
find_package(FLANN)
endmacro()
string(REGEX REPLACE "[.-]" "_" LIB ${LIB})
if(${LIB}_FOUND)
list(APPEND PCL_${COMPONENT}_INCLUDE_DIRS ${${LIB}_INCLUDE_DIRS})
- if(${LIB}_USE_FILE)
+
+ if(${LIB} MATCHES "VTK")
+ if(${${LIB}_VERSION_MAJOR} GREATER_EQUAL 9)
+ set(ISVTK9ORGREATER TRUE)
+ endif()
+ endif()
+
+ if(${LIB}_USE_FILE AND NOT ISVTK9ORGREATER )
include(${${LIB}_USE_FILE})
else()
list(APPEND PCL_${COMPONENT}_LIBRARY_DIRS "${${LIB}_LIBRARY_DIRS}")
endif()
if(${LIB}_LIBRARIES)
- list(APPEND PCL_${COMPONENT}_LIBRARIES "${${LIB}_LIBRARIES}")
+ list(APPEND PCL_${COMPONENT}_LINK_LIBRARIES "${${LIB}_LIBRARIES}")
endif()
if(${LIB}_DEFINITIONS AND NOT ${LIB} STREQUAL "VTK")
list(APPEND PCL_${COMPONENT}_DEFINITIONS ${${LIB}_DEFINITIONS})
set(PCL_DEBUG_SUFFIX "@CMAKE_DEBUG_POSTFIX@")
set(PCL_RELEASE_SUFFIX "@CMAKE_RELEASE_POSTFIX@")
+set(PCL_SHARED_LIBS "@PCL_SHARED_LIBS@")
+
#set SSE flags used compiling PCL
list(APPEND PCL_DEFINITIONS @PCLCONFIG_SSE_DEFINITIONS@)
list(APPEND PCL_COMPILE_OPTIONS @PCLCONFIG_SSE_COMPILE_OPTIONS@)
+#set AVX flags used compiling PCL
+list(APPEND PCL_COMPILE_OPTIONS @PCLCONFIG_AVX_COMPILE_OPTIONS@)
+
set(pcl_all_components @PCLCONFIG_AVAILABLE_COMPONENTS@)
list(LENGTH pcl_all_components PCL_NB_COMPONENTS)
pcl_remove_duplicate_libraries(PCL_COMPONENTS PCL_LIBRARIES)
# Add 3rd party libraries, as user code might include our .HPP implementations
-list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${QHULL_LIBRARIES} ${OPENNI_LIBRARIES} ${OPENNI2_LIBRARIES} ${ENSENSO_LIBRARIES} ${davidSDK_LIBRARIES} ${DSSDK_LIBRARIES} ${RSSDK_LIBRARIES} ${RSSDK2_LIBRARIES} ${VTK_LIBRARIES})
+list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${OPENNI_LIBRARIES} ${OPENNI2_LIBRARIES} ${ENSENSO_LIBRARIES} ${davidSDK_LIBRARIES} ${DSSDK_LIBRARIES} ${RSSDK_LIBRARIES} ${RSSDK2_LIBRARIES} ${VTK_LIBRARIES})
if (TARGET FLANN::FLANN)
list(APPEND PCL_LIBRARIES FLANN::FLANN)
endif()
+if(TARGET QHULL::QHULL)
+ list(APPEND PCL_LIBRARIES QHULL::QHULL)
+endif()
+
find_package_handle_standard_args(PCL DEFAULT_MSG PCL_LIBRARIES PCL_INCLUDE_DIRS)
mark_as_advanced(PCL_LIBRARIES PCL_INCLUDE_DIRS PCL_LIBRARY_DIRS)
[![Release][release-image]][releases]
[![License][license-image]][license]
-[release-image]: https://img.shields.io/badge/release-1.12.0-green.svg?style=flat
+[release-image]: https://img.shields.io/badge/release-1.12.1-green.svg?style=flat
[releases]: https://github.com/PointCloudLibrary/pcl/releases
[license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat
[ci-ubuntu-20.10]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20GCC&jobName=Ubuntu&configuration=Ubuntu%2020.10%20GCC&label=Ubuntu%2020.10%20GCC
[ci-windows-x86]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x86&label=Windows%20VS2019%20x86
[ci-windows-x64]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x64&label=Windows%20VS2019%20x64
-[ci-macos-10.14]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Mojave%2010.14&label=macOS%20Mojave%2010.14
+[ci-macos-11]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Big%20Sur%2011&label=macOS%20Big%20Sur%2011
[ci-macos-10.15]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Catalina%2010.15&label=macOS%20Catalina%2010.15
[ci-docs]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/Documentation?branchName=master
[ci-latest-docs]: https://dev.azure.com/PointCloudLibrary/pcl/_build/latest?definitionId=14&branchName=master
------------------------ | ------------------------------------------------------------------------------------------------- |
Ubuntu | [![Status][ci-ubuntu-18.04]][ci-latest-build] <br> [![Status][ci-ubuntu-20.04]][ci-latest-build] <br> [![Status][ci-ubuntu-20.10]][ci-latest-build] |
Windows | [![Status][ci-windows-x86]][ci-latest-build] <br> [![Status][ci-windows-x64]][ci-latest-build] |
-macOS | [![Status][ci-macos-10.14]][ci-latest-build] <br> [![Status][ci-macos-10.15]][ci-latest-build] |
+macOS | [![Status][ci-macos-10.15]][ci-latest-build] <br> [![Status][ci-macos-11]][ci-latest-build] |
Documentation | [![Status][ci-docs]][ci-latest-docs] |
Community
indices,
distances);
// gather NN-search results
- double score = 0;
for (std::size_t i = 0; i < (std::size_t)NN_; ++i) {
- score = distances[0][i];
index_score is;
is.idx_models_ =
single_categories_pointers_to_models_[it->second]->at(indices[0][i]);
is.idx_input_ = static_cast<int>(idx);
- is.score_ = score;
+ is.score_ = distances[0][i];
indices_scores.push_back(is);
}
}
int detect_clutter = 1;
int hv_method = 0;
int use_hv = 1;
- float thres_hyp_ = 0.2f;
+ float thres_hyp = 0.2f;
float desc_radius = 0.04f;
pcl::console::parse_argument(argc, argv, "-models_dir", path);
pcl::console::parse_argument(argc, argv, "-detect_clutter", detect_clutter);
pcl::console::parse_argument(argc, argv, "-hv_method", hv_method);
pcl::console::parse_argument(argc, argv, "-use_hv", use_hv);
- pcl::console::parse_argument(argc, argv, "-thres_hyp", thres_hyp_);
+ pcl::console::parse_argument(argc, argv, "-thres_hyp", thres_hyp);
+ pcl::console::parse_argument(argc, argv, "-desc_radius", desc_radius);
if (mians_scenes.empty()) {
PCL_ERROR("Set the directory containing mians scenes using the -mians_scenes_dir "
local.setUseCache(static_cast<bool>(use_cache));
local.initialize(static_cast<bool>(force_retrain));
- local.setThresholdAcceptHyp(thres_hyp_);
+ local.setThresholdAcceptHyp(thres_hyp);
uniform_keypoint_extractor->setSamplingDensity(0.005f);
local.setICPIterations(icp_iterations);
set(SUBSYS_NAME apps)
set(SUBSYS_DESC "Application examples/samples that show how PCL works")
set(SUBSYS_DEPS common geometry io filters sample_consensus segmentation visualization kdtree features surface octree registration keypoints tracking search recognition ml stereo 2d)
-set(SUBSYS_OPT_DEPS openni vtk Qt5)
+set(SUBSYS_OPT_DEPS openni vtk ${QTX})
set(DEFAULT FALSE)
set(REASON "Disabled by default")
if(QHULL_FOUND)
PCL_ADD_EXECUTABLE(pcl_pcd_select_object_plane COMPONENT ${SUBSYS_NAME} SOURCES src/pcd_select_object_plane.cpp)
target_link_libraries(pcl_pcd_select_object_plane pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_features pcl_surface)
- #TODO: Update when CMAKE 3.10 is available
- if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
- target_link_libraries(pcl_pcd_select_object_plane VTK::FiltersGeometry)
- endif()
endif()
PCL_ADD_EXECUTABLE(pcl_pcd_organized_edge_detection COMPONENT ${SUBSYS_NAME} SOURCES src/pcd_organized_edge_detection.cpp)
target_link_libraries(pcl_pcd_organized_edge_detection pcl_common pcl_io pcl_features pcl_visualization)
PCL_ADD_EXECUTABLE(pcl_face_trainer COMPONENT ${SUBSYS_NAME} SOURCES src/face_detection/face_trainer.cpp)
- target_link_libraries(pcl_face_trainer pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree ${VTK_LIBRARIES})
+ target_link_libraries(pcl_face_trainer pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree)
PCL_ADD_EXECUTABLE(pcl_fs_face_detector COMPONENT ${SUBSYS_NAME} SOURCES src/face_detection//filesystem_face_detection.cpp BUNDLE)
- target_link_libraries(pcl_fs_face_detector pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree ${VTK_LIBRARIES})
+ target_link_libraries(pcl_fs_face_detector pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree)
PCL_ADD_EXECUTABLE(pcl_stereo_ground_segmentation COMPONENT ${SUBSYS_NAME} SOURCES src/stereo_ground_segmentation.cpp)
target_link_libraries(pcl_stereo_ground_segmentation pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_features pcl_stereo)
- if(Qt5_FOUND AND HAVE_QVTK)
+ if(QT_FOUND AND HAVE_QVTK)
# Manual registration demo
PCL_ADD_EXECUTABLE(pcl_manual_registration
COMPONENT
src/manual_registration/manual_registration.ui
BUNDLE)
- target_link_libraries(pcl_manual_registration pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface Qt5::Widgets)
- #TODO: Update when CMAKE 3.10 is available
- if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
- target_link_libraries(pcl_manual_registration VTK::GUISupportQt)
- endif()
+ target_link_libraries(pcl_manual_registration pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QTX}::Widgets)
PCL_ADD_EXECUTABLE(pcl_pcd_video_player
COMPONENT
src/pcd_video_player/pcd_video_player.ui
BUNDLE)
- target_link_libraries(pcl_pcd_video_player pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface Qt5::Widgets)
- #TODO: Update when CMAKE 3.10 is available
- if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
- target_link_libraries(pcl_pcd_video_player VTK::GUISupportQt)
- endif()
+ target_link_libraries(pcl_pcd_video_player pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QTX}::Widgets)
endif()
if(WITH_OPENNI)
target_link_libraries(pcl_openni_organized_edge_detection pcl_common pcl_io pcl_features pcl_visualization)
PCL_ADD_EXECUTABLE(pcl_openni_face_detector COMPONENT ${SUBSYS_NAME} SOURCES src/face_detection//openni_face_detection.cpp src/face_detection//openni_frame_source.cpp BUNDLE)
- target_link_libraries(pcl_openni_face_detector pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree ${VTK_LIBRARIES})
+ target_link_libraries(pcl_openni_face_detector pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree)
- if(Qt5_FOUND AND HAVE_QVTK)
+ if(QT_FOUND AND HAVE_QVTK)
# OpenNI Passthrough application demo
PCL_ADD_EXECUTABLE(pcl_openni_passthrough
COMPONENT
src/openni_passthrough.cpp
src/openni_passthrough.ui)
- target_link_libraries(pcl_openni_passthrough pcl_common pcl_io pcl_filters pcl_visualization Qt5::Widgets)
- #TODO: Update when CMAKE 3.10 is available
- if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
- target_link_libraries(pcl_openni_passthrough VTK::GUISupportQt)
- endif()
+ target_link_libraries(pcl_openni_passthrough pcl_common pcl_io pcl_filters pcl_visualization ${QTX}::Widgets)
list(APPEND CMAKE_AUTOUIC_SEARCH_PATHS "src")
src/organized_segmentation_demo.cpp
src/organized_segmentation_demo.ui
BUNDLE)
- target_link_libraries(pcl_organized_segmentation_demo pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface Qt5::Widgets)
- #TODO: Update when CMAKE 3.10 is available
- if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
- target_link_libraries(pcl_organized_segmentation_demo VTK::GUISupportQt)
- endif()
+ target_link_libraries(pcl_organized_segmentation_demo pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QTX}::Widgets)
+
endif()
if(QHULL_FOUND)
set(SUBSUBSYS_NAME cloud_composer)
set(SUBSUBSYS_DESC "Cloud Composer - Application for Manipulating Point Clouds")
set(SUBSUBSYS_DEPS common io visualization filters apps)
-set(SUBSUBSYS_EXT_DEPS vtk Qt5)
+set(SUBSUBSYS_EXT_DEPS vtk ${QTX})
# QVTK?
if(NOT HAVE_QVTK)
PCL_ADD_LIBRARY(pcl_cc_tool_interface COMPONENT ${SUBSUBSYS_NAME} SOURCES ${INTERFACE_HEADERS} ${INTERFACE_SOURCES})
-set(vtk_libs ${VTK_LIBRARIES})
-#TODO: Update when CMAKE 3.10 is available
-if (NOT (${VTK_VERSION} VERSION_LESS 9.0))
- set(vtk_libs VTK::GUISupportQt)
-endif()
-target_link_libraries(pcl_cc_tool_interface pcl_common pcl_filters pcl_search pcl_visualization Qt5::Widgets ${vtk_libs})
+
+target_link_libraries(pcl_cc_tool_interface pcl_common pcl_filters pcl_search pcl_visualization ${QTX}::Widgets)
set(PCL_LIB_TYPE ${PCL_LIB_TYPE_ORIGIN})
set(EXE_NAME "pcl_${SUBSUBSYS_NAME}")
PCL_ADD_EXECUTABLE(${EXE_NAME} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${uis} ${incs} ${srcs} ${resources} ${impl_incs})
-target_link_libraries("${EXE_NAME}" pcl_cc_tool_interface pcl_common pcl_io pcl_visualization pcl_filters Qt5::Widgets)
+target_link_libraries("${EXE_NAME}" pcl_cc_tool_interface pcl_common pcl_io pcl_visualization pcl_filters ${QTX}::Widgets)
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
- target_link_libraries(${TOOL_TARGET} pcl_cc_tool_interface pcl_common pcl_io ${DEPS} Qt5::Widgets)
+ target_link_libraries(${TOOL_TARGET} pcl_cc_tool_interface pcl_common pcl_io ${DEPS} ${QTX}::Widgets)
if(APPLE)
set_target_properties(${TOOL_TARGET} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
set(SUBSUBSYS_DESC "In-hand scanner for small objects")
set(SUBSUBSYS_DEPS common features io kdtree apps)
set(SUBSUBSYS_LIBS pcl_common pcl_features pcl_io pcl_kdtree)
-set(SUBSUBSYS_EXT_DEPS Qt5 OpenGL OpenGL_GLU openni)
+set(SUBSUBSYS_EXT_DEPS ${QTX} OpenGL OpenGL_GLU openni)
################################################################################
${IMPL_INCS}
${UI}
BUNDLE)
-target_link_libraries("${EXE_NAME}" ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} Qt5::Concurrent Qt5::Widgets Qt5::OpenGL)
+target_link_libraries("${EXE_NAME}" ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} ${QTX}::Concurrent ${QTX}::Widgets ${QTX}::OpenGL)
pcl_add_includes("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${INCS})
pcl_add_includes("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}/impl" ${IMPL_INCS})
${OI_INCS}
BUNDLE)
-target_link_libraries(pcl_offline_integration ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} Qt5::Concurrent Qt5::Widgets Qt5::OpenGL)
+target_link_libraries(pcl_offline_integration ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} ${QTX}::Concurrent ${QTX}::Widgets ${QTX}::OpenGL)
# Add to the compound apps target
list(APPEND PCL_APPS_ALL_TARGETS ${PCL_IN_HAND_SCANNER_ALL_TARGETS})
std::map<float, float> connected_labels;
float c_intensity = 0.1f;
- float intensity_incr = 0.1f;
+ const float intensity_incr = 0.1f;
{
set(SUBSUBSYS_NAME modeler)
set(SUBSUBSYS_DESC "PCLModeler: PCL based reconstruction platform")
set(SUBSUBSYS_DEPS common geometry io filters sample_consensus segmentation visualization kdtree features surface octree registration keypoints tracking search apps)
-set(SUBSUBSYS_EXT_DEPS vtk Qt5)
+set(SUBSUBSYS_EXT_DEPS vtk ${QTX})
set(REASON "")
# QVTK?
${incs}
${impl_incs})
-target_link_libraries("${EXE_NAME}" pcl_common pcl_io pcl_kdtree pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search Qt5::Widgets)
-#TODO: Update when CMAKE 3.10 is available
-if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
- target_link_libraries("${EXE_NAME}" VTK::GUISupportQt)
-endif()
+target_link_libraries("${EXE_NAME}" pcl_common pcl_io pcl_kdtree pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search ${QTX}::Widgets)
# Install include files
PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${incs})
set(SUBSUBSYS_NAME point_cloud_editor)
set(SUBSUBSYS_DESC "Point Cloud Editor - Simple editor for 3D point clouds")
set(SUBSUBSYS_DEPS common filters io apps)
-set(SUBSUBSYS_EXT_DEPS vtk Qt5 OpenGL)
+set(SUBSUBSYS_EXT_DEPS vtk ${QTX} OpenGL)
# Default to not building for now
if(${DEFAULT} STREQUAL "TRUE")
${RSRC}
${INCS})
-target_link_libraries("${EXE_NAME}" Qt5::Widgets Qt5::OpenGL ${OPENGL_LIBRARIES} ${BOOST_LIBRARIES} pcl_common pcl_io pcl_filters)
+target_link_libraries("${EXE_NAME}" ${QTX}::Widgets ${QTX}::OpenGL ${OPENGL_LIBRARIES} ${BOOST_LIBRARIES} pcl_common pcl_io pcl_filters)
PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSYS_NAME}/${SUBSUBSYS_NAME}" ${INCS})
PCL_MAKE_PKGCONFIG(${EXE_NAME} COMPONENT ${SUBSUBSYS_NAME} DESC ${SUBSUBSYS_DESC})
#include <QFileDialog>
#include <QMessageBox>
#include <QMouseEvent>
+#include <QApplication>
+#include <QDesktopWidget>
#include <qgl.h>
#include <pcl/pcl_config.h>
CloudEditorWidget::load ()
{
QString file_path = QFileDialog::getOpenFileName(this, tr("Open File"));
-
+
if (file_path.isEmpty())
return;
}
QString file_path = QFileDialog::getSaveFileName(this,tr("Save point cloud"));
-
+
std::string file_path_std = file_path.toStdString();
if ( (file_path_std.empty()) || (!cloud_ptr_) )
return;
void
CloudEditorWidget::mousePressEvent (QMouseEvent *event)
{
+ auto ratio = this->devicePixelRatio();
if (!tool_ptr_)
return;
- tool_ptr_ -> start(event -> x(), event -> y(),
+ tool_ptr_ -> start(event -> x()*ratio, event -> y()*ratio,
event -> modifiers(), event -> buttons());
update();
}
void
CloudEditorWidget::mouseMoveEvent (QMouseEvent *event)
{
+ auto ratio = this->devicePixelRatio();
if (!tool_ptr_)
return;
- tool_ptr_ -> update(event -> x(), event -> y(),
+ tool_ptr_ -> update(event -> x()*ratio, event -> y()*ratio,
event -> modifiers(), event -> buttons());
update();
}
void
CloudEditorWidget::mouseReleaseEvent (QMouseEvent *event)
{
+ auto ratio = this->devicePixelRatio();
if (!tool_ptr_)
return;
- tool_ptr_ -> end(event -> x(), event -> y(),
+ tool_ptr_ -> end(event -> x()*ratio, event -> y()*ratio,
event -> modifiers(), event -> button());
update();
}
void
CloudEditorWidget::loadFilePCD(const std::string &filename)
-{
+{
PclCloudPtr pcl_cloud_ptr;
Cloud3D tmp;
if (pcl::io::loadPCDFile<Point3D>(filename, tmp) == -1)
void
CloudEditorWidget::initKeyMap ()
-{
+{
key_map_[Qt::Key_1] = &CloudEditorWidget::colorByPure;
key_map_[Qt::Key_2] = &CloudEditorWidget::colorByX;
key_map_[Qt::Key_3] = &CloudEditorWidget::colorByY;
+++ /dev/null
-#
-# Compute target flags macros by Anatoly Baksheev
-#
-# Usage in CmakeLists.txt:
-# include(CudaComputeTargetFlags.cmake)
-# APPEND_TARGET_ARCH_FLAGS()
-
-#compute flags macros
-macro(CUDA_COMPUTE_TARGET_FLAGS arch_bin arch_ptx cuda_nvcc_target_flags)
- string(REGEX REPLACE "\\." "" ARCH_BIN_WITHOUT_DOTS "${${arch_bin}}")
- string(REGEX REPLACE "\\." "" ARCH_PTX_WITHOUT_DOTS "${${arch_ptx}}")
-
- set(cuda_computer_target_flags_temp "")
-
- # Tell NVCC to add binaries for the specified GPUs
- string(REGEX MATCHALL "[0-9()]+" ARCH_LIST "${ARCH_BIN_WITHOUT_DOTS}")
- foreach(ARCH IN LISTS ARCH_LIST)
- if(ARCH MATCHES "([0-9]+)\\(([0-9]+)\\)")
- # User explicitly specified PTX for the concrete BIN
- set(cuda_computer_target_flags_temp ${cuda_computer_target_flags_temp} -gencode arch=compute_${CMAKE_MATCH_2},code=sm_${CMAKE_MATCH_1})
- else()
- # User didn't explicitly specify PTX for the concrete BIN, we assume PTX=BIN
- set(cuda_computer_target_flags_temp ${cuda_computer_target_flags_temp} -gencode arch=compute_${ARCH},code=sm_${ARCH})
- endif()
- endforeach()
-
- # Tell NVCC to add PTX intermediate code for the specified architectures
- string(REGEX MATCHALL "[0-9]+" ARCH_LIST "${ARCH_PTX_WITHOUT_DOTS}")
- foreach(ARCH IN LISTS ARCH_LIST)
- set(cuda_computer_target_flags_temp ${cuda_computer_target_flags_temp} -gencode arch=compute_${ARCH},code=compute_${ARCH})
- endforeach()
-
- set(${cuda_nvcc_target_flags} ${cuda_computer_target_flags_temp})
-endmacro()
-
-macro(APPEND_TARGET_ARCH_FLAGS)
- set(cuda_nvcc_target_flags "")
- CUDA_COMPUTE_TARGET_FLAGS(CUDA_ARCH_BIN CUDA_ARCH_PTX cuda_nvcc_target_flags)
- if(cuda_nvcc_target_flags)
- message(STATUS "CUDA NVCC target flags: ${cuda_nvcc_target_flags}")
- list(APPEND CUDA_NVCC_FLAGS ${cuda_nvcc_target_flags})
- endif()
-endmacro()
add_library(FLANN::FLANN INTERFACE IMPORTED)
if(TARGET flann::flann_cpp_s AND TARGET flann::flann_cpp)
- if(PCL_FLANN_REQUIRED_TYPE MATCHES "DONTCARE")
+ if(PCL_FLANN_REQUIRED_TYPE MATCHES "SHARED")
+ set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp)
+ set(FLANN_LIBRARY_TYPE SHARED)
+ elseif(PCL_FLANN_REQUIRED_TYPE MATCHES "STATIC")
+ set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s)
+ set(FLANN_LIBRARY_TYPE STATIC)
+ else()
if(PCL_SHARED_LIBS)
set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp)
set(FLANN_LIBRARY_TYPE SHARED)
set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s)
set(FLANN_LIBRARY_TYPE STATIC)
endif()
- elseif(PCL_FLANN_REQUIRED_TYPE MATCHES "SHARED")
- set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp)
- set(FLANN_LIBRARY_TYPE SHARED)
- else()
- set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s)
- set(FLANN_LIBRARY_TYPE STATIC)
endif()
elseif(TARGET flann::flann_cpp_s)
set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s)
)
if(FLANN_LIBRARY_SHARED AND FLANN_LIBRARY_STATIC)
- if(PCL_FLANN_REQUIRED_TYPE MATCHES "DONTCARE")
+ if(PCL_FLANN_REQUIRED_TYPE MATCHES "SHARED")
+ set(FLANN_LIBRARY_TYPE SHARED)
+ set(FLANN_LIBRARY ${FLANN_LIBRARY_SHARED})
+ elseif(PCL_FLANN_REQUIRED_TYPE MATCHES "STATIC")
+ set(FLANN_LIBRARY_TYPE STATIC)
+ set(FLANN_LIBRARY ${FLANN_LIBRARY_STATIC})
+ else()
if(PCL_SHARED_LIBS)
set(FLANN_LIBRARY_TYPE SHARED)
set(FLANN_LIBRARY ${FLANN_LIBRARY_SHARED})
set(FLANN_LIBRARY_TYPE STATIC)
set(FLANN_LIBRARY ${FLANN_LIBRARY_STATIC})
endif()
- elseif(PCL_FLANN_REQUIRED_TYPE MATCHES "SHARED")
- set(FLANN_LIBRARY_TYPE SHARED)
- set(FLANN_LIBRARY ${FLANN_LIBRARY_SHARED})
- else()
- set(FLANN_LIBRARY_TYPE STATIC)
- set(FLANN_LIBRARY ${FLANN_LIBRARY_STATIC})
endif()
elseif(FLANN_LIBRARY_STATIC)
set(FLANN_LIBRARY_TYPE STATIC)
endif()
endforeach()
get_filename_component(FLANN_ROOT "${FLANN_INCLUDE_DIR}" PATH)
+ message(STATUS "FLANN found (include: ${FLANN_INCLUDE_DIR}, lib: ${FLANN_LIBRARY})")
endif()
--- /dev/null
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+
+FindOpenMP is added to PCL local Cmake modules due to bug in earlier version.
+TODO: Can be removed when Cmake 3.11 is required.
+See https://gitlab.kitware.com/cmake/cmake/-/issues/20364
+
+FindOpenMP
+----------
+
+Finds Open Multi-Processing (OpenMP) support.
+
+This module can be used to detect OpenMP support in a compiler. If
+the compiler supports OpenMP, the flags required to compile with
+OpenMP support are returned in variables for the different languages.
+The variables may be empty if the compiler does not need a special
+flag to support OpenMP.
+
+Variables
+^^^^^^^^^
+
+The module exposes the components ``C``, ``CXX``, and ``Fortran``.
+Each of these controls the various languages to search OpenMP support for.
+
+Depending on the enabled components the following variables will be set:
+
+``OpenMP_FOUND``
+ Variable indicating that OpenMP flags for all requested languages have been found.
+ If no components are specified, this is true if OpenMP settings for all enabled languages
+ were detected.
+``OpenMP_VERSION``
+ Minimal version of the OpenMP standard detected among the requested languages,
+ or all enabled languages if no components were specified.
+
+This module will set the following variables per language in your
+project, where ``<lang>`` is one of C, CXX, or Fortran:
+
+``OpenMP_<lang>_FOUND``
+ Variable indicating if OpenMP support for ``<lang>`` was detected.
+``OpenMP_<lang>_FLAGS``
+ OpenMP compiler flags for ``<lang>``, separated by spaces.
+``OpenMP_<lang>_INCLUDE_DIRS``
+ Directories that must be added to the header search path for ``<lang>``
+ when using OpenMP.
+
+For linking with OpenMP code written in ``<lang>``, the following
+variables are provided:
+
+``OpenMP_<lang>_LIB_NAMES``
+ :ref:`;-list <CMake Language Lists>` of libraries for OpenMP programs for ``<lang>``.
+``OpenMP_<libname>_LIBRARY``
+ Location of the individual libraries needed for OpenMP support in ``<lang>``.
+``OpenMP_<lang>_LIBRARIES``
+ A list of libraries needed to link with OpenMP code written in ``<lang>``.
+
+Additionally, the module provides :prop_tgt:`IMPORTED` targets:
+
+``OpenMP::OpenMP_<lang>``
+ Target for using OpenMP from ``<lang>``.
+
+Specifically for Fortran, the module sets the following variables:
+
+``OpenMP_Fortran_HAVE_OMPLIB_HEADER``
+ Boolean indicating if OpenMP is accessible through ``omp_lib.h``.
+``OpenMP_Fortran_HAVE_OMPLIB_MODULE``
+ Boolean indicating if OpenMP is accessible through the ``omp_lib`` Fortran module.
+
+The module will also try to provide the OpenMP version variables:
+
+``OpenMP_<lang>_SPEC_DATE``
+ Date of the OpenMP specification implemented by the ``<lang>`` compiler.
+``OpenMP_<lang>_VERSION_MAJOR``
+ Major version of OpenMP implemented by the ``<lang>`` compiler.
+``OpenMP_<lang>_VERSION_MINOR``
+ Minor version of OpenMP implemented by the ``<lang>`` compiler.
+``OpenMP_<lang>_VERSION``
+ OpenMP version implemented by the ``<lang>`` compiler.
+
+The specification date is formatted as given in the OpenMP standard:
+``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of
+the OpenMP specification implemented by the ``<lang>`` compiler.
+
+For some compilers, it may be necessary to add a header search path to find
+the relevant OpenMP headers. This location may be language-specific. Where
+this is needed, the module may attempt to find the location, but it can be
+provided directly by setting the ``OpenMP_<lang>_INCLUDE_DIR`` cache variable.
+Note that this variable is an _input_ control to the module. Project code
+should use the ``OpenMP_<lang>_INCLUDE_DIRS`` _output_ variable if it needs
+to know what include directories are needed.
+#]=======================================================================]
+
+cmake_policy(PUSH)
+cmake_policy(SET CMP0012 NEW) # if() recognizes numbers and booleans
+cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
+function(_OPENMP_FLAG_CANDIDATES LANG)
+ if(NOT OpenMP_${LANG}_FLAG)
+ unset(OpenMP_FLAG_CANDIDATES)
+
+ set(OMP_FLAG_GNU "-fopenmp")
+ set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp" "-Xclang -fopenmp")
+ set(OMP_FLAG_AppleClang "-Xclang -fopenmp")
+ set(OMP_FLAG_HP "+Oopenmp")
+ if(WIN32)
+ set(OMP_FLAG_Intel "-Qopenmp")
+ elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND
+ "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
+ set(OMP_FLAG_Intel "-openmp")
+ else()
+ set(OMP_FLAG_Intel "-qopenmp")
+ endif()
+ set(OMP_FLAG_MSVC "-openmp")
+ set(OMP_FLAG_PathScale "-openmp")
+ set(OMP_FLAG_NAG "-openmp")
+ set(OMP_FLAG_Absoft "-openmp")
+ set(OMP_FLAG_PGI "-mp")
+ set(OMP_FLAG_Flang "-fopenmp")
+ set(OMP_FLAG_SunPro "-xopenmp")
+ set(OMP_FLAG_XL "-qsmp=omp")
+ # Cray compiler activate OpenMP with -h omp, which is enabled by default.
+ set(OMP_FLAG_Cray " " "-h omp")
+
+ # If we know the correct flags, use those
+ if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
+ set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
+ # Fall back to reasonable default tries otherwise
+ else()
+ set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ")
+ endif()
+ set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE)
+ else()
+ set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# sample openmp source code to test
+set(OpenMP_C_CXX_TEST_SOURCE
+"
+#include <omp.h>
+int main(void) {
+#ifdef _OPENMP
+ omp_get_max_threads();
+ return 0;
+#elif defined(__HIP_DEVICE_COMPILE__)
+ return 0;
+#else
+ breaks_on_purpose
+#endif
+}
+")
+
+# in Fortran, an implementation may provide an omp_lib.h header
+# or omp_lib module, or both (OpenMP standard, section 3.1)
+# Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2)
+# Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code
+# while not actually enabling OpenMP, building code sequentially
+set(OpenMP_Fortran_TEST_SOURCE
+ "
+ program test
+ @OpenMP_Fortran_INCLUDE_LINE@
+ !$ integer :: n
+ n = omp_get_num_threads()
+ end program test
+ "
+)
+
+function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH)
+ set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
+ if("${LANG}" STREQUAL "C")
+ set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c")
+ file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+ elseif("${LANG}" STREQUAL "CXX")
+ set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp")
+ file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+ elseif("${LANG}" STREQUAL "Fortran")
+ set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90")
+ file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}")
+ configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY)
+ endif()
+ set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
+endfunction()
+
+include(CMakeParseImplicitLinkInfo)
+
+function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
+ _OPENMP_FLAG_CANDIDATES("${LANG}")
+ _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC)
+
+ unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
+ separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}")
+ foreach(_VERBOSE_OPTION IN LISTS OpenMP_VERBOSE_OPTIONS)
+ if(NOT _VERBOSE_OPTION MATCHES "^-Wl,")
+ list(APPEND OpenMP_VERBOSE_COMPILE_OPTIONS ${_VERBOSE_OPTION})
+ endif()
+ endforeach()
+
+ foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES)
+ set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}")
+ if(OpenMP_VERBOSE_COMPILE_OPTIONS)
+ string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}")
+ endif()
+ string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+
+ if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+
+ if(CMAKE_${LANG}_VERBOSE_FLAG)
+ unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES)
+ unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS)
+ unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS)
+ unset(OpenMP_${LANG}_LOG_VAR)
+
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
+
+ cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}"
+ OpenMP_${LANG}_IMPLICIT_LIBRARIES
+ OpenMP_${LANG}_IMPLICIT_LINK_DIRS
+ OpenMP_${LANG}_IMPLICIT_FWK_DIRS
+ OpenMP_${LANG}_LOG_VAR
+ "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}"
+ )
+
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
+
+ unset(_OPENMP_LIB_NAMES)
+ foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
+ get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY)
+ get_filename_component(_OPENMP_IMPLICIT_LIB_NAME "${_OPENMP_IMPLICIT_LIB}" NAME)
+ get_filename_component(_OPENMP_IMPLICIT_LIB_PLAIN "${_OPENMP_IMPLICIT_LIB}" NAME_WE)
+ string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PLAIN_ESC "${_OPENMP_IMPLICIT_LIB_PLAIN}")
+ string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PATH_ESC "${_OPENMP_IMPLICIT_LIB}")
+ if(NOT ( "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES
+ OR "${CMAKE_${LANG}_STANDARD_LIBRARIES}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)"
+ OR "${CMAKE_${LANG}_LINK_EXECUTABLE}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" ) )
+ if(_OPENMP_IMPLICIT_LIB_DIR)
+ set(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY "${_OPENMP_IMPLICIT_LIB}" CACHE FILEPATH
+ "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP")
+ else()
+ find_library(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY
+ NAMES "${_OPENMP_IMPLICIT_LIB_NAME}"
+ DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP"
+ HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
+ CMAKE_FIND_ROOT_PATH_BOTH
+ NO_DEFAULT_PATH
+ )
+ endif()
+ mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY)
+ list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB_PLAIN})
+ endif()
+ endforeach()
+ set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE)
+ else()
+ # We do not know how to extract implicit OpenMP libraries for this compiler.
+ # Assume that it handles them automatically, e.g. the Intel Compiler on
+ # Windows should put the dependency in its object files.
+ set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
+ endif()
+ break()
+ elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang"
+ AND CMAKE_${LANG}_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0")
+
+ # Check for separate OpenMP library on AppleClang 7+
+ find_library(OpenMP_libomp_LIBRARY
+ NAMES omp gomp iomp5
+ HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
+ )
+ mark_as_advanced(OpenMP_libomp_LIBRARY)
+
+ if(OpenMP_libomp_LIBRARY)
+ # Try without specifying include directory first. We only want to
+ # explicitly add a search path if the header can't be found on the
+ # default header search path already.
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+ if(NOT OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ find_path(OpenMP_${LANG}_INCLUDE_DIR omp.h)
+ mark_as_advanced(OpenMP_${LANG}_INCLUDE_DIR)
+ set(OpenMP_${LANG}_INCLUDE_DIR "${OpenMP_${LANG}_INCLUDE_DIR}" PARENT_SCOPE)
+ if(OpenMP_${LANG}_INCLUDE_DIR)
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+ endif()
+ endif()
+ if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+ set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
+ break()
+ endif()
+ endif()
+ elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Clang" AND WIN32)
+ # Check for separate OpenMP library for Clang on Windows
+ find_library(OpenMP_libomp_LIBRARY
+ NAMES libomp libgomp libiomp5
+ HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
+ )
+ mark_as_advanced(OpenMP_libomp_LIBRARY)
+ if(OpenMP_libomp_LIBRARY)
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+ if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+ set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
+ break()
+ endif()
+ endif()
+ else()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Detecting ${LANG} OpenMP failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
+ endif()
+ set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
+ set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
+ endforeach()
+
+ unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
+endfunction()
+
+set(OpenMP_C_CXX_CHECK_VERSION_SOURCE
+"
+#include <stdio.h>
+#include <omp.h>
+const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M',
+ 'P', '-', 'd', 'a', 't', 'e', '[',
+ ('0' + ((_OPENMP/100000)%10)),
+ ('0' + ((_OPENMP/10000)%10)),
+ ('0' + ((_OPENMP/1000)%10)),
+ ('0' + ((_OPENMP/100)%10)),
+ ('0' + ((_OPENMP/10)%10)),
+ ('0' + ((_OPENMP/1)%10)),
+ ']', '\\0' };
+int main(void)
+{
+ puts(ompver_str);
+ return 0;
+}
+")
+
+set(OpenMP_Fortran_CHECK_VERSION_SOURCE
+"
+ program omp_ver
+ @OpenMP_Fortran_INCLUDE_LINE@
+ integer, parameter :: zero = ichar('0')
+ integer, parameter :: ompv = openmp_version
+ character, dimension(24), parameter :: ompver_str =&
+ (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',&
+ 'd', 'a', 't', 'e', '[',&
+ char(zero + mod(ompv/100000, 10)),&
+ char(zero + mod(ompv/10000, 10)),&
+ char(zero + mod(ompv/1000, 10)),&
+ char(zero + mod(ompv/100, 10)),&
+ char(zero + mod(ompv/10, 10)),&
+ char(zero + mod(ompv/1, 10)), ']' /)
+ print *, ompver_str
+ end program omp_ver
+")
+
+function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
+ _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC)
+
+ unset(_includeDirFlags)
+ if(OpenMP_${LANG}_INCLUDE_DIR)
+ set(_includeDirFlags "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}")
+ endif()
+
+ set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin")
+ string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
+ try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}"
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" ${_includeDirFlags}
+ COPY_FILE ${BIN_FILE}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT)
+
+ if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
+ file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
+ set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
+ if("${specstr}" MATCHES "${regex_spec_date}")
+ set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
+ endif()
+ else()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Detecting ${LANG} OpenMP version failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
+ endif()
+endfunction()
+
+macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG)
+ set(OpenMP_SPEC_DATE_MAP
+ # Preview versions
+ "201611=5.0" # OpenMP 5.0 preview 1
+ # Combined versions, 2.5 onwards
+ "201811=5.0"
+ "201511=4.5"
+ "201307=4.0"
+ "201107=3.1"
+ "200805=3.0"
+ "200505=2.5"
+ # C/C++ version 2.0
+ "200203=2.0"
+ # Fortran version 2.0
+ "200011=2.0"
+ # Fortran version 1.1
+ "199911=1.1"
+ # C/C++ version 1.0 (there's no 1.1 for C/C++)
+ "199810=1.0"
+ # Fortran version 1.0
+ "199710=1.0"
+ )
+ if(MSVC)
+ list(APPEND OpenMP_SPEC_DATE_MAP "2019=2.0")
+ endif()
+
+ if(OpenMP_${LANG}_SPEC_DATE)
+ string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}")
+ else()
+ set(_version_match "")
+ endif()
+ if(NOT _version_match STREQUAL "")
+ set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
+ set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
+ set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}")
+ else()
+ unset(OpenMP_${LANG}_VERSION_MAJOR)
+ unset(OpenMP_${LANG}_VERSION_MINOR)
+ unset(OpenMP_${LANG}_VERSION)
+ endif()
+ unset(_version_match)
+ unset(OpenMP_SPEC_DATE_MAP)
+endmacro()
+
+foreach(LANG IN ITEMS C CXX)
+ if(CMAKE_${LANG}_COMPILER_LOADED)
+ if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
+ _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
+ set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
+ CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE)
+ set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
+ CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE)
+ mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
+ endif()
+ endif()
+endforeach()
+
+if(CMAKE_Fortran_COMPILER_LOADED)
+ if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+ set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
+ _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
+ if(OpenMP_Fortran_FLAGS_WORK)
+ set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
+ endif()
+
+ set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+ CACHE STRING "Fortran compiler flags for OpenMP parallelization")
+ set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
+ CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+ mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
+ endif()
+
+ if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
+ set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
+ _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
+ if(OpenMP_Fortran_FLAGS_WORK)
+ set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
+ endif()
+
+ set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+ CACHE STRING "Fortran compiler flags for OpenMP parallelization")
+
+ set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}"
+ CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+ endif()
+
+ if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+ set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
+ else()
+ set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
+ endif()
+endif()
+
+if(NOT OpenMP_FIND_COMPONENTS)
+ set(OpenMP_FINDLIST C CXX Fortran)
+else()
+ set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS})
+endif()
+
+unset(_OpenMP_MIN_VERSION)
+
+include(FindPackageHandleStandardArgs)
+
+foreach(LANG IN LISTS OpenMP_FINDLIST)
+ if(CMAKE_${LANG}_COMPILER_LOADED)
+ if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS)
+ _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL)
+ set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE
+ INTERNAL "${LANG} compiler's OpenMP specification date")
+ endif()
+ _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
+
+ set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
+ set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
+ set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
+ set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT})
+
+ set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS)
+ if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
+ set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES)
+ else()
+ foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
+ list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
+ endforeach()
+ endif()
+
+ if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.17")
+ find_package_handle_standard_args(OpenMP_${LANG}
+ NAME_MISMATCHED
+ REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS}
+ VERSION_VAR OpenMP_${LANG}_VERSION
+ )
+ else()
+ find_package_handle_standard_args(OpenMP_${LANG}
+ REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS}
+ VERSION_VAR OpenMP_${LANG}_VERSION
+ )
+ endif()
+
+ if(OpenMP_${LANG}_FOUND)
+ if(DEFINED OpenMP_${LANG}_VERSION)
+ if(NOT _OpenMP_MIN_VERSION OR _OpenMP_MIN_VERSION VERSION_GREATER OpenMP_${LANG}_VERSION)
+ set(_OpenMP_MIN_VERSION OpenMP_${LANG}_VERSION)
+ endif()
+ endif()
+ set(OpenMP_${LANG}_LIBRARIES "")
+ foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
+ list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}")
+ endforeach()
+ if(OpenMP_${LANG}_INCLUDE_DIR)
+ set(OpenMP_${LANG}_INCLUDE_DIRS ${OpenMP_${LANG}_INCLUDE_DIR})
+ else()
+ set(OpenMP_${LANG}_INCLUDE_DIRS "")
+ endif()
+
+ if(NOT TARGET OpenMP::OpenMP_${LANG})
+ add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED)
+ endif()
+ if(OpenMP_${LANG}_FLAGS)
+ separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}")
+ set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
+ INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>")
+ unset(_OpenMP_${LANG}_OPTIONS)
+ endif()
+ if(OpenMP_${LANG}_INCLUDE_DIRS)
+ set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
+ INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${OpenMP_${LANG}_INCLUDE_DIRS}>")
+ endif()
+ if(OpenMP_${LANG}_LIBRARIES)
+ set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
+ INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}")
+ endif()
+ endif()
+ endif()
+endforeach()
+
+unset(_OpenMP_REQ_VARS)
+foreach(LANG IN ITEMS C CXX Fortran)
+ if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS)
+ list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND")
+ endif()
+endforeach()
+
+find_package_handle_standard_args(OpenMP
+ REQUIRED_VARS ${_OpenMP_REQ_VARS}
+ VERSION_VAR ${_OpenMP_MIN_VERSION}
+ HANDLE_COMPONENTS)
+
+set(OPENMP_FOUND ${OpenMP_FOUND})
+
+if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND)
+ if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+ set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "")
+ endif()
+ if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
+ set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "")
+ endif()
+endif()
+
+if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED ))
+ message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled")
+endif()
+
+unset(OpenMP_C_CXX_TEST_SOURCE)
+unset(OpenMP_Fortran_TEST_SOURCE)
+unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE)
+unset(OpenMP_Fortran_CHECK_VERSION_SOURCE)
+unset(OpenMP_Fortran_INCLUDE_LINE)
+
+cmake_policy(POP)
mark_as_advanced(OPENNI_INCLUDE_DIRS)
# Libraries
- if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ if(NOT WIN32)
find_package(libusb REQUIRED)
set(OPENNI_LIBRARIES ${OPENNI_LIBRARY} libusb::libusb)
else()
mark_as_advanced(OPENNI2_INCLUDE_DIRS)
# Libraries
- if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ if(NOT WIN32)
find_package(libusb REQUIRED)
set(OPENNI2_LIBRARIES ${OPENNI2_LIBRARY} libusb::libusb)
else()
-###############################################################################
-# Find QHULL
+#.rst:
+# FindQhull
+# --------
+#
+# Try to find QHULL library and headers. This module supports both old released versions
+# of QHULL ≤ 7.3.2 and newer development versions that ship with a modern config file,
+# but its limited to only the reentrant version of Qhull.
+#
+# PCL_QHULL_REQUIRED_TYPE can be used to select if you want static or shared libraries, but it defaults to "don't care".
+#
+# IMPORTED Targets
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines the :prop_tgt:`IMPORTED` targets:
+#
+# ``QHULL::QHULL``
+# Defined if the system has QHULL.
+#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
+#
+# This module sets the following variables:
+#
+# ::
+#
+# QHULL_FOUND True in case QHULL is found, otherwise false
+#
+# Example usage
+# ^^^^^^^^^^^^^
+#
+# ::
+#
+# find_package(QHULL REQUIRED)
+#
+# add_executable(foo foo.cc)
+# target_link_libraries(foo QHULL::QHULL)
#
-# This sets the following variables:
-# QHULL_FOUND - True if QHULL was found.
-# QHULL_INCLUDE_DIRS - Directories containing the QHULL include files.
-# QHULL_LIBRARIES - Libraries needed to use QHULL.
-# QHULL_DEFINITIONS - Compiler flags for QHULL.
-# If QHULL_USE_STATIC is specified then look for static libraries ONLY else
-# look for shared ones
-if(QHULL_USE_STATIC)
- set(QHULL_RELEASE_NAME qhullstatic_r)
- set(QHULL_DEBUG_NAME qhullstatic_rd)
-else()
- set(QHULL_RELEASE_NAME qhull_r qhull)
- set(QHULL_DEBUG_NAME qhull_rd qhull_d)
+# Skip if QHULL::QHULL is already defined
+if(TARGET QHULL::QHULL)
+ return()
+endif()
+
+# Try to locate QHull using modern cmake config (available on latest Qhull version).
+find_package(Qhull CONFIG QUIET)
+
+if(Qhull_FOUND)
+ unset(Qhull_FOUND)
+ set(QHULL_FOUND ON)
+ set(HAVE_QHULL ON)
+
+ message(STATUS "Found Qhull version ${Qhull_VERSION}")
+
+ # Create interface library that effectively becomes an alias for the appropriate (static/dynamic) imported QHULL target
+ add_library(QHULL::QHULL INTERFACE IMPORTED)
+
+ if(TARGET Qhull::qhull_r AND TARGET Qhull::qhullstatic_r)
+ if(PCL_QHULL_REQUIRED_TYPE MATCHES "SHARED")
+ set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhull_r)
+ set(QHULL_LIBRARY_TYPE SHARED)
+ elseif(PCL_QHULL_REQUIRED_TYPE MATCHES "STATIC")
+ set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhullstatic_r)
+ set(QHULL_LIBRARY_TYPE STATIC)
+ else()
+ if(PCL_SHARED_LIBS)
+ set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhull_r)
+ set(QHULL_LIBRARY_TYPE SHARED)
+ else()
+ set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhullstatic_r)
+ set(QHULL_LIBRARY_TYPE STATIC)
+ endif()
+ endif()
+ elseif(TARGET Qhull::qhullstatic_r)
+ set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhullstatic_r)
+ set(QHULL_LIBRARY_TYPE STATIC)
+ else()
+ set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhull_r)
+ set(QHULL_LIBRARY_TYPE SHARED)
+ endif()
+
+ return()
endif()
find_file(QHULL_HEADER
- NAMES libqhull/libqhull.h qhull.h
+ NAMES libqhull_r.h
HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" "${QHULL_INCLUDE_DIR}"
PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull"
- PATH_SUFFIXES qhull src/libqhull libqhull include)
+ PATH_SUFFIXES qhull_r src/libqhull_r libqhull_r include)
set(QHULL_HEADER "${QHULL_HEADER}" CACHE INTERNAL "QHull header" FORCE )
if(QHULL_HEADER)
get_filename_component(qhull_header ${QHULL_HEADER} NAME_WE)
- if("${qhull_header}" STREQUAL "qhull")
+ if("${qhull_header}" STREQUAL "qhull_r")
get_filename_component(QHULL_INCLUDE_DIR ${QHULL_HEADER} PATH)
- elseif("${qhull_header}" STREQUAL "libqhull")
+ elseif("${qhull_header}" STREQUAL "libqhull_r")
get_filename_component(QHULL_INCLUDE_DIR ${QHULL_HEADER} PATH)
get_filename_component(QHULL_INCLUDE_DIR ${QHULL_INCLUDE_DIR} PATH)
endif()
set(QHULL_INCLUDE_DIR "QHULL_INCLUDE_DIR-NOTFOUND")
endif()
-find_library(QHULL_LIBRARY
- NAMES ${QHULL_RELEASE_NAME}
+find_library(QHULL_LIBRARY_SHARED
+ NAMES qhull_r qhull
HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}"
PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull"
PATH_SUFFIXES project build bin lib)
-get_filename_component(QHULL_LIBRARY_NAME "${QHULL_LIBRARY}" NAME)
-
find_library(QHULL_LIBRARY_DEBUG
- NAMES ${QHULL_DEBUG_NAME} ${QHULL_RELEASE_NAME}
+ NAMES qhull_rd qhull_d
HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}"
PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull"
PATH_SUFFIXES project build bin lib debug/lib)
-if(NOT QHULL_LIBRARY_DEBUG)
- set(QHULL_LIBRARY_DEBUG ${QHULL_LIBRARY})
-endif()
-
-get_filename_component(QHULL_LIBRARY_DEBUG_NAME "${QHULL_LIBRARY_DEBUG}" NAME)
-
-if(QHULL_INCLUDE_DIR AND QHULL_LIBRARY)
-
- # Include directories
- set(QHULL_INCLUDE_DIRS ${QHULL_INCLUDE_DIR})
- unset(QHULL_INCLUDE_DIR)
- mark_as_advanced(QHULL_INCLUDE_DIRS)
+find_library(QHULL_LIBRARY_STATIC
+ NAMES qhullstatic_r
+ HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}"
+ PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull"
+ PATH_SUFFIXES project build bin lib)
- # Libraries
- set(QHULL_LIBRARIES optimized ${QHULL_LIBRARY} debug ${QHULL_LIBRARY_DEBUG})
- unset(QHULL_LIBRARY)
- unset(QHULL_LIBRARY_DEBUG)
- mark_as_advanced(QHULL_LIBRARIES)
+find_library(QHULL_LIBRARY_DEBUG_STATIC
+ NAMES qhullstatic_rd
+ HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}"
+ PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull"
+ PATH_SUFFIXES project build bin lib debug/lib)
+if(QHULL_LIBRARY_SHARED AND QHULL_LIBRARY_STATIC)
+ if(PCL_QHULL_REQUIRED_TYPE MATCHES "SHARED")
+ set(QHULL_LIBRARY_TYPE SHARED)
+ set(QHULL_LIBRARY ${QHULL_LIBRARY_SHARED})
+ elseif(PCL_QHULL_REQUIRED_TYPE MATCHES "STATIC")
+ set(QHULL_LIBRARY_TYPE STATIC)
+ set(QHULL_LIBRARY ${QHULL_LIBRARY_STATIC})
+ else()
+ if(PCL_SHARED_LIBS)
+ set(QHULL_LIBRARY_TYPE SHARED)
+ set(QHULL_LIBRARY ${QHULL_LIBRARY_SHARED})
+ else()
+ set(QHULL_LIBRARY_TYPE STATIC)
+ set(QHULL_LIBRARY ${QHULL_LIBRARY_STATIC})
+ endif()
+ endif()
+elseif(QHULL_LIBRARY_STATIC)
+ set(QHULL_LIBRARY_TYPE STATIC)
+ set(QHULL_LIBRARY ${QHULL_LIBRARY_STATIC})
+elseif(QHULL_LIBRARY_SHARED)
+ set(QHULL_LIBRARY_TYPE SHARED)
+ set(QHULL_LIBRARY ${QHULL_LIBRARY_SHARED})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Qhull
FOUND_VAR QHULL_FOUND
- REQUIRED_VARS QHULL_LIBRARIES QHULL_INCLUDE_DIRS
+ REQUIRED_VARS QHULL_LIBRARY QHULL_INCLUDE_DIR
)
if(QHULL_FOUND)
set(HAVE_QHULL ON)
- if(NOT QHULL_USE_STATIC)
- add_definitions("-Dqh_QHpointer")
- if(MSVC)
- add_definitions("-Dqh_QHpointer_dllimport")
+ add_library(QHULL::QHULL ${QHULL_LIBRARY_TYPE} IMPORTED)
+ set_target_properties(QHULL::QHULL PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${QHULL_INCLUDE_DIR}")
+ set_property(TARGET QHULL::QHULL APPEND PROPERTY IMPORTED_CONFIGURATIONS "RELEASE")
+ set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "CXX")
+ set_target_properties(QHULL::QHULL PROPERTIES INTERFACE_COMPILE_DEFINITIONS "qh_QHpointer")
+ if(MSVC)
+ set_target_properties(QHULL::QHULL PROPERTIES INTERFACE_COMPILE_DEFINITIONS "qh_QHpointer_dllimport")
+ endif()
+ if(WIN32 AND NOT (PCL_QHULL_REQUIRED_TYPE MATCHES "STATIC"))
+ set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_IMPLIB_RELEASE "${QHULL_LIBRARY}")
+ else()
+ set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_LOCATION_RELEASE "${QHULL_LIBRARY}")
+ endif()
+ if(QHULL_LIBRARY_DEBUG)
+ set_property(TARGET QHULL::QHULL APPEND PROPERTY IMPORTED_CONFIGURATIONS "DEBUG")
+ if(WIN32 AND NOT (PCL_QHULL_REQUIRED_TYPE MATCHES "STATIC"))
+ set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_IMPLIB_DEBUG "${QHULL_LIBRARY_DEBUG}")
+ else()
+ set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_LOCATION_DEBUG "${QHULL_LIBRARY_DEBUG}")
endif()
endif()
- message(STATUS "QHULL found (include: ${QHULL_INCLUDE_DIRS}, lib: ${QHULL_LIBRARIES})")
+ message(STATUS "QHULL found (include: ${QHULL_INCLUDE_DIR}, lib: ${QHULL_LIBRARY})")
endif()
mark_as_advanced(libusb_INCLUDE_DIRS libusb_LIBRARIES)
-if(LIBUSB_FOUND)
+if(libusb_FOUND)
add_library(libusb::libusb UNKNOWN IMPORTED)
set_target_properties(libusb::libusb PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${libusb_INCLUDE_DIR}")
set_target_properties(libusb::libusb PROPERTIES IMPORTED_LOCATION "${libusb_LIBRARIES}")
return()
endif()
-get_filename_component(BOOST_ROOT "${Boost_INCLUDE_DIR}" PATH)
-get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH)
-get_filename_component(EIGEN_ROOT "${EIGEN_INCLUDE_DIRS}" PATH)
-get_filename_component(QHULL_ROOT "${QHULL_INCLUDE_DIRS}" PATH)
-get_filename_component(VTK_ROOT "${VTK_DIR}" PATH)
-get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH)
-get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH)
+# get root directory of each dependency libraries to be copied to PCL/3rdParty
+get_filename_component(BOOST_ROOT "${Boost_INCLUDE_DIR}" PATH) # ../Boost/include/boost-x_x/ -> ../Boost/include/
+get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) # ../Boost/include/ -> ../Boost/
+get_filename_component(EIGEN_ROOT "${EIGEN_INCLUDE_DIRS}" PATH) # ../Eigen3/include/ -> ../Eigen3/
+get_filename_component(QHULL_ROOT "${Qhull_DIR}" PATH) # ../qhull/lib/cmake/Qhull/ -> ../qhull/lib/cmake
+get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/cmake/ -> ../qhull/lib/
+get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/ -> ../qhull/
+get_filename_component(VTK_ROOT "${VTK_DIR}" PATH) # ../VTK/lib/cmake/vtk-x.x/ -> ../VTK/lib/cmake/
+get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/cmake/ -> ../VTK/lib/
+get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/ -> ../VTK/
set(PCL_3RDPARTY_COMPONENTS)
foreach(dep Eigen Boost Qhull FLANN VTK)
string(APPEND CPACK_NSIS_PACKAGE_NAME "-msvc2017-${win_system_name}")
elseif(MSVC_VERSION MATCHES "^192[0-9]$")
string(APPEND CPACK_NSIS_PACKAGE_NAME "-msvc2019-${win_system_name}")
+ elseif(MSVC_VERSION MATCHES "^193[0-9]$")
+ string(APPEND CPACK_NSIS_PACKAGE_NAME "-msvc2022-${win_system_name}")
else()
string(APPEND CPACK_NSIS_PACKAGE_NAME "-${win_system_name}")
endif()
include(CheckCXXSourceRuns)
+ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
+ # Setting -march & -mtune just as required flags for check_cxx_source_runs,
+ # and CMAKE_REQUIRED_FLAGS will be restored after test runs.
+ set(CMAKE_REQUIRED_FLAGS "-march=native -mtune=native")
+ endif()
+
check_cxx_source_runs("
#include <immintrin.h>
int main()
HAVE_AVX)
endif()
+ set(CMAKE_REQUIRED_FLAGS)
+
+# Setting the -mavx/-mavx2 defines __AVX(2)__, see here https://stackoverflow.com/a/28939692
+# and this allows the compiler to use the codes for AVX behind code guards.
+ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
+ if(HAVE_AVX2)
+ set(AVX_FLAGS "-mavx2" PARENT_SCOPE)
+ elseif(HAVE_AVX)
+ set(AVX_FLAGS "-mavx" PARENT_SCOPE)
+ endif()
+ endif()
+
# Setting the /arch defines __AVX(2)__, see here https://docs.microsoft.com/en-us/cpp/build/reference/arch-x64?view=msvc-160
# AVX2 extends and includes AVX.
# Setting these defines allows the compiler to use AVX instructions as well as code guarded with the defines.
endif()
set(Boost_ADDITIONAL_VERSIONS
- "1.76.0" "1.76" "1.75.0" "1.75"
+ "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75"
"1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70"
"1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65")
-# Disable the config mode of find_package(Boost)
-set(Boost_NO_BOOST_CMAKE ON)
-
# Optional boost modules
find_package(Boost 1.65.0 QUIET COMPONENTS serialization mpi)
if(Boost_SERIALIZATION_FOUND)
if(Boost_FOUND)
set(BOOST_FOUND TRUE)
- # Obtain diagnostic information about Boost's automatic linking outputted
- # during compilation time.
- add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS})
- include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
- link_directories(${Boost_LIBRARY_DIRS})
endif()
# Find CUDA
-
if(MSVC)
# Setting this to true brakes Visual Studio builds.
set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE OFF CACHE BOOL "CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE")
if(CUDA_FOUND)
message(STATUS "Found CUDA Toolkit v${CUDA_VERSION_STRING}")
+
+ enable_language(CUDA)
set(HAVE_CUDA TRUE)
- # CUDA_ARCH_BIN is a space separated list of versions to include in output so-file. So you can set CUDA_ARCH_BIN = 10 11 12 13 20
- # Also user can specify virtual arch in parenthesis to limit instructions set,
- # for example CUDA_ARCH_BIN = 11(11) 12(11) 13(11) 20(11) 21(11) -> forces using only sm_11 instructions.
- # The CMake scripts interpret XX as XX (XX). This allows user to omit parenthesis.
- # Arch 21 is an exceptional case since it doesn't have own sm_21 instructions set.
- # So 21 = 21(21) is an invalid configuration and user has to explicitly force previous sm_20 instruction set via 21(20).
- # CUDA_ARCH_BIN adds support of only listed GPUs. As alternative CMake scripts also parse 'CUDA_ARCH_PTX' variable,
- # which is a list of intermediate PTX codes to include in final so-file. The PTX code can/will be JIT compiled for any current or future GPU.
- # To add support of older GPU for kinfu, I would embed PTX 11 and 12 into so-file. GPU with sm_13 will run PTX 12 code (no difference for kinfu)
-
- # Find a complete list for CUDA compute capabilities at http://developer.nvidia.com/cuda-gpus
-
- # For a list showing CUDA toolkit version support for compute capabilities see: https://en.wikipedia.org/wiki/CUDA
- # or the nvidia release notes ie:
- # https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-general-new-features
- # or
- # https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#deprecated-features
-
- if(NOT ${CUDA_VERSION_STRING} VERSION_LESS "11.0")
- set(__cuda_arch_bin "3.5 3.7 5.0 5.2 5.3 6.0 6.1 6.2 7.0 7.2 7.5 8.0 8.6")
- elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "10.0")
- set(__cuda_arch_bin "3.0 3.2 3.5 3.7 5.0 5.2 5.3 6.0 6.1 6.2 7.0 7.2 7.5")
- elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "9.0")
- set(__cuda_arch_bin "3.0 3.2 3.5 3.7 5.0 5.2 5.3 6.0 6.1 6.2 7.0 7.2")
+ if (CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
+ if(${CUDA_VERSION_STRING} VERSION_GREATER_EQUAL "11.1")
+ execute_process(COMMAND ${CMAKE_CUDA_COMPILER} --list-gpu-code RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE OUTPUT_VAL)
+ if(EXIT_CODE EQUAL 0)
+ #Remove sm_
+ string(REPLACE "sm_" "" OUTPUT_VAL ${OUTPUT_VAL})
+ #Convert to list
+ string(REPLACE "\n" ";" __CUDA_ARCH_BIN ${OUTPUT_VAL})
+ #Remove last empty entry
+ list(REMOVE_AT __CUDA_ARCH_BIN -1)
+ else()
+ message(FATAL_ERROR "Failed to run NVCC to get list of GPU codes: ${EXIT_CODE}")
+ endif()
+ elseif(${CUDA_VERSION_STRING} VERSION_GREATER_EQUAL "11.0")
+ set(__CUDA_ARCH_BIN "35;37;50;52;53;60;61;62;70;72;75;80")
+ elseif(${CUDA_VERSION_STRING} VERSION_GREATER_EQUAL "10.0")
+ set(__CUDA_ARCH_BIN "30;32;35;37;50;52;53;60;61;62;70;72;75")
+ elseif(${CUDA_VERSION_STRING} VERSION_GREATER_EQUAL "9.1")
+ set(__CUDA_ARCH_BIN "30;32;35;37;50;52;53;60;61;62;70;72")
+ else()
+ set(__CUDA_ARCH_BIN "30;32;35;37;50;52;53;60;61;62;70")
+ endif()
+ else()
+ message(FATAL_ERROR "Unsupported CUDA compiler ${CMAKE_CUDA_COMPILER_ID}.")
endif()
- set(CUDA_ARCH_BIN ${__cuda_arch_bin} CACHE STRING "Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported")
-
- set(CUDA_ARCH_PTX "" CACHE STRING "Specify 'virtual' PTX arch to build PTX intermediate code for. Example: 1.0 1.2 or 10 12")
- #set(CUDA_ARCH_PTX "1.1 1.2" CACHE STRING "Specify 'virtual' PTX arch to build PTX intermediate code for. Example: 1.0 1.2 or 10 12")
-
- # Guess this macros will be included in cmake distributive
- include(${PCL_SOURCE_DIR}/cmake/CudaComputeTargetFlags.cmake)
- APPEND_TARGET_ARCH_FLAGS()
-
- # Prevent compilation issues between recent gcc versions and old CUDA versions
- list(APPEND CUDA_NVCC_FLAGS "-D_FORCE_INLINES")
+ set(CUDA_ARCH_BIN ${__CUDA_ARCH_BIN} CACHE STRING "Specify 'real' GPU architectures to build binaries for")
- # Allow calling a constexpr __host__ function from a __device__ function.
- list(APPEND CUDA_NVCC_FLAGS "--expt-relaxed-constexpr")
+ if(POLICY CMP0104)
+ cmake_policy(SET CMP0104 NEW)
+ set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH_BIN})
+ message(STATUS "CMAKE_CUDA_ARCHITECTURES: ${CMAKE_CUDA_ARCHITECTURES}")
+
+ #Add empty project as its not required with newer CMake
+ add_library(pcl_cuda INTERFACE)
+ else()
+ # Generate SASS
+ set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH_BIN})
+ # Generate PTX for last architecture
+ list(GET CUDA_ARCH_BIN -1 ver)
+ set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode arch=compute_${ver},code=compute_${ver}")
+ message(STATUS "CMAKE_CUDA_FLAGS: ${CMAKE_CUDA_FLAGS}")
+
+ add_library(pcl_cuda INTERFACE)
+ target_include_directories(pcl_cuda INTERFACE ${CUDA_TOOLKIT_INCLUDE})
+
+ endif ()
endif()
--- /dev/null
+#
+#pcl_find_libusb is used due to VCPKG making impossible to use local findXX modules.
+# and VCPKG findlibusb doesn't create the libusb targets.
+
+# Find and set libusb
+find_package(libusb)
+
+if(TARGET libusb::libusb)
+ #libusb target is found by the find_package script.
+ #VCPKG skip PCLs findlibusb and sets its own variables which is handled below.
+ return()
+endif()
+
+#Handle VCPKG definitions
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(libusb DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIRS)
+
+mark_as_advanced(LIBUSB_INCLUDE_DIRS LIBUSB_LIBRARIES)
+
+if(libusb_FOUND)
+ add_library(libusb::libusb UNKNOWN IMPORTED)
+ if(${LIBUSB_INCLUDE_DIRS})
+ set_target_properties(libusb::libusb PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBUSB_INCLUDE_DIRS}")
+ endif()
+ if(EXISTS "${LIBUSB_LIBRARY}")
+ set_target_properties(libusb::libusb PROPERTIES IMPORTED_LOCATION ${LIBUSB_LIBRARY})
+ endif()
+ if(EXISTS "${LIBUSB_LIBRARY_DEBUG}")
+ set_target_properties(libusb::libusb PROPERTIES IMPORTED_LOCATION_DEBUG ${LIBUSB_LIBRARY_DEBUG})
+ endif()
+ if(EXISTS "${LIBUSB_LIBRARY_RELEASE}")
+ set_target_properties(libusb::libusb PROPERTIES IMPORTED_LOCATION_RELEASE ${LIBUSB_LIBRARY_RELEASE})
+ endif()
+endif()
--- /dev/null
+# This file is not processed if WITH_QT evaluates to a CMake false constant.
+#
+# First we convert WITH_QT to WITH_QT_STR with
+# - CMake true constants to string YES (except numbers unequal 1)
+# - Other values to upper case string
+#
+# Background: WITH_QT was previously boolean and we want to be backwards compatible.
+#
+# This if condition matches all CMake true constants (`${WITH_QT}`) except numbers other than 1 (`NOT (WITH_QT LESS 1 OR WITH_QT GREATER 1)`).
+#
+# This way we prevent things like -DWITH_QT=5 to be handled as YES instead of QT5.
+# Setting -DWITH_QT=5 will error and inform you to use -DWITH_QT=QT5 instead.
+# (This breaks backward compatibility, but hopefully no one will use values not equal to 1 if they want to express true.)
+#
+# Note: "NOT (WITH_QT LESS 1 OR WITH_QT GREATER 1)" is not the same as
+# "WITH_QT EQUAL 1" because "LESS/GREATER/EQUAL" all pre-check if WITH_QT is a valid number.
+if(${WITH_QT} AND NOT (WITH_QT LESS 1 OR WITH_QT GREATER 1))
+ set(WITH_QT_STR "YES")
+else()
+ string(TOUPPER ${WITH_QT} WITH_QT_STR)
+endif()
+
+if(NOT WITH_QT_STR MATCHES "^(AUTO|YES|QT6|QT5)$")
+ message(FATAL_ERROR "Option WITH_QT must be one of AUTO|YES|QT6|QT5|NO but is '${WITH_QT}'")
+endif()
+
+if(WITH_QT_STR MATCHES "^(AUTO|YES|QT6)$")
+ find_package(Qt6 QUIET COMPONENTS Concurrent OpenGL Widgets)
+ set(QT6_FOUND ${Qt6_FOUND})
+ set(QT_FOUND ${QT6_FOUND})
+ if (QT6_FOUND)
+ set(QTX Qt6)
+ endif()
+endif()
+
+if(WITH_QT_STR MATCHES "^(AUTO|YES|QT5)$" AND NOT QT6_FOUND)
+ find_package(Qt5 5.9.5 QUIET COMPONENTS Concurrent OpenGL Widgets)
+ set(QT5_FOUND ${Qt5_FOUND})
+ set(QT_FOUND ${QT5_FOUND})
+ if(QT5_FOUND)
+ set(QTX Qt5)
+ endif()
+endif()
+
+if(NOT WITH_QT_STR MATCHES "^(AUTO)$" AND NOT QT_FOUND)
+ message(FATAL_ERROR "Can not find Qt required by WITH_QT=${WITH_QT}.")
+endif()
+
+if(NOT QT_FOUND)
+ message(STATUS "Qt is not found.")
+ return()
+endif()
+
+set(QT_VERSION ${${QTX}_VERSION})
+message(STATUS "Qt version: ${QT_VERSION}")
+
+set(QT_DISABLE_PRECATED_BEFORE_VAL "0x050900")
+
+#Set Cmake Auto features to skip .hh files
+if(POLICY CMP0100)
+ cmake_policy(SET CMP0100 OLD)
+endif()
+
+#If building CUDA required libraries
+#Change ${QTX}::Core fixed -fPIC flags to conditionally only CXX
+#TODO: To be removed when QT is >5.14.1
+if(BUILD_CUDA OR BUILD_GPU)
+ if(${QTX}Widgets_VERSION VERSION_LESS 5.14.1)
+ get_property(core_options TARGET ${QTX}::Core PROPERTY INTERFACE_COMPILE_OPTIONS)
+ string(REPLACE "-fPIC" "$<IF:$<COMPILE_LANGUAGE:CXX>,-fPIC,>" new_core_options ${core_options})
+ set_property(TARGET ${QTX}::Core PROPERTY INTERFACE_COMPILE_OPTIONS ${new_core_options})
+ endif()
+endif()
+
+get_property(core_def TARGET ${QTX}::Core PROPERTY INTERFACE_COMPILE_DEFINITIONS)
+list(APPEND core_def "QT_DISABLE_DEPRECATED_BEFORE=${QT_DISABLE_PRECATED_BEFORE_VAL}")
+set_property(TARGET ${QTX}::Core PROPERTY INTERFACE_COMPILE_DEFINITIONS ${core_def})
set(SSE_FLAGS)
set(SSE_DEFINITIONS)
- if(NOT CMAKE_CROSSCOMPILING)
+ if(PCL_ENABLE_MARCHNATIVE AND (NOT CMAKE_CROSSCOMPILING))
# Test GCC/G++ and CLANG
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-march=native" HAVE_MARCH)
- if(HAVE_MARCH)
- list(APPEND SSE_FLAGS "-march=native")
- else()
- list(APPEND SSE_FLAGS "-mtune=native")
- endif()
- message(STATUS "Using CPU native flags for SSE optimization: ${SSE_FLAGS}")
endif()
endif()
else()
# Setting -ffloat-store to alleviate 32bit vs 64bit discrepancies on non-SSE
# platforms.
- list(APPEND SSE_FLAGS "-ffloat-store")
+ string(APPEND SSE_FLAGS " -ffloat-store")
+ endif()
+
+ if(PCL_ENABLE_MARCHNATIVE AND (NOT CMAKE_CROSSCOMPILING))
+ if(HAVE_MARCH)
+ string(APPEND SSE_FLAGS " -march=native")
+ else()
+ string(APPEND SSE_FLAGS " -mtune=native")
+ endif()
+ message(STATUS "Using CPU native flags for SSE optimization: ${SSE_FLAGS}")
endif()
elseif(MSVC AND NOT CMAKE_SIZEOF_VOID_P)
if(SSE_LEVEL GREATER_EQUAL 2.0)
FiltersSources
ImagingCore
ImagingSources
+ InteractionImage
InteractionStyle
InteractionWidgets
IOCore
message(WARNING "Missing vtk modules: ${vtkMissingComponents}")
endif()
-if("vtkGUISupportQt" IN_LIST VTK_MODULES_ENABLED AND "vtkRenderingQt" IN_LIST VTK_MODULES_ENABLED)
+if("vtkGUISupportQt" IN_LIST VTK_MODULES_ENABLED)
set(HAVE_QVTK TRUE)
#PCL_VTK_COMPONENTS is used in the PCLConfig.cmake to refind the required modules.
#Pre vtk 9.0, all vtk libraries are linked into pcl_visualizer.
#Subprojects can link against pcl_visualizer and directly use VTK-QT libraries.
- list(APPEND PCL_VTK_COMPONENTS vtkRenderingQt vtkGUISupportQt)
+ list(APPEND PCL_VTK_COMPONENTS vtkGUISupportQt)
elseif("GUISupportQt" IN_LIST VTK_AVAILABLE_COMPONENTS AND "RenderingQt" IN_LIST VTK_AVAILABLE_COMPONENTS)
set(HAVE_QVTK TRUE)
#PCL_VTK_COMPONENTS is used in the PCLConfig.cmake to refind the required modules.
#Post vtk 9.0, only required libraries are linked against pcl_visualizer.
#Subprojects need to manually link to VTK-QT libraries.
- list(APPEND PCL_VTK_COMPONENTS RenderingQt GUISupportQt)
+ list(APPEND PCL_VTK_COMPONENTS GUISupportQt)
else()
unset(HAVE_QVTK)
endif()
# Options for building PCL.
+# By default, PCL restricts the dependency search to only shared or only static libraries,
+# depending on whether PCL itself is built as a shared or static library.
+# This restriction is undesirable when a dependency is available
+# only as a shared library while building PCL as a static library, or vice versa.
+# In such cases, the user may prefer to use the found dependency anyway.
+# For example, the user may prefer to build PCL as a static library
+# using a shared OpenGL library provided by the system.
+# This option allows to override the restriction imposed by default.
+option(PCL_ALLOW_BOTH_SHARED_AND_STATIC_DEPENDENCIES, "Do not force PCL dependencies to be all shared or all static." OFF)
+
# Build shared libraries by default.
option(PCL_SHARED_LIBS "Build shared libraries." ON)
if(PCL_SHARED_LIBS)
set(PCL_LIB_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX})
set(PCL_LIB_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
set(PCL_LIB_TYPE "SHARED")
-# set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
- if(WIN32)
- set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_IMPORT_LIBRARY_SUFFIX})
+ if(NOT PCL_ALLOW_BOTH_SHARED_AND_STATIC_DEPENDENCIES)
+ if(WIN32)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_IMPORT_LIBRARY_SUFFIX})
+ endif()
endif()
else()
set(PCL_LIB_PREFIX ${CMAKE_STATIC_LIBRARY_PREFIX})
set(PCL_LIB_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX})
set(PCL_LIB_TYPE "STATIC")
- set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
+ if(NOT PCL_ALLOW_BOTH_SHARED_AND_STATIC_DEPENDENCIES)
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
+ endif()
endif()
mark_as_advanced(PCL_SHARED_LIBS)
mark_as_advanced(PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32)
# Build with shared/static linking for FLANN (advanced users)
-set(PCL_FLANN_REQUIRED_TYPE "DONTCARE" CACHE STRING "Select build type to use (STATIC/SHARED).")
+set(PCL_FLANN_REQUIRED_TYPE "DONTCARE" CACHE STRING "Select build type to use STATIC or SHARED.")
set_property(CACHE PCL_FLANN_REQUIRED_TYPE PROPERTY STRINGS DONTCARE SHARED STATIC)
-
-mark_as_advanced(PCL_BUILD_WITH_FLANN_DYNAMIC_LINKING_WIN32)
+mark_as_advanced(PCL_FLANN_REQUIRED_TYPE)
# Build with dynamic linking for QHull (advanced users)
-option(PCL_BUILD_WITH_QHULL_DYNAMIC_LINKING_WIN32 "Build against a dynamically linked QHull on Win32 platforms." OFF)
-mark_as_advanced(PCL_BUILD_WITH_QHULL_DYNAMIC_LINKING_WIN32)
+set(PCL_QHULL_REQUIRED_TYPE "DONTCARE" CACHE STRING "Select build type to use STATIC or SHARED.")
+set_property(CACHE PCL_QHULL_REQUIRED_TYPE PROPERTY STRINGS DONTCARE SHARED STATIC)
+mark_as_advanced(PCL_QHULL_REQUIRED_TYPE)
# Precompile for a minimal set of point types instead of all.
option(PCL_ONLY_CORE_POINT_TYPES "Compile explicitly only for a small subset of point types (e.g., pcl::PointXYZ instead of PCL_XYZ_POINT_TYPES)." OFF)
option(PCL_ENABLE_SSE "Enable or Disable SSE optimizations." ON)
mark_as_advanced(PCL_ENABLE_SSE)
-if(WIN32)
- # Enable or Disable the check for AVX optimizations
- option(PCL_ENABLE_AVX "Enable or Disable AVX optimizations." ON)
- mark_as_advanced(PCL_ENABLE_AVX)
+# Enable or Disable the check for AVX optimizations
+option(PCL_ENABLE_AVX "Enable or Disable AVX optimizations." ON)
+mark_as_advanced(PCL_ENABLE_AVX)
+
+if(UNIX)
+ # Enable or Disable the check for March Native optimizations
+ option(PCL_ENABLE_MARCHNATIVE "Enable or Disable march native optimizations." ON)
+ mark_as_advanced(PCL_ENABLE_MARCHNATIVE)
+else()
+ set(PCL_ENABLE_MARCHNATIVE FALSE)
endif()
# Allow the user to enable compiler cache
set(PCLCONFIG_OPTIONAL_DEPENDENCIES)
set(PCLCONFIG_SSE_DEFINITIONS "${SSE_DEFINITIONS}")
set(PCLCONFIG_SSE_COMPILE_OPTIONS ${SSE_FLAGS})
+set(PCLCONFIG_AVX_COMPILE_OPTIONS ${AVX_FLAGS})
foreach(_ss ${PCL_SUBSYSTEMS_MODULES})
PCL_GET_SUBSYS_STATUS(_status ${_ss})
add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES})
PCL_ADD_VERSION_INFO(${_name})
target_compile_features(${_name} PUBLIC ${PCL_CXX_COMPILE_FEATURES})
- # must link explicitly against boost.
- target_link_libraries(${_name} ${Boost_LIBRARIES} Threads::Threads)
+
+ target_link_libraries(${_name} Threads::Threads)
if(TARGET OpenMP::OpenMP_CXX)
target_link_libraries(${_name} OpenMP::OpenMP_CXX)
endif()
RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT}
LIBRARY DESTINATION ${LIB_INSTALL_DIR} COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT})
+
+ # Copy PDB if available
+ if(MSVC AND PCL_SHARED_LIBS)
+ install(FILES $<TARGET_PDB_FILE:${_name}> DESTINATION ${BIN_INSTALL_DIR} OPTIONAL)
+ endif()
endfunction()
###############################################################################
cmake_parse_arguments(ADD_LIBRARY_OPTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
REMOVE_VTK_DEFINITIONS()
- if(PCL_SHARED_LIBS)
- # to overcome a limitation in cuda_add_library, we add manually PCLAPI_EXPORTS macro
- cuda_add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES} OPTIONS -DPCLAPI_EXPORTS)
- else()
- cuda_add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES})
- endif()
+
+ add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES})
+
PCL_ADD_VERSION_INFO(${_name})
- # must link explicitly against boost.
- target_link_libraries(${_name} ${Boost_LIBRARIES})
+ target_compile_options(${_name} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>: ${GEN_CODE} --expt-relaxed-constexpr>)
+
+ target_include_directories(${_name} PRIVATE ${CUDA_TOOLKIT_INCLUDE})
set_target_properties(${_name} PROPERTIES
VERSION ${PCL_VERSION}
add_executable(${_name} ${ADD_LIBRARY_OPTION_SOURCES})
endif()
PCL_ADD_VERSION_INFO(${_name})
- # must link explicitly against boost.
- target_link_libraries(${_name} ${Boost_LIBRARIES} Threads::Threads)
+
+ target_link_libraries(${_name} Threads::Threads)
if(WIN32 AND MSVC)
set_target_properties(${_name} PROPERTIES DEBUG_OUTPUT_NAME ${_name}${CMAKE_DEBUG_POSTFIX}
cmake_parse_arguments(ADD_LIBRARY_OPTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
REMOVE_VTK_DEFINITIONS()
- cuda_add_executable(${_name} ${ADD_LIBRARY_OPTION_SOURCES})
+
+ add_executable(${_name} ${ADD_LIBRARY_OPTION_SOURCES})
+
PCL_ADD_VERSION_INFO(${_name})
- # must link explicitly against boost.
- target_link_libraries(${_name} ${Boost_LIBRARIES})
+ target_compile_options(${_name} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>: ${GEN_CODE} --expt-relaxed-constexpr>)
+
+ target_include_directories(${_name} PRIVATE ${CUDA_TOOLKIT_INCLUDE})
if(WIN32 AND MSVC)
set_target_properties(${_name} PROPERTIES DEBUG_OUTPUT_NAME ${_name}${CMAKE_DEBUG_POSTFIX}
target_link_libraries(${_exename} Threads::Threads)
- # must link explicitly against boost only on Windows
- target_link_libraries(${_exename} ${Boost_LIBRARIES})
-
#Only applies to MSVC
if(MSVC)
#Requires CMAKE version 3.13.0
###############################################################################
# Make a pkg-config file for a library. Do not include general PCL stuff in the
# arguments; they will be added automatically.
-# _name The library name. "pcl_" will be preprended to this.
+# _name The library name. Please prepend "pcl_" to ensure no conflicts in user systems
# COMPONENT The part of PCL that this pkg-config file belongs to.
# DESC Description of the library.
# PCL_DEPS External dependencies to pcl libs, as a list. (will get mangled to external pkg-config name)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${kissfft_srcs} ${incs} ${common_incs} ${impl_incs} ${tools_incs} ${kissfft_incs} ${common_incs_impl} ${range_image_incs} ${range_image_incs_impl})
+target_link_libraries(${LIB_NAME} Boost::boost)
+
if(MSVC AND NOT (MSVC_VERSION LESS 1915))
# MSVC resolved a byte alignment issue in compiler version 15.9
# We get this due to using Eigen objects and allocating those objects with make_shared
const Eigen::Vector3f& origin,
Eigen::Affine3f& transformation);
- /** \brief Extract the Euler angles (XYZ-convention) from the given transformation
+ /** \brief Extract the Euler angles (intrinsic rotations, ZYX-convention) from the given transformation
* \param[in] t the input transformation matrix
* \param[in] roll the resulting roll angle
* \param[in] pitch the resulting pitch angle
template <typename Scalar> void
getEulerAngles (const Eigen::Transform<Scalar, 3, Eigen::Affine> &t, Scalar &roll, Scalar &pitch, Scalar &yaw);
- /** Extract x,y,z and the Euler angles (XYZ-convention) from the given transformation
+ /** Extract x,y,z and the Euler angles (intrinsic rotations, ZYX-convention) from the given transformation
* \param[in] t the input transformation matrix
* \param[out] x the resulting x translation
* \param[out] y the resulting y translation
Scalar &x, Scalar &y, Scalar &z,
Scalar &roll, Scalar &pitch, Scalar &yaw);
- /** \brief Create a transformation from the given translation and Euler angles (XYZ-convention)
+ /** \brief Create a transformation from the given translation and Euler angles (intrinsic rotations, ZYX-convention)
* \param[in] x the input x translation
* \param[in] y the input y translation
* \param[in] z the input z translation
return (getTransformation<double> (x, y, z, roll, pitch, yaw, t));
}
- /** \brief Create a transformation from the given translation and Euler angles (XYZ-convention)
+ /** \brief Create a transformation from the given translation and Euler angles (intrinsic rotations, ZYX-convention)
* \param[in] x the input x translation
* \param[in] y the input y translation
* \param[in] z the input z translation
Eigen::Matrix<Scalar, 3, 3> &covariance_matrix,
Eigen::Matrix<Scalar, 4, 1> ¢roid)
{
+ // Shifted data/with estimate of mean. This gives very good accuracy and good performance.
// create the buffer on the stack which is much faster than using cloud[indices[i]] and centroid as a buffer
Eigen::Matrix<Scalar, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<Scalar, 1, 9, Eigen::RowMajor>::Zero ();
+ Eigen::Matrix<Scalar, 3, 1> K(0.0, 0.0, 0.0);
+ for(const auto& point: cloud)
+ if(isFinite(point)) {
+ K.x() = point.x; K.y() = point.y; K.z() = point.z; break;
+ }
std::size_t point_count;
if (cloud.is_dense)
{
// For each point in the cloud
for (const auto& point: cloud)
{
- accu [0] += point.x * point.x;
- accu [1] += point.x * point.y;
- accu [2] += point.x * point.z;
- accu [3] += point.y * point.y; // 4
- accu [4] += point.y * point.z; // 5
- accu [5] += point.z * point.z; // 8
- accu [6] += point.x;
- accu [7] += point.y;
- accu [8] += point.z;
+ Scalar x = point.x - K.x(), y = point.y - K.y(), z = point.z - K.z();
+ accu [0] += x * x;
+ accu [1] += x * y;
+ accu [2] += x * z;
+ accu [3] += y * y;
+ accu [4] += y * z;
+ accu [5] += z * z;
+ accu [6] += x;
+ accu [7] += y;
+ accu [8] += z;
}
}
else
if (!isFinite (point))
continue;
- accu [0] += point.x * point.x;
- accu [1] += point.x * point.y;
- accu [2] += point.x * point.z;
- accu [3] += point.y * point.y;
- accu [4] += point.y * point.z;
- accu [5] += point.z * point.z;
- accu [6] += point.x;
- accu [7] += point.y;
- accu [8] += point.z;
+ Scalar x = point.x - K.x(), y = point.y - K.y(), z = point.z - K.z();
+ accu [0] += x * x;
+ accu [1] += x * y;
+ accu [2] += x * z;
+ accu [3] += y * y;
+ accu [4] += y * z;
+ accu [5] += z * z;
+ accu [6] += x;
+ accu [7] += y;
+ accu [8] += z;
++point_count;
}
}
- accu /= static_cast<Scalar> (point_count);
if (point_count != 0)
{
- //centroid.head<3> () = accu.tail<3> (); -- does not compile with Clang 3.0
- centroid[0] = accu[6]; centroid[1] = accu[7]; centroid[2] = accu[8];
+ accu /= static_cast<Scalar> (point_count);
+ centroid[0] = accu[6] + K.x(); centroid[1] = accu[7] + K.y(); centroid[2] = accu[8] + K.z();
centroid[3] = 1;
covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6];
covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7];
Eigen::Matrix<Scalar, 3, 3> &covariance_matrix,
Eigen::Matrix<Scalar, 4, 1> ¢roid)
{
+ // Shifted data/with estimate of mean. This gives very good accuracy and good performance.
// create the buffer on the stack which is much faster than using cloud[indices[i]] and centroid as a buffer
Eigen::Matrix<Scalar, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<Scalar, 1, 9, Eigen::RowMajor>::Zero ();
+ Eigen::Matrix<Scalar, 3, 1> K(0.0, 0.0, 0.0);
+ for(const auto& index : indices)
+ if(isFinite(cloud[index])) {
+ K.x() = cloud[index].x; K.y() = cloud[index].y; K.z() = cloud[index].z; break;
+ }
std::size_t point_count;
if (cloud.is_dense)
{
point_count = indices.size ();
for (const auto &index : indices)
{
- //const PointT& point = cloud[*iIt];
- accu [0] += cloud[index].x * cloud[index].x;
- accu [1] += cloud[index].x * cloud[index].y;
- accu [2] += cloud[index].x * cloud[index].z;
- accu [3] += cloud[index].y * cloud[index].y;
- accu [4] += cloud[index].y * cloud[index].z;
- accu [5] += cloud[index].z * cloud[index].z;
- accu [6] += cloud[index].x;
- accu [7] += cloud[index].y;
- accu [8] += cloud[index].z;
+ Scalar x = cloud[index].x - K.x(), y = cloud[index].y - K.y(), z = cloud[index].z - K.z();
+ accu [0] += x * x;
+ accu [1] += x * y;
+ accu [2] += x * z;
+ accu [3] += y * y;
+ accu [4] += y * z;
+ accu [5] += z * z;
+ accu [6] += x;
+ accu [7] += y;
+ accu [8] += z;
}
}
else
continue;
++point_count;
- accu [0] += cloud[index].x * cloud[index].x;
- accu [1] += cloud[index].x * cloud[index].y;
- accu [2] += cloud[index].x * cloud[index].z;
- accu [3] += cloud[index].y * cloud[index].y; // 4
- accu [4] += cloud[index].y * cloud[index].z; // 5
- accu [5] += cloud[index].z * cloud[index].z; // 8
- accu [6] += cloud[index].x;
- accu [7] += cloud[index].y;
- accu [8] += cloud[index].z;
+ Scalar x = cloud[index].x - K.x(), y = cloud[index].y - K.y(), z = cloud[index].z - K.z();
+ accu [0] += x * x;
+ accu [1] += x * y;
+ accu [2] += x * z;
+ accu [3] += y * y;
+ accu [4] += y * z;
+ accu [5] += z * z;
+ accu [6] += x;
+ accu [7] += y;
+ accu [8] += z;
}
}
- accu /= static_cast<Scalar> (point_count);
- //Eigen::Vector3f vec = accu.tail<3> ();
- //centroid.head<3> () = vec;//= accu.tail<3> ();
- //centroid.head<3> () = accu.tail<3> (); -- does not compile with Clang 3.0
- centroid[0] = accu[6]; centroid[1] = accu[7]; centroid[2] = accu[8];
- centroid[3] = 1;
- covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6];
- covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7];
- covariance_matrix.coeffRef (2) = accu [2] - accu [6] * accu [8];
- covariance_matrix.coeffRef (4) = accu [3] - accu [7] * accu [7];
- covariance_matrix.coeffRef (5) = accu [4] - accu [7] * accu [8];
- covariance_matrix.coeffRef (8) = accu [5] - accu [8] * accu [8];
- covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1);
- covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2);
- covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5);
-
+ if (point_count != 0)
+ {
+ accu /= static_cast<Scalar> (point_count);
+ centroid[0] = accu[6] + K.x(); centroid[1] = accu[7] + K.y(); centroid[2] = accu[8] + K.z();
+ centroid[3] = 1;
+ covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6];
+ covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7];
+ covariance_matrix.coeffRef (2) = accu [2] - accu [6] * accu [8];
+ covariance_matrix.coeffRef (4) = accu [3] - accu [7] * accu [7];
+ covariance_matrix.coeffRef (5) = accu [4] - accu [7] * accu [8];
+ covariance_matrix.coeffRef (8) = accu [5] - accu [8] * accu [8];
+ covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1);
+ covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2);
+ covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5);
+ }
return (static_cast<unsigned int> (point_count));
}
cloud.is_dense = msg.is_dense == 1;
// Copy point data
- std::uint32_t num_points = msg.width * msg.height;
- cloud.resize (num_points);
+ cloud.resize (msg.width * msg.height);
std::uint8_t* cloud_data = reinterpret_cast<std::uint8_t*>(&cloud[0]);
// Check if we can copy adjacent points in a single memcpy. We can do so if there
field_map[0].size == msg.point_step &&
field_map[0].size == sizeof(PointT))
{
- std::uint32_t cloud_row_step = static_cast<std::uint32_t> (sizeof (PointT) * cloud.width);
+ const auto cloud_row_step = (sizeof (PointT) * cloud.width);
const std::uint8_t* msg_data = &msg.data[0];
// Should usually be able to copy all rows at once
if (msg.row_step == cloud_row_step)
}
else
{
- for (std::uint32_t i = 0; i < msg.height; ++i, cloud_data += cloud_row_step, msg_data += msg.row_step)
+ for (uindex_t i = 0; i < msg.height; ++i, cloud_data += cloud_row_step, msg_data += msg.row_step)
memcpy (cloud_data, msg_data, cloud_row_step);
}
else
{
// If not, memcpy each group of contiguous fields separately
- for (index_t row = 0; row < msg.height; ++row)
+ for (uindex_t row = 0; row < msg.height; ++row)
{
const std::uint8_t* row_data = &msg.data[row * msg.row_step];
- for (index_t col = 0; col < msg.width; ++col)
+ for (uindex_t col = 0; col < msg.width; ++col)
{
const std::uint8_t* msg_data = row_data + col * msg.point_step;
for (const detail::FieldMapping& mapping : field_map)
msg.header = cloud.header;
msg.point_step = sizeof (PointT);
- msg.row_step = static_cast<std::uint32_t> (sizeof (PointT) * msg.width);
+ msg.row_step = (sizeof (PointT) * msg.width);
msg.is_dense = cloud.is_dense;
/// @todo msg.is_bigendian = ?;
}
msg.height = cloud.height;
msg.width = cloud.width;
}
- int rgb_offset = cloud.fields[rgb_index].offset;
- int point_step = cloud.point_step;
+ auto rgb_offset = cloud.fields[rgb_index].offset;
+ const auto point_step = cloud.point_step;
// pcl::image_encodings::BGR8;
msg.header = cloud.header;
msg.encoding = "bgr8";
- msg.step = static_cast<std::uint32_t>(msg.width * sizeof (std::uint8_t) * 3);
+ msg.step = (msg.width * sizeof (std::uint8_t) * 3);
msg.data.resize (msg.step * msg.height);
for (std::size_t y = 0; y < cloud.height; y++)
0.25f * histogram_[histogram_.size () - 2] * 2.0f;
if (last_value > max)
{
- max_idx = histogram_.size ();
+ max_idx = histogram_.size () - 1;
}
// Compute mean value.
// top-level (not recursive)
if (fstride==1 && p<=5)
{
- int k;
+ int k=0;
// execute the p different work units in different threads
// We cannot use OPENMP_LEGACY_CONST_DATA_SHARING_RULE here, because we cannot include
)
include_directories(./include)
-#set(LIB_NAME pcl_${SUBSYS_NAME})
+set(LIB_NAME "pcl_${SUBSYS_NAME}")
set(EXT_DEPS CUDA)
-#PCL_MAKE_PKGCONFIG(${LIB_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}"
-# "${SUBSYS_DEPS}" "${EXT_DEPS}" "" "" "")
+PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC "${SUBSYS_DESC}"
+ PCL_DEPS "${SUBSYS_DEPS}" EXT_DEPS "" HEADER_ONLY)
# Install include files
PCL_ADD_INCLUDES(${SUBSYS_NAME} "cuda" ${incs})
* returned (true) or inside (false).
* \param limit_negative the limit_negative flag
*/
+ PCL_DEPRECATED(1, 16, "use bool getFilterLimitsNegative() instead")
inline void
getFilterLimitsNegative (bool &limit_negative) { limit_negative = filter_limit_negative_; }
+
+ /** \brief Get whether the data outside the interval (min/max) is to be
+ * returned (true) or inside (false).
+ * \return true if data \b outside the interval [min; max] is to be returned, false otherwise
+ */
inline bool
getFilterLimitsNegative () { return (filter_limit_negative_); }
#pragma once
+PCL_DEPRECATED_HEADER(1, 16, "The CUDA VoxelGrid filter does not work. Use the CPU VoxelGrid filter instead.")
+
#include <pcl_cuda/filters/filter.h>
#include <pcl_cuda/filters/passthrough.h>
#include <thrust/count.h>
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.imgmath', 'sphinxcontrib.doxylink.doxylink']
+extensions = ['sphinx.ext.imgmath', 'sphinxcontrib.doxylink']
# Add any paths that contain templates here, relative to this directory.
# templates_path = ['_templates']
file_insertion_enabled = True
raw_enabled = True
# Set up doxylink
-doxylink = {'pcl' : ('../../../build/doc/doxygen/pcl.tag', 'http://docs.pointclouds.org/trunk/')}
+doxylink = {'pcl' : ('../../../s/doc/doxygen/pcl.tag', 'https://pointclouds.org/documentation/')}
-sphinx
+sphinx>=3
sphinxcontrib-doxylink
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
- struct MyPointType
+ struct EIGEN_ALIGN16 MyPointType // enforce SSE padding for correct memory alignment
{
PCL_ADD_POINT4D; // preferred way of adding a XYZ+padding
float test;
PCL_MAKE_ALIGNED_OPERATOR_NEW // make sure our new allocators are aligned
- } EIGEN_ALIGN16; // enforce SSE padding for correct memory alignment
+ };
POINT_CLOUD_REGISTER_POINT_STRUCT (MyPointType, // here we assume a XYZ + "test" (as fields)
(float, x, x)
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.imgmath', 'sphinxcontrib.doxylink.doxylink']
+extensions = ['sphinx.ext.imgmath', 'sphinxcontrib.doxylink']
imgmath_dvipng_args = ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent']
# Add any paths that contain templates here, relative to this directory.
raw_enabled = True
# Set up doxylink
-doxylink = {'pcl' : ('../../../build/doc/doxygen/pcl.tag', 'http://docs.pointclouds.org/trunk/')}
+doxylink = {'pcl' : ('../../../s/doc/doxygen/pcl.tag', 'https://pointclouds.org/documentation/')}
The code
--------
-Before you begin, you should download the PCD dataset used in this tutorial from GitHub (`milk.pcd <https://github.com/PointCloudLibrary/pcl/blob/master/test/milk.pcd?raw=true>`_ and
+Before you begin, you should download the PCD dataset used in this tutorial from GitHub (`milk.pcd <https://github.com/PointCloudLibrary/data/blob/master/tutorials/correspondence_grouping/milk.pcd?raw=true>`_ and
`milk_cartoon_all_small_clorox.pcd <https://github.com/PointCloudLibrary/pcl/blob/master/test/milk_cartoon_all_small_clorox.pcd?raw=true>`_) and put the files in a folder of your convenience.
Also, copy and paste the following code into your editor and save it as ``correspondence_grouping.cpp`` (or download the source file :download:`here <./sources/correspondence_grouping/correspondence_grouping.cpp>`).
Or, alternatively, if you prefer specifying the radii in units of cloud resolution::
- $ ./correspondence_grouping milk.pcd milk_cartoon_all_small_clorox.pcd milk.pcd milk_cartoon_all_small_clorox.pcd -r --model_ss 7.5 --scene_ss 20 --rf_rad 10 --descr_rad 15 --cg_size 10
+ $ ./correspondence_grouping milk.pcd milk_cartoon_all_small_clorox.pcd -r --model_ss 7.5 --scene_ss 20 --rf_rad 10 --descr_rad 15 --cg_size 10
Remember to replace ``milk.pcd`` and ``milk_cartoon_all_small_clorox.pcd`` with model and scene filenames, in this exact order. If you want you can add other command line options as described at the beginning of this tutorial.
Instance 1:
Correspondences belonging to this instance: 24
- | 0.969 -0.120 0.217 |
- R = | 0.117 0.993 0.026 |
- | -0.218 -0.000 0.976 |
+ | 0.968 -0.148 0.201 |
+ R = | -0.146 -0.989 -0.023 |
+ | 0.202 -0.007 -0.979 |
- t = < -0.159, 0.212, -0.042 >
+ t = < -0.171, -0.204, 0.043 >
+You may see warnings about invalid reference frames (this can happen if a keypoint does not have enough other points in its neighborhood). If these warnings are only displayed for few points and the results look good otherwise, you can ignore them, else you should try to adapt the parameters.
+
The output window should look like this (depending on the command line options used):
.. image:: images/correspondence_grouping/correspondence_grouping.jpg
The default following values can be tweaked into CMake if you don't have a standard installation, for example:
-.. code-block:: cmake
+.. code-block::
DAVIDSDK_ABI_DIR /opt/davidsdk
* :ref:`compiling_pcl_posix`
======= ======
- |mi_11| Title: **Compiling PCL from source on POSIX compliant systems**
+ |mi_12| Title: **Compiling PCL from source on POSIX compliant systems**
Author: *Victor Lamoine*
In this tutorial, we will explain how to compile PCL from sources on POSIX/Unix systems.
======= ======
- .. |mi_11| image:: images/pcl_logo.png
+ .. |mi_12| image:: images/pcl_logo.png
:height: 120px
* :ref:`building_pcl`
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.h
:language: cpp
- :lines: 41-56
+ :lines: 38-53
These are the public slots triggered by the buttons in the UI.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.h
:language: cpp
- :lines: 58-85
+ :lines: 55-87
These are the protected members of our class;
* ``viewer_`` is the visualizer object
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 4-8
+ :lines: 8-12
We initialize the members of our class to default values (note that theses values should match with the UI buttons ticked)
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 9-24
+ :lines: 13-28
Here we initialize the UI, window title and generate a random point cloud (500 points), note we don't care about the color for now.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 26-31
+ :lines: 30-42
Here we set up the QVTK window.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 33-46
+ :lines: 44-57
At this point we connect SLOTS and their functions to ensure that each UI elements has an use.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 48-52
+ :lines: 59-65
We call the coloring function, add the point cloud and refresh the QVTK viewer.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 60-98
+ :lines: 83-122
This functions deals with opening files, it supports both ``pcd`` and ``ply`` files.
The LUT computing will only work if the point cloud is dense (only finite values) so we remove NaN values from the point cloud if needed.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 100-127
+ :lines: 124-151
| This functions deals with saving the displayed file, it supports both ``pcd`` and ``ply`` files.
| As said before, if the user doesn't append an extension to the file name, ``ply`` will be automatically added.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 129-152
+ :lines: 153-177
This function is called whenever one of the three radio buttons X,Y,Z are clicked, it determines which radio button is clicked and changes
the ``filtering_axis_`` member accordingly.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 154-187
+ :lines: 179-213
This function is called whenever one of the radio buttons in the color list is clicked, the ``color_mode_`` member is modified accordingly.
We also call the coloring function and update the cloud / QVTK widget.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 189-209
+ :lines: 215-235
| This is the core function of the application. We are going to color the cloud following a color scheme.
The point cloud is going to be colored following one direction, we first need to know where it starts and where it ends
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 211-238
+ :lines: 237-264
We then loop through the whole cloud to find the minimum and maximum values.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 239-244
+ :lines: 266-271
Here we compute the scaling, RGB values are coded from 0 to 255 (as integers), we need to scale our distances so that the
minimum distance equals 0 (in RGB scale) and the maximum distance 255 (in RGB scale).
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 246-260
+ :lines: 274-286
We have computed how much we need to scale the distances to fit the RGB scale, we first need to round the ``double`` values to the closest ``integer``
because colors are coded as integers.
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 262-270
+ :lines: 288-296
This is where we apply the color level we have computed to the point cloud R,G,B values.
You can do whatever you want here, the simplest option is to apply the 3 channels (R,G,B) to the ``value`` computed, this means that the
.. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp
:language: cpp
- :lines: 271-305
+ :lines: 297-331
These are examples of coloring schemes, if you are wondering how it works, simply plot the computed values into a spreadsheet software.
.. literalinclude:: sources/qt_visualizer/pclviewer.h
:language: cpp
- :lines: 1-17
+ :lines: 1-14
This file is the header for the class PCLViewer; we include ``QMainWindow`` because this class contains UI elements, we include the PCL headers we will
be using and the VTK header for the ``qvtkWidget``. We also define typedefs of the point types and point clouds, this improves readabily.
.. literalinclude:: sources/qt_visualizer/pclviewer.h
:language: cpp
- :lines: 19-22
+ :lines: 16-19
We declare the namespace ``Ui`` and the class PCLViewer inside it.
.. literalinclude:: sources/qt_visualizer/pclviewer.h
:language: cpp
- :lines: 24-26
+ :lines: 21-23
This is the definition of the PCLViewer class; the macro ``Q_OBJECT`` tells the compiler that this object contains UI elements;
this imply that this file will be processed through `the Meta-Object Compiler (moc) <http://qt-project.org/doc/qt-4.8/moc.html>`_.
.. literalinclude:: sources/qt_visualizer/pclviewer.h
:language: cpp
- :lines: 28-30
+ :lines: 25-27
The constructor and destructor of the PCLViewer class.
.. literalinclude:: sources/qt_visualizer/pclviewer.h
:language: cpp
- :lines: 32-49
+ :lines: 29-46
These are the public slots; these functions will be linked with UI elements actions.
.. literalinclude:: sources/qt_visualizer/pclviewer.h
:language: cpp
- :lines: 51-57
+ :lines: 48-57
| A boost shared pointer to a PCLVisualier and a pointer to a point cloud are defined here.
| The integers ``red``, ``green``, ``blue`` will help us store the value of the sliders.
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 1-14
+ :lines: 1-18
We include the class header and the header for the UI object; note that this file is generated by the moc and it's path depend on
where you call cmake !
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 16-31
+ :lines: 10-35
| ``red`` ``green`` and ``blue`` protected members are initialized to their default values.
| The cloud is filled with random points (in a cube) and accordingly to ``red`` ``green`` and ``blue`` colors.
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 33-37
+ :lines: 37-49
| Here we create a PCL Visualizer name ``viewer`` and we also specify that we don't want an interactor to be created.
| We don't want an interactor to be created because our ``qvtkWidget`` is already an interactor and it's the one we want to use.
| So the next step is to configure our newly created PCL Visualiser interactor to use the ``qvtkWidget``.
-The ``update()`` method of the ``qvtkWidget`` should be called each time you modify the PCL visualizer; if you don't call it you don't know if the
-visualizer will be updated before the user try to pan/spin/zoom.
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 39-51
+ :lines: 51-63
Here we connect slots and signals, this links UI actions to functions. Here is a summary of what we have linked :
* ``pushButton_random``:
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 53-57
+ :lines: 65-69
| This is the last part of our constructor; we add the point cloud to the visualizer, call the method ``pSliderValueChanged`` to change the point size to 2.
-We finally reset the camera within the PCL Visualizer not avoid the user having to zoom out and update the qvtkwidget to be
+We finally reset the camera within the PCL Visualizer not avoid the user having to zoom out and refesh the view to be
sure the modifications will be displayed.
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 59-74
+ :lines: 72-87
| This is the public slot function member called when the push button "Random" is pressed.
| The ``for`` loop iterates through the point cloud and changes point cloud color to a random number (between 0 and 255).
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 76-88
+ :lines: 89-101
| This is the public slot function member called whenever the red, green or blue slider is released
| The ``for`` loop iterates through the point cloud and changes point cloud color to ``red``, ``green`` and ``blue`` member values.
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 97-116
+ :lines: 120-139
| These are the public slot function member called whenever the red, green or blue slider value is changed
| These functions just changes the member value accordingly to the slider value.
.. literalinclude:: sources/qt_visualizer/pclviewer.cpp
:language: cpp
- :lines: 118-121
+ :lines: 141-144
The destructor.
For this tutorial we will use the model from the Queen's Dataset. You can choose any other point cloud, but in order to make the
code work you will need to use the triangulation algorithm in order to obtain polygons. You can find the proposed model here:
- * `points <https://github.com/PointCloudLibrary/data/blob/master/tutorials/min_cut_segmentation_tutorial.pcd>`_ - contains the point cloud
- * `indices - contains indices of the points for which RoPs must be computed
- * `triangles - contains the polygons
+ * `points <https://github.com/PointCloudLibrary/pcl/blob/master/test/rops_cloud.pcd>`_ - contains the point cloud
+ * `indices <https://github.com/PointCloudLibrary/pcl/blob/master/test/rops_indices.txt>`_ - contains indices of the points for which RoPs must be computed
+ * `triangles <https://github.com/PointCloudLibrary/pcl/blob/master/test/rops_triangles.txt>`_ - contains the polygons
Next what you need to do is to create a file ``rops_feature.cpp`` in any editor you prefer and copy the following code inside of it:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Find the QtWidgets library
-find_package(Qt5 REQUIRED Widgets)
+find_package(Qt6 QUIET COMPONENTS Widgets)
+if (NOT Qt6_FOUND)
+ find_package(Qt5 COMPONENTS Widgets REQUIRED)
+ set(QTX Qt5)
+else()
+ set(QTX Qt6)
+endif()
find_package(VTK REQUIRED)
find_package(PCL 1.7.1 REQUIRED)
add_executable(${PROJECT_NAME} ${project_SOURCES})
-target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} Qt5::Widgets)
+target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} ${QTX}::Widgets)
#include "pclviewer.h"
#include "ui_pclviewer.h"
+#if VTK_MAJOR_VERSION > 8
+#include <vtkGenericOpenGLRenderWindow.h>
+#endif
+
PCLViewer::PCLViewer (QWidget *parent) :
QMainWindow (parent),
filtering_axis_ (1), // = y
}
// Set up the QVTK window
- viewer_.reset (new pcl::visualization::PCLVisualizer ("viewer", false));
- viewer_->setBackgroundColor (0.1, 0.1, 0.1);
- ui->qvtkWidget->SetRenderWindow (viewer_->getRenderWindow ());
- viewer_->setupInteractor (ui->qvtkWidget->GetInteractor (), ui->qvtkWidget->GetRenderWindow ());
- ui->qvtkWidget->update ();
+#if VTK_MAJOR_VERSION > 8
+ auto renderer = vtkSmartPointer<vtkRenderer>::New();
+ auto renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
+ renderWindow->AddRenderer(renderer);
+ viewer_.reset(new pcl::visualization::PCLVisualizer(renderer, renderWindow, "viewer", false));
+ ui->qvtkWidget->setRenderWindow(viewer_->getRenderWindow());
+ viewer_->setupInteractor(ui->qvtkWidget->interactor(), ui->qvtkWidget->renderWindow());
+#else
+ viewer_.reset(new pcl::visualization::PCLVisualizer("viewer", false));
+ ui->qvtkWidget->SetRenderWindow(viewer_->getRenderWindow());
+ viewer_->setupInteractor(ui->qvtkWidget->GetInteractor(), ui->qvtkWidget->GetRenderWindow());
+#endif
// Connect "Load" and "Save" buttons and their functions
connect (ui->pushButton_load, SIGNAL(clicked ()), this, SLOT(loadFileButtonPressed ()));
// Color the randomly generated cloud
colorCloudDistances ();
+ viewer_->setBackgroundColor (0.1, 0.1, 0.1);
viewer_->addPointCloud (cloud_, "cloud");
viewer_->resetCamera ();
- ui->qvtkWidget->update ();
+
+ refreshView();
}
PCLViewer::~PCLViewer ()
delete ui;
}
+void
+PCLViewer::refreshView()
+{
+#if VTK_MAJOR_VERSION > 8
+ ui->qvtkWidget->renderWindow()->Render();
+#else
+ ui->qvtkWidget->update();
+#endif
+}
+
void
PCLViewer::loadFileButtonPressed ()
{
colorCloudDistances ();
viewer_->updatePointCloud (cloud_, "cloud");
viewer_->resetCamera ();
- ui->qvtkWidget->update ();
+
+ refreshView();
}
void
colorCloudDistances ();
viewer_->updatePointCloud (cloud_, "cloud");
- ui->qvtkWidget->update ();
+
+ refreshView();
}
void
colorCloudDistances ();
viewer_->updatePointCloud (cloud_, "cloud");
- ui->qvtkWidget->update ();
+
+ refreshView();
}
void
// Boost
#include <boost/math/special_functions/round.hpp>
-// Visualization Toolkit (VTK)
-#include <vtkRenderWindow.h>
-
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
lookUpTableChosen ();
protected:
+ /** @brief Rerender the view */
+ void
+ refreshView();
+
/** @brief The PCL visualizer object */
pcl::visualization::PCLVisualizer::Ptr viewer_;
</layout>
</item>
<item>
- <widget class="QVTKWidget" name="qvtkWidget" native="true">
+ <widget class="PCLQVTKWidget" name="qvtkWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>50</horstretch>
</widget>
<customwidgets>
<customwidget>
- <class>QVTKWidget</class>
- <extends>QWidget</extends>
- <header>QVTKWidget.h</header>
+ <class>PCLQVTKWidget</class>
+ <extends>QOpenGLWidget</extends>
+ <header location="global">pcl/visualization/qvtk_compatibility.h</header>
</customwidget>
</customwidgets>
<tabstops>
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Find the QtWidgets library
-find_package(Qt5 REQUIRED Widgets)
+find_package(Qt6 QUIET COMPONENTS Concurrent OpenGL Widgets)
+if (NOT Qt6_FOUND)
+ find_package(Qt5 COMPONENTS Concurrent OpenGL Widgets REQUIRED)
+ set(QTX Qt5)
+else()
+ set(QTX Qt6)
+endif()
find_package(VTK REQUIRED)
find_package(PCL 1.7.1 REQUIRED)
add_executable(${PROJECT_NAME} ${project_SOURCES})
-target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} Qt5::Widgets)
+target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} ${QTX}::Widgets)
#include "pclviewer.h"
#include "ui_pclviewer.h"
+#if VTK_MAJOR_VERSION > 8
+#include <vtkGenericOpenGLRenderWindow.h>
+#endif
+
PCLViewer::PCLViewer (QWidget *parent) :
QMainWindow (parent),
ui (new Ui::PCLViewer)
// Setup the cloud pointer
cloud.reset (new PointCloudT);
// The number of points in the cloud
- cloud->points.resize (200);
+ cloud->resize (200);
// The default color
red = 128;
point.b = blue;
}
- // Set up the QVTK window
- viewer.reset (new pcl::visualization::PCLVisualizer ("viewer", false));
- ui->qvtkWidget->SetRenderWindow (viewer->getRenderWindow ());
- viewer->setupInteractor (ui->qvtkWidget->GetInteractor (), ui->qvtkWidget->GetRenderWindow ());
- ui->qvtkWidget->update ();
+ // Set up the QVTK window
+#if VTK_MAJOR_VERSION > 8
+ auto renderer = vtkSmartPointer<vtkRenderer>::New();
+ auto renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
+ renderWindow->AddRenderer(renderer);
+ viewer.reset(new pcl::visualization::PCLVisualizer(renderer, renderWindow, "viewer", false));
+ ui->qvtkWidget->setRenderWindow(viewer->getRenderWindow());
+ viewer->setupInteractor(ui->qvtkWidget->interactor(), ui->qvtkWidget->renderWindow());
+#else
+ viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));
+ ui->qvtkWidget->SetRenderWindow(viewer->getRenderWindow());
+ viewer->setupInteractor(ui->qvtkWidget->GetInteractor(), ui->qvtkWidget->GetRenderWindow());
+#endif
// Connect "random" button and the function
connect (ui->pushButton_random, SIGNAL (clicked ()), this, SLOT (randomButtonPressed ()));
viewer->addPointCloud (cloud, "cloud");
pSliderValueChanged (2);
viewer->resetCamera ();
- ui->qvtkWidget->update ();
+
+ refreshView();
}
void
}
viewer->updatePointCloud (cloud, "cloud");
- ui->qvtkWidget->update ();
+ refreshView();
}
void
point.b = blue;
}
viewer->updatePointCloud (cloud, "cloud");
- ui->qvtkWidget->update ();
+ refreshView();
}
void
PCLViewer::pSliderValueChanged (int value)
{
viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, value, "cloud");
- ui->qvtkWidget->update ();
+ refreshView();
+}
+
+void
+PCLViewer::refreshView()
+{
+#if VTK_MAJOR_VERSION > 8
+ ui->qvtkWidget->renderWindow()->Render();
+#else
+ ui->qvtkWidget->update();
+#endif
}
void
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
-// Visualization Toolkit (VTK)
-#include <vtkRenderWindow.h>
-
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
blueSliderValueChanged (int value);
protected:
+ void
+ refreshView();
+
pcl::visualization::PCLVisualizer::Ptr viewer;
PointCloudT::Ptr cloud;
private:
Ui::PCLViewer *ui;
-
};
<string>PCLViewer</string>
</property>
<widget class="QWidget" name="centralwidget">
- <widget class="QVTKWidget" name="qvtkWidget" native="true">
+ <widget class="PCLQVTKWidget" name="qvtkWidget" native="true">
<property name="geometry">
<rect>
<x>300</x>
</widget>
<customwidgets>
<customwidget>
- <class>QVTKWidget</class>
- <extends>QWidget</extends>
- <header>QVTKWidget.h</header>
+ <class>PCLQVTKWidget</class>
+ <extends>QOpenGLWidget</extends>
+ <header location="global">pcl/visualization/qvtk_compatibility.h</header>
</customwidget>
</customwidgets>
<resources/>
.. code-block:: cmake
find_package(PCL 1.3 REQUIRED COMPONENTS common io)
- ...
set (srcs
src/conditional_removal.cpp
# ...
- src/bilateral.cpp)
+ src/bilateral.cpp
)
# Find "set (incs", and add a new entry there, e.g.,
In the case of the search method, we can either do the same, or be clever and
provide a default option for the user. The best default options are:
- * use an organized search method via :pcl:`pcl::OrganizedNeighbor<pcl::OrganizedNeighbor>` if the point cloud is organized;
+ * use an organized search method via :pcl:`pcl::search::OrganizedNeighbor<pcl::search::OrganizedNeighbor>` if the point cloud is organized;
* use a general purpose kdtree via :pcl:`pcl::KdTreeFLANN<pcl::KdTreeFLANN>` if the point cloud is unorganized.
.. code-block:: cpp
/** \brief Estimate a descriptor for a given point.
* \param[in] index the index of the point to estimate a descriptor for
* \param[in] normals a pointer to the set of normals
- * \param[in] rf the reference frame
+ * \param[out] rf the reference frame
* \param[out] desc the resultant estimated descriptor
* \return true if the descriptor was computed successfully, false if there was an error
* (e.g. the nearest neighbor didn't return any neighbors)
Vector3fMapConst origin = (*input_)[(*indices_)[index]].getVector3fMap ();
// Get origin normal
// Use pre-computed normals
+ if (!pcl::isNormalFinite(normals[minIndex]))
+ {
+ std::fill (desc.begin (), desc.end (), std::numeric_limits<float>::quiet_NaN ());
+ std::fill (rf, rf + 9, 0.f);
+ return (false);
+ }
normal = normals[minIndex].getNormalVector3fMap ();
// Compute and store the RF direction
using Filter<PointT>::filter_name_;
using Filter<PointT>::indices_;
using Filter<PointT>::input_;
-
+ using Filter<PointT>::removed_indices_;
+
using PointCloud = typename Filter<PointT>::PointCloud;
using PointCloudPtr = typename PointCloud::Ptr;
using PointCloudConstPtr = typename PointCloud::ConstPtr;
*/
Eigen::Vector3f
getHullCloudRange ();
-
- /** \brief Apply the two-dimensional hull filter.
- * All points are assumed to lie in the same plane as the 2D hull, an
- * axis-aligned 2D coordinate system using the two dimensions specified
- * (PlaneDim1, PlaneDim2) is used for calculations.
- * \param[out] output The set of points that pass the 2D polygon filter.
- */
- template<unsigned PlaneDim1, unsigned PlaneDim2> void
- applyFilter2D (PointCloud &output);
/** \brief Apply the two-dimensional hull filter.
* All points are assumed to lie in the same plane as the 2D hull, an
template<unsigned PlaneDim1, unsigned PlaneDim2> void
applyFilter2D (Indices &indices);
- /** \brief Apply the three-dimensional hull filter.
- * Polygon-ray crossings are used for three rays cast from each point
- * being tested, and a majority vote of the resulting
- * polygon-crossings is used to decide whether the point lies inside
- * or outside the hull.
- * \param[out] output The set of points that pass the 3D polygon hull
- * filter.
- */
- void
- applyFilter3D (PointCloud &output);
-
/** \brief Apply the three-dimensional hull filter.
* Polygon-ray crossings are used for three rays cast from each point
* being tested, and a majority vote of the resulting
}
}
+#define PCL_INSTANTIATE_Convolution(Tin, Tout) \
+ template class PCL_EXPORTS Convolution<Tin, Tout>;
+
} // namespace filters
} // namespace pcl
#include <pcl/filters/crop_hull.h>
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-template<typename PointT> void
+template<typename PointT>
+PCL_DEPRECATED(1, 13, "This is a trivial call to base class method")
+void
pcl::CropHull<PointT>::applyFilter (PointCloud &output)
{
- if (dim_ == 2)
- {
- // in this case we are assuming all the points lie in the same plane as the
- // 2D convex hull, so the choice of projection just changes the
- // conditioning of the problem: choose to squash the XYZ component of the
- // hull-points that has least variation - this will also give reasonable
- // results if the points don't lie exactly in the same plane
- const Eigen::Vector3f range = getHullCloudRange ();
- if (range[0] <= range[1] && range[0] <= range[2])
- applyFilter2D<1,2> (output);
- else if (range[1] <= range[2] && range[1] <= range[0])
- applyFilter2D<2,0> (output);
- else
- applyFilter2D<0,1> (output);
- }
- else
- {
- applyFilter3D (output);
- }
+ FilterIndices<PointT>::applyFilter(output);
}
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> void
pcl::CropHull<PointT>::applyFilter (Indices &indices)
{
+ indices.clear();
+ removed_indices_->clear();
+ indices.reserve(indices_->size());
+ removed_indices_->reserve(indices_->size());
if (dim_ == 2)
{
// in this case we are assuming all the points lie in the same plane as the
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> template<unsigned PlaneDim1, unsigned PlaneDim2> void
-pcl::CropHull<PointT>::applyFilter2D (PointCloud &output)
+pcl::CropHull<PointT>::applyFilter2D (Indices &indices)
{
for (std::size_t index = 0; index < indices_->size (); index++)
{
))
{
if (crop_outside_)
- output.push_back ((*input_)[(*indices_)[index]]);
+ indices.push_back ((*indices_)[index]);
// once a point has tested +ve for being inside one polygon, we can
// stop checking the others:
break;
}
// If we're removing points *inside* the hull, only remove points that
// haven't been found inside any polygons
- if (poly == hull_polygons_.size () && !crop_outside_)
- output.push_back ((*input_)[(*indices_)[index]]);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-template<typename PointT> template<unsigned PlaneDim1, unsigned PlaneDim2> void
-pcl::CropHull<PointT>::applyFilter2D (Indices &indices)
-{
- // see comments in (PointCloud& output) overload
- for (std::size_t index = 0; index < indices_->size (); index++)
- {
- std::size_t poly;
- for (poly = 0; poly < hull_polygons_.size (); poly++)
- {
- if (isPointIn2DPolyWithVertIndices<PlaneDim1,PlaneDim2> (
- (*input_)[(*indices_)[index]], hull_polygons_[poly], *hull_cloud_
- ))
- {
- if (crop_outside_)
- indices.push_back ((*indices_)[index]);
- break;
- }
- }
if (poly == hull_polygons_.size () && !crop_outside_)
indices.push_back ((*indices_)[index]);
+ if (indices.empty() || indices.back() != (*indices_)[index]) {
+ removed_indices_->push_back ((*indices_)[index]);
+ }
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> void
-pcl::CropHull<PointT>::applyFilter3D (PointCloud &output)
+pcl::CropHull<PointT>::applyFilter3D (Indices &indices)
{
// This algorithm could definitely be sped up using kdtree/octree
// information, if that is available!
// 'random' rays are arbitrary - basically anything that is less likely to
// hit the edge between polygons than coordinate-axis aligned rays would
// be.
- std::size_t crossings[3] = {0,0,0};
- Eigen::Vector3f rays[3] =
- {
- Eigen::Vector3f (0.264882f, 0.688399f, 0.675237f),
- Eigen::Vector3f (0.0145419f, 0.732901f, 0.68018f),
- Eigen::Vector3f (0.856514f, 0.508771f, 0.0868081f)
- };
-
- for (std::size_t poly = 0; poly < hull_polygons_.size (); poly++)
- for (std::size_t ray = 0; ray < 3; ray++)
- crossings[ray] += rayTriangleIntersect
- ((*input_)[(*indices_)[index]], rays[ray], hull_polygons_[poly], *hull_cloud_);
-
- if (crop_outside_ && (crossings[0]&1) + (crossings[1]&1) + (crossings[2]&1) > 1)
- output.push_back ((*input_)[(*indices_)[index]]);
- else if (!crop_outside_)
- output.push_back ((*input_)[(*indices_)[index]]);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-template<typename PointT> void
-pcl::CropHull<PointT>::applyFilter3D (Indices &indices)
-{
- // see comments in applyFilter3D (PointCloud& output)
- for (std::size_t index = 0; index < indices_->size (); index++)
- {
std::size_t crossings[3] = {0,0,0};
Eigen::Vector3f rays[3] =
{
indices.push_back ((*indices_)[index]);
else if (!crop_outside_)
indices.push_back ((*indices_)[index]);
+ else
+ removed_indices_->push_back ((*indices_)[index]);
}
}
eigen_val = eigensolver.eigenvalues ().asDiagonal ();
leaf.evecs_ = eigensolver.eigenvectors ();
- if (eigen_val (0, 0) < 0 || eigen_val (1, 1) < 0 || eigen_val (2, 2) <= 0)
+ if (eigen_val (0, 0) < -Eigen::NumTraits<double>::dummy_precision () || eigen_val (1, 1) < -Eigen::NumTraits<double>::dummy_precision () || eigen_val (2, 2) <= 0)
{
+ PCL_WARN ("[VoxelGridCovariance::applyFilter] Invalid eigen value! (%g, %g, %g)\n", eigen_val (0, 0), eigen_val (1, 1), eigen_val (2, 2));
leaf.nr_points = -1;
continue;
}
Eigen::Vector3d rand_point;
Eigen::Vector3d dist_point;
+ cell_cloud.reserve (pnt_per_cell * std::count_if (leaves_.begin (), leaves_.end (),
+ [this] (auto& l) { return (l.second.nr_points >= min_points_per_voxel_); }));
+
// Generate points for each occupied voxel with sufficient points.
for (typename std::map<std::size_t, Leaf>::iterator it = leaves_.begin (); it != leaves_.end (); ++it)
{
using ConstPtr = shared_ptr<const NormalSpaceSampling<PointT, NormalT> >;
/** \brief Empty constructor. */
- NormalSpaceSampling ()
- : sample_ (std::numeric_limits<unsigned int>::max ())
+ NormalSpaceSampling () : NormalSpaceSampling (false) {}
+
+ /** \brief Constructor.
+ * \param[in] extract_removed_indices Set to true if you want to be able to extract the indices of points being removed.
+ */
+ explicit NormalSpaceSampling (bool extract_removed_indices)
+ : FilterIndices<PointT> (extract_removed_indices)
+ , sample_ (std::numeric_limits<unsigned int>::max ())
, seed_ (static_cast<unsigned int> (time (nullptr)))
, binsx_ ()
, binsy_ ()
/** \brief Get whether the data outside the interval (min/max) is to be returned (true) or inside (false).
* \param[out] limit_negative true if data \b outside the interval [min; max] is to be returned, false otherwise
*/
+ PCL_DEPRECATED(1, 16, "use bool getFilterLimitsNegative() instead")
inline void
getFilterLimitsNegative (bool &limit_negative) const
{
inline void
setMinimumPointsNumberPerVoxel (unsigned int min_points_per_voxel) { min_points_per_voxel_ = min_points_per_voxel; }
- /** \brief Return the minimum number of points required for a voxel to be used.
- */
- inline unsigned int
- getMinimumPointsNumberPerVoxel () const { return min_points_per_voxel_; }
+ /** \brief Return the minimum number of points required for a voxel to be used.
+ */
+ inline unsigned int
+ getMinimumPointsNumberPerVoxel () const { return min_points_per_voxel_; }
/** \brief Set to true if leaf layout information needs to be saved for later access.
* \param[in] save_leaf_layout the new value (true/false)
/** \brief Get whether the data outside the interval (min/max) is to be returned (true) or inside (false).
* \param[out] limit_negative true if data \b outside the interval [min; max] is to be returned, false otherwise
*/
+ PCL_DEPRECATED(1, 16, "use bool getFilterLimitsNegative() instead")
inline void
getFilterLimitsNegative (bool &limit_negative) const
{
result.b = static_cast<std::uint8_t>(b);
return (result);
}
+
+#ifndef PCL_NO_PRECOMPILE
+#include <pcl/impl/instantiate.hpp>
+#include <pcl/point_types.h>
+
+PCL_INSTANTIATE_PRODUCT(
+ Convolution, ((pcl::RGB))((pcl::RGB)))
+
+PCL_INSTANTIATE_PRODUCT(
+ Convolution, ((pcl::PointXYZRGB))((pcl::PointXYZRGB)))
+#endif // PCL_NO_PRECOMPILE
+
} // namespace filters
} // namespace pcl
set(LIB_NAME "pcl_${SUBSYS_NAME}")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
+
+add_library(${LIB_NAME} INTERFACE)
+target_include_directories(${LIB_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
+target_link_libraries(${LIB_NAME} INTERFACE Boost::boost pcl_common)
+
PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS} HEADER_ONLY)
# Install include files
#include <pcl/point_cloud.h>
#include <type_traits>
-
#include <vector>
////////////////////////////////////////////////////////////////////////////////
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" ${UTILS_INC})
PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs})
+#Ensures that CUDA is added and the project can compile as it uses cuda calls.
+set_source_files_properties(src/device_memory.cpp PROPERTIES LANGUAGE CUDA)
+
set(EXT_DEPS "")
#set(EXT_DEPS CUDA)
PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS} EXT_DEPS ${EXT_DEPS})
* \param num_bytes number of bytes to upload
* */
bool
- upload(const void* host_ptr,
+ upload(const void* host_ptr_arg,
std::size_t device_begin_byte_offset,
std::size_t num_bytes);
* \param num_bytes number of bytes to download
* */
bool
- download(void* host_ptr,
+ download(void* host_ptr_arg,
std::size_t device_begin_byte_offset,
std::size_t num_bytes) const;
set(SUBSYS_NAME gpu_kinfu)
set(SUBSYS_PATH gpu/kinfu)
set(SUBSYS_DESC "Kinect Fusion implementation")
-set(SUBSYS_DEPS common io gpu_containers geometry search visualization)
-
-set(build FALSE)
-
-# OpenNI found?
-if(NOT WITH_OPENNI)
- set(DEFAULT FALSE)
- set(REASON "OpenNI was not found or was disabled by the user.")
-else()
- set(DEFAULT TRUE)
- set(REASON)
-endif()
+set(SUBSYS_DEPS common io gpu_containers geometry search)
+set(DEFAULT TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
return()
endif()
-REMOVE_VTK_DEFINITIONS()
-FILE(GLOB incs include/pcl/gpu/kinfu/*.h*)
+file(GLOB incs include/pcl/gpu/kinfu/*.h*)
file(GLOB srcs src/*.cpp src/*.h*)
file(GLOB cuda src/cuda/*.cu src/cuda/*.h*)
set(LIB_NAME "pcl_${SUBSYS_NAME}")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src")
-include_directories(SYSTEM ${CUDA_INCLUDE_DIRS})
-
-if(UNIX OR APPLE)
- set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xcompiler;-fPIC;")
-endif()
-
-if(NOT UNIX OR APPLE)
- add_definitions(-DPCLAPI_EXPORTS)
-endif()
-set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "--ftz=true;--prec-div=false;--prec-sqrt=false")
-CUDA_COMPILE(cuda_objs ${cuda})
+PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${cuda})
+target_link_libraries(${LIB_NAME} pcl_cuda pcl_gpu_containers)
-PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${cuda} ${cuda_objs})
-target_link_libraries("${LIB_NAME}" pcl_gpu_containers)
+target_compile_options(${LIB_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--ftz=true;--prec-div=false;--prec-sqrt=false>)
-set(EXT_DEPS "")
-#set(EXT_DEPS CUDA)
PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS} EXT_DEPS ${EXT_DEPS})
# Install include files
PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_PATH}" ${incs})
-if(BUILD_visualization)
- add_subdirectory(test)
+if(BUILD_tools)
add_subdirectory(tools)
endif()
-if(NOT WITH_OPENNI)
+set(SUBSUBSYS_NAME tools)
+set(SUBSUBSYS_DESC "Kinfu tools")
+set(SUBSUBSYS_DEPS gpu_kinfu visualization)
+set(SUBSUBSYS_OPT_DEPS opencv)
+set(EXT_DEPS openni)
+set(DEFAULT TRUE)
+set(REASON "")
+
+PCL_SUBSUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSUBSYS_NAME} ${SUBSUBSYS_DESC} ${DEFAULT} ${REASON})
+PCL_SUBSUBSYS_DEPEND(build ${SUBSUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} OPT_DEPS ${SUBSUBSYS_OPT_DEPS} EXT_DEPS ${EXT_DEPS})
+
+if(NOT build)
return()
endif()
-if(NOT VTK_FOUND)
- set(DEFAULT FALSE)
- set(REASON "VTK was not found.")
-else()
- set(DEFAULT TRUE)
- set(REASON)
- include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
-endif()
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
file(GLOB hdrs "*.h*")
-include_directories(SYSTEM ${VTK_INCLUDE_DIRS} ${OPENNI_INCLUDE_DIRS})
+include_directories(SYSTEM ${OPENNI_INCLUDE_DIRS})
## KINECT FUSION
set(the_target pcl_kinfu_app)
source_group("Source Files" FILES ${srcs})
-PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
-target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu)
+PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
+target_link_libraries(${the_target} pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu)
if(OpenCV_FOUND)
target_link_libraries("${the_target}" ${OpenCV_LIBS})
set(the_target pcl_record_tsdfvolume)
set(srcs record_tsdfvolume.cpp capture.cpp)
-PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs})
-target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu)
+PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs})
+target_link_libraries(${the_target} pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu)
set(SUBSYS_NAME gpu_kinfu_large_scale)
set(SUBSYS_PATH gpu/kinfu_large_scale)
set(SUBSYS_DESC "Kinect Fusion implementation, with volume shifting")
-set(SUBSYS_DEPS common visualization io gpu_containers gpu_utils geometry search octree filters kdtree features surface)
-
-set(build FALSE)
-
-# OpenNI found?
-if(NOT WITH_OPENNI)
- set(DEFAULT FALSE)
- set(REASON "OpenNI was not found or was disabled by the user.")
-else()
- set(DEFAULT TRUE)
- set(REASON)
-endif()
+set(SUBSYS_DEPS common io gpu_containers gpu_utils geometry search octree filters kdtree features surface)
+set(DEFAULT TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
return()
endif()
-REMOVE_VTK_DEFINITIONS()
file(GLOB incs include/pcl/gpu/kinfu_large_scale/*.h*)
file(GLOB impl_incs include/pcl/gpu/kinfu_large_scale/impl/*.h*)
file(GLOB srcs src/*.cpp src/*.h*)
source_group("Source Files" FILES ${srcs})
set(LIB_NAME "pcl_${SUBSYS_NAME}")
-include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src" ${CUDA_INCLUDE_DIRS})
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src")
-if(UNIX OR APPLE)
- set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xcompiler;-fPIC;")
-endif()
+PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs} ${cuda})
-if(NOT UNIX OR APPLE)
- add_definitions(-DPCLAPI_EXPORTS)
-endif()
-
-set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "--ftz=true;--prec-div=false;--prec-sqrt=false")
-CUDA_COMPILE(cuda_objs ${cuda})
+target_link_libraries(${LIB_NAME} pcl_cuda pcl_common pcl_io pcl_gpu_utils pcl_gpu_containers pcl_gpu_octree pcl_octree pcl_filters)
-PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs} ${cuda} ${cuda_objs})
-target_link_libraries("${LIB_NAME}" pcl_common pcl_io pcl_gpu_utils pcl_gpu_containers pcl_gpu_octree pcl_octree pcl_filters)
+target_compile_options(${LIB_NAME} PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--ftz=true;--prec-div=false;--prec-sqrt=false>)
-set(EXT_DEPS "")
-#set(EXT_DEPS CUDA)
PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS} EXT_DEPS ${EXT_DEPS})
# Install include files
PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_PATH}" ${incs})
-add_subdirectory(test)
-add_subdirectory(tools)
+if(BUILD_tools)
+ add_subdirectory(tools)
+endif()
-if((NOT WITH_OPENNI) AND (NOT WITH_OPENNI2))
+set(SUBSUBSYS_NAME tools)
+set(SUBSUBSYS_DESC "Kinfu large scale tools")
+set(SUBSUBSYS_DEPS gpu_kinfu_large_scale visualization)
+set(SUBSUBSYS_OPT_DEPS )
+set(EXT_DEPS openni openni2)
+set(DEFAULT TRUE)
+set(REASON "")
+
+PCL_SUBSUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSUBSYS_NAME} ${SUBSUBSYS_DESC} ${DEFAULT} ${REASON})
+PCL_SUBSUBSYS_DEPEND(build ${SUBSUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} OPT_DEPS ${SUBSUBSYS_OPT_DEPS} EXT_DEPS ${EXT_DEPS})
+
+if(NOT build)
return()
endif()
-if(NOT VTK_FOUND)
- set(DEFAULT FALSE)
- set(REASON "VTK was not found.")
-else()
- set(DEFAULT TRUE)
- set(REASON)
- include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
-endif()
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
file(GLOB hdrs "*.h*")
include_directories(SYSTEM ${VTK_INCLUDE_DIRS})
source_group("Source Files" FILES ${srcs})
-PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
+PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} BUNDLE)
target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu_large_scale pcl_kdtree pcl_features pcl_surface)
## KINECT FUSION
source_group("Source Files" FILES ${srcs})
-PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
+PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu_large_scale pcl_octree)
## STANDALONE MARCHING CUBES
set(the_target pcl_kinfu_largeScale_mesh_output)
set(srcs process_kinfu_large_scale_output.cpp)
-PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
+PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu_large_scale pcl_filters)
## RECORD MAPS_RGB
set(the_target pcl_record_kinect_maps_rgb)
set(srcs record_maps_rgb.cpp)
-PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
+PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE)
target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu_large_scale pcl_filters)
return()
endif()
-REMOVE_VTK_DEFINITIONS()
-
#find NPP
unset(CUDA_npp_LIBRARY CACHE)
find_cuda_helper_libs(nppc)
"${CMAKE_CURRENT_SOURCE_DIR}/src/cuda/nvidia"
)
-include_directories(SYSTEM
- ${VTK_INCLUDE_DIRS}
- ${OpenCV_INCLUDE_DIRS}
- ${CUDA_INCLUDE_DIRS}
-)
+set(LIB_NAME "pcl_${SUBSYS_NAME}")
+
+PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} ${srcs_cuda})
+target_link_libraries(${LIB_NAME} pcl_cuda pcl_common pcl_search pcl_surface pcl_segmentation pcl_features pcl_sample_consensus pcl_gpu_utils pcl_gpu_containers "${CUDA_CUDART_LIBRARY}" ${CUDA_npp_LIBRARY})
if(UNIX OR APPLE)
- set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xcompiler;-fPIC;")
+ target_compile_options(${LIB_NAME} INTERFACE $<$<COMPILE_LANGUAGE:CUDA>:"-Xcompiler=-fPIC">)
endif()
-if(NOT UNIX OR APPLE)
- add_definitions(-DPCLAPI_EXPORTS)
-endif()
-
-CUDA_COMPILE(objs_cuda ${srcs_cuda} ${hdrs})
-
-set(LIB_NAME "pcl_${SUBSYS_NAME}")
-PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} ${srcs_cuda} ${objs_cuda})
-target_link_libraries("${LIB_NAME}" pcl_common pcl_io pcl_search pcl_surface pcl_segmentation pcl_features pcl_sample_consensus pcl_gpu_utils pcl_gpu_containers "${CUDA_CUDART_LIBRARY}" ${CUDA_npp_LIBRARY})
PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS})
# install include files
#include <pcl/console/print.h>
-#include <pcl/filters/voxel_grid.h>
-
-#include <pcl/features/integral_image_normal.h>
-
#include <pcl/common/transforms.h>
#include <pcl/segmentation/organized_multi_plane_segmentation.h>
include_directories(SYSTEM ${VTK_INCLUDE_DIRS})
#PCL_ADD_EXECUTABLE(${the_target} "${SUBSYS_NAME}" people_tracking.cpp)
-#target_link_libraries("${the_target}" pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization)
+#target_link_libraries("${the_target}" pcl_common pcl_kdtree pcl_gpu_people pcl_io pcl_visualization)
if(HAVE_OPENNI)
PCL_ADD_EXECUTABLE(pcl_people_app COMPONENT ${SUBSYS_NAME} SOURCES people_app.cpp)
- target_link_libraries (pcl_people_app pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization ${Boost_LIBRARIES})
+ target_link_libraries (pcl_people_app pcl_common pcl_gpu_people pcl_io pcl_visualization ${Boost_LIBRARIES})
endif()
PCL_ADD_EXECUTABLE(pcl_people_pcd_prob COMPONENT ${SUBSYS_NAME} SOURCES people_pcd_prob.cpp)
-target_link_libraries (pcl_people_pcd_prob pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization ${Boost_LIBRARIES})
+target_link_libraries (pcl_people_pcd_prob pcl_common pcl_kdtree pcl_gpu_people pcl_io pcl_visualization)
#PCL_ADD_EXECUTABLE(people_pcd_folder COMPONENT ${SUBSYS_NAME} SOURCES people_pcd_folder.cpp)
-#target_link_libraries (people_pcd_folder pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization ${Boost_LIBRARIES})
+#target_link_libraries (people_pcd_folder pcl_common pcl_kdtree pcl_gpu_people pcl_io pcl_visualization)
#PCL_ADD_EXECUTABLE(people_pcd_person COMPONENT ${SUBSYS_NAME} SOURCES people_pcd_person.cpp)
-#target_link_libraries (people_pcd_person pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization)
+#target_link_libraries (people_pcd_person pcl_common pcl_kdtree pcl_gpu_people pcl_io pcl_visualization)
#pragma once
-#include <pcl/point_types.h>
-#include <pcl/point_cloud.h>
+#include <pcl/gpu/containers/device_array.h>
+#include <pcl/gpu/octree/octree.hpp>
#include <pcl/PointIndices.h>
#include <pcl/pcl_macros.h>
-#include <pcl/gpu/octree/octree.hpp>
-#include <pcl/gpu/containers/device_array.h>
+#include <pcl/point_cloud.h>
+#include <pcl/point_types.h>
-namespace pcl
-{
- namespace gpu
+namespace pcl {
+namespace gpu {
+template <typename PointT>
+void
+extractEuclideanClusters(const typename pcl::PointCloud<PointT>::Ptr& host_cloud_,
+ const pcl::gpu::Octree::Ptr& tree,
+ float tolerance,
+ std::vector<PointIndices>& clusters,
+ unsigned int min_pts_per_cluster,
+ unsigned int max_pts_per_cluster);
+
+/** \brief @b EuclideanClusterExtraction represents a segmentation class for cluster
+ * extraction in an Euclidean sense, depending on pcl::gpu::octree
+ * \author Koen Buys, Radu Bogdan Rusu
+ * \ingroup segmentation
+ */
+template <typename PointT>
+class EuclideanClusterExtraction {
+public:
+ using PointCloudHost = pcl::PointCloud<PointT>;
+ using PointCloudHostPtr = typename PointCloudHost::Ptr;
+ using PointCloudHostConstPtr = typename PointCloudHost::ConstPtr;
+
+ using PointIndicesPtr = PointIndices::Ptr;
+ using PointIndicesConstPtr = PointIndices::ConstPtr;
+
+ using GPUTree = pcl::gpu::Octree;
+ using GPUTreePtr = pcl::gpu::Octree::Ptr;
+
+ using CloudDevice = pcl::gpu::Octree::PointCloud;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /** \brief Empty constructor. */
+ EuclideanClusterExtraction() = default;
+
+ /** \brief the destructor */
+ /* ~EuclideanClusterExtraction ()
+ {
+ tree_.clear();
+ };
+ */
+ /** \brief Provide a pointer to the search object.
+ * \param tree a pointer to the spatial search object.
+ */
+ inline void
+ setSearchMethod(GPUTreePtr& tree)
+ {
+ tree_ = tree;
+ }
+
+ /** \brief Get a pointer to the search method used.
+ * @todo fix this for a generic search tree
+ */
+ inline GPUTreePtr
+ getSearchMethod()
+ {
+ return (tree_);
+ }
+
+ /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space
+ * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean
+ * space
+ */
+ inline void
+ setClusterTolerance(double tolerance)
+ {
+ cluster_tolerance_ = tolerance;
+ }
+
+ /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space.
+ */
+ inline double
+ getClusterTolerance()
+ {
+ return (cluster_tolerance_);
+ }
+
+ /** \brief Set the minimum number of points that a cluster needs to contain in order
+ * to be considered valid.
+ * \param min_cluster_size the minimum cluster size
+ */
+ inline void
+ setMinClusterSize(int min_cluster_size)
+ {
+ min_pts_per_cluster_ = min_cluster_size;
+ }
+
+ /** \brief Get the minimum number of points that a cluster needs to contain in order
+ * to be considered valid. */
+ inline int
+ getMinClusterSize()
{
- template <typename PointT> void
- extractEuclideanClusters (const typename pcl::PointCloud<PointT>::Ptr &host_cloud_,
- const pcl::gpu::Octree::Ptr &tree,
- float tolerance,
- std::vector<PointIndices> &clusters,
- unsigned int min_pts_per_cluster,
- unsigned int max_pts_per_cluster);
-
- /** \brief @b EuclideanClusterExtraction represents a segmentation class for cluster extraction in an Euclidean sense, depending on pcl::gpu::octree
- * \author Koen Buys, Radu Bogdan Rusu
- * \ingroup segmentation
- */
- template <typename PointT>
- class EuclideanClusterExtraction
- {
- public:
- using PointCloudHost = pcl::PointCloud<PointT>;
- using PointCloudHostPtr = typename PointCloudHost::Ptr;
- using PointCloudHostConstPtr = typename PointCloudHost::ConstPtr;
-
- using PointIndicesPtr = PointIndices::Ptr;
- using PointIndicesConstPtr = PointIndices::ConstPtr;
-
- using GPUTree = pcl::gpu::Octree;
- using GPUTreePtr = pcl::gpu::Octree::Ptr;
-
- using CloudDevice = pcl::gpu::Octree::PointCloud;
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /** \brief Empty constructor. */
- EuclideanClusterExtraction () = default;
-
- /** \brief the destructor */
-/* ~EuclideanClusterExtraction ()
- {
- tree_.clear();
- };
-*/
- /** \brief Provide a pointer to the search object.
- * \param tree a pointer to the spatial search object.
- */
- inline void setSearchMethod (GPUTreePtr &tree) { tree_ = tree; }
-
- /** \brief Get a pointer to the search method used.
- * @todo fix this for a generic search tree
- */
- inline GPUTreePtr getSearchMethod () { return (tree_); }
-
- /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space
- * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean space
- */
- inline void setClusterTolerance (double tolerance) { cluster_tolerance_ = tolerance; }
-
- /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. */
- inline double getClusterTolerance () { return (cluster_tolerance_); }
-
- /** \brief Set the minimum number of points that a cluster needs to contain in order to be considered valid.
- * \param min_cluster_size the minimum cluster size
- */
- inline void setMinClusterSize (int min_cluster_size) { min_pts_per_cluster_ = min_cluster_size; }
-
- /** \brief Get the minimum number of points that a cluster needs to contain in order to be considered valid. */
- inline int getMinClusterSize () { return (min_pts_per_cluster_); }
-
- /** \brief Set the maximum number of points that a cluster needs to contain in order to be considered valid.
- * \param max_cluster_size the maximum cluster size
- */
- inline void setMaxClusterSize (int max_cluster_size) { max_pts_per_cluster_ = max_cluster_size; }
-
- /** \brief Get the maximum number of points that a cluster needs to contain in order to be considered valid. */
- inline int getMaxClusterSize () { return (max_pts_per_cluster_); }
-
- inline void setInput (CloudDevice input) {input_ = input;}
-
- inline void setHostCloud (PointCloudHostPtr host_cloud) {host_cloud_ = host_cloud;}
-
- /** \brief Cluster extraction in a PointCloud given by <setInputCloud (), setIndices ()>
- * \param clusters the resultant point clusters
- */
- void extract (std::vector<pcl::PointIndices> &clusters);
-
- protected:
- /** \brief the input cloud on the GPU */
- CloudDevice input_;
-
- /** \brief the original cloud the Host */
- PointCloudHostPtr host_cloud_;
-
- /** \brief A pointer to the spatial search object. */
- GPUTreePtr tree_;
-
- /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */
- double cluster_tolerance_ {0};
-
- /** \brief The minimum number of points that a cluster needs to contain in order to be considered valid (default = 1). */
- int min_pts_per_cluster_ {1};
-
- /** \brief The maximum number of points that a cluster needs to contain in order to be considered valid (default = MAXINT). */
- int max_pts_per_cluster_ {std::numeric_limits<int>::max()};
-
- /** \brief Class getName method. */
- virtual std::string getClassName () const { return ("gpu::EuclideanClusterExtraction"); }
- };
- /** \brief Sort clusters method (for std::sort).
- * \ingroup segmentation
- */
- inline bool
- comparePointClusters (const pcl::PointIndices &a, const pcl::PointIndices &b)
- {
- return (a.indices.size () < b.indices.size ());
- }
+ return (min_pts_per_cluster_);
}
+
+ /** \brief Set the maximum number of points that a cluster needs to contain in order
+ * to be considered valid.
+ * \param max_cluster_size the maximum cluster size
+ */
+ inline void
+ setMaxClusterSize(int max_cluster_size)
+ {
+ max_pts_per_cluster_ = max_cluster_size;
+ }
+
+ /** \brief Get the maximum number of points that a cluster needs to contain in order
+ * to be considered valid. */
+ inline int
+ getMaxClusterSize()
+ {
+ return (max_pts_per_cluster_);
+ }
+
+ inline void
+ setInput(CloudDevice input)
+ {
+ input_ = input;
+ }
+
+ inline void
+ setHostCloud(PointCloudHostPtr host_cloud)
+ {
+ host_cloud_ = host_cloud;
+ }
+
+ /** \brief extract clusters of a PointCloud given by <setInputCloud(), setIndices()>
+ * \param clusters the resultant point clusters
+ */
+ void
+ extract(std::vector<pcl::PointIndices>& clusters);
+
+protected:
+ /** \brief the input cloud on the GPU */
+ CloudDevice input_;
+
+ /** \brief the original cloud the Host */
+ PointCloudHostPtr host_cloud_;
+
+ /** \brief A pointer to the spatial search object. */
+ GPUTreePtr tree_;
+
+ /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */
+ double cluster_tolerance_{0};
+
+ /** \brief The minimum number of points that a cluster needs to contain in order to be
+ * considered valid (default = 1). */
+ int min_pts_per_cluster_{1};
+
+ /** \brief The maximum number of points that a cluster needs to contain in order to be
+ * considered valid (default = MAXINT). */
+ int max_pts_per_cluster_{std::numeric_limits<int>::max()};
+
+ /** \brief Class getName method. */
+ virtual std::string
+ getClassName() const
+ {
+ return ("gpu::EuclideanClusterExtraction");
+ }
+};
+/** \brief Sort clusters method (for std::sort).
+ * \ingroup segmentation
+ */
+inline bool
+comparePointClusters(const pcl::PointIndices& a, const pcl::PointIndices& b)
+{
+ return (a.indices.size() < b.indices.size());
}
+} // namespace gpu
+} // namespace pcl
#pragma once
-#include <pcl/point_types.h>
-#include <pcl/point_cloud.h>
+#include <pcl/gpu/octree/octree.hpp>
#include <pcl/PointIndices.h>
#include <pcl/pcl_macros.h>
-#include <pcl/gpu/octree/octree.hpp>
+#include <pcl/point_cloud.h>
+#include <pcl/point_types.h>
-namespace pcl
-{
- namespace gpu
+namespace pcl {
+namespace gpu {
+template <typename PointT>
+void
+extractLabeledEuclideanClusters(
+ const typename pcl::PointCloud<PointT>::Ptr& host_cloud_,
+ const pcl::gpu::Octree::Ptr& tree,
+ float tolerance,
+ std::vector<PointIndices>& clusters,
+ unsigned int min_pts_per_cluster,
+ unsigned int max_pts_per_cluster);
+
+/** \brief @b EuclideanLabeledClusterExtraction represents a segmentation class for
+ * cluster extraction in an Euclidean sense, depending on pcl::gpu::octree
+ * \author Koen Buys, Radu Bogdan Rusu
+ * \ingroup segmentation
+ */
+template <typename PointT>
+class EuclideanLabeledClusterExtraction {
+public:
+ using PointType = pcl::PointXYZ;
+ using PointCloudHost = pcl::PointCloud<PointT>;
+ using PointCloudHostPtr = typename PointCloudHost::Ptr;
+ using PointCloudHostConstPtr = typename PointCloudHost::ConstPtr;
+
+ using PointIndicesPtr = PointIndices::Ptr;
+ using PointIndicesConstPtr = PointIndices::ConstPtr;
+
+ using GPUTree = pcl::gpu::Octree;
+ using GPUTreePtr = pcl::gpu::Octree::Ptr;
+
+ using CloudDevice = pcl::gpu::Octree::PointCloud;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /** \brief Empty constructor. */
+ EuclideanLabeledClusterExtraction() = default;
+
+ /** \brief Provide a pointer to the search object.
+ * \param tree a pointer to the spatial search object.
+ */
+ inline void
+ setSearchMethod(const GPUTreePtr& tree)
+ {
+ tree_ = tree;
+ }
+
+ /** \brief Get a pointer to the search method used.
+ * @todo fix this for a generic search tree
+ */
+ inline GPUTreePtr
+ getSearchMethod()
+ {
+ return (tree_);
+ }
+
+ /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space
+ * \param tolerance the spatial cluster tolerance measured by L2 distance
+ */
+ inline void
+ setClusterTolerance(double tolerance)
+ {
+ cluster_tolerance_ = tolerance;
+ }
+
+ /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space.
+ */
+ inline double
+ getClusterTolerance()
+ {
+ return (cluster_tolerance_);
+ }
+
+ /** \brief Set the minimum number of points that a cluster needs to contain in order
+ * to be considered valid.
+ * \param min_cluster_size the minimum cluster size
+ */
+ inline void
+ setMinClusterSize(int min_cluster_size)
+ {
+ min_pts_per_cluster_ = min_cluster_size;
+ }
+
+ /** \brief Get the minimum number of points that a cluster needs to contain in order
+ * to be considered valid. */
+ inline int
+ getMinClusterSize()
{
- template <typename PointT> void
- extractLabeledEuclideanClusters (const typename pcl::PointCloud<PointT>::Ptr &host_cloud_,
- const pcl::gpu::Octree::Ptr &tree,
- float tolerance,
- std::vector<PointIndices> &clusters,
- unsigned int min_pts_per_cluster,
- unsigned int max_pts_per_cluster);
-
- /** \brief @b EuclideanLabeledClusterExtraction represents a segmentation class for cluster extraction in an Euclidean sense, depending on pcl::gpu::octree
- * \author Koen Buys, Radu Bogdan Rusu
- * \ingroup segmentation
- */
- template <typename PointT>
- class EuclideanLabeledClusterExtraction
- {
- public:
- using PointType = pcl::PointXYZ;
- using PointCloudHost = pcl::PointCloud<PointT>;
- using PointCloudHostPtr = typename PointCloudHost::Ptr;
- using PointCloudHostConstPtr = typename PointCloudHost::ConstPtr;
-
- using PointIndicesPtr = PointIndices::Ptr;
- using PointIndicesConstPtr = PointIndices::ConstPtr;
-
- using GPUTree = pcl::gpu::Octree;
- using GPUTreePtr = pcl::gpu::Octree::Ptr;
-
- using CloudDevice = pcl::gpu::Octree::PointCloud;
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /** \brief Empty constructor. */
- EuclideanLabeledClusterExtraction () = default;
-
- /** \brief Provide a pointer to the search object.
- * \param tree a pointer to the spatial search object.
- */
- inline void setSearchMethod (const GPUTreePtr &tree) { tree_ = tree; }
-
- /** \brief Get a pointer to the search method used.
- * @todo fix this for a generic search tree
- */
- inline GPUTreePtr getSearchMethod () { return (tree_); }
-
- /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space
- * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean space
- */
- inline void setClusterTolerance (double tolerance) { cluster_tolerance_ = tolerance; }
-
- /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. */
- inline double getClusterTolerance () { return (cluster_tolerance_); }
-
- /** \brief Set the minimum number of points that a cluster needs to contain in order to be considered valid.
- * \param min_cluster_size the minimum cluster size
- */
- inline void setMinClusterSize (int min_cluster_size) { min_pts_per_cluster_ = min_cluster_size; }
-
- /** \brief Get the minimum number of points that a cluster needs to contain in order to be considered valid. */
- inline int getMinClusterSize () { return (min_pts_per_cluster_); }
-
- /** \brief Set the maximum number of points that a cluster needs to contain in order to be considered valid.
- * \param max_cluster_size the maximum cluster size
- */
- inline void setMaxClusterSize (int max_cluster_size) { max_pts_per_cluster_ = max_cluster_size; }
-
- /** \brief Get the maximum number of points that a cluster needs to contain in order to be considered valid. */
- inline int getMaxClusterSize () { return (max_pts_per_cluster_); }
-
- inline void setInput (CloudDevice input) {input_ = input;}
-
- inline void setHostCloud (PointCloudHostPtr host_cloud) {host_cloud_ = host_cloud;}
-
- /** \brief Cluster extraction in a PointCloud given by <setInputCloud (), setIndices ()>
- * \param clusters the resultant point clusters
- */
- void extract (std::vector<PointIndices> &clusters);
-
- protected:
- /** \brief the input cloud on the GPU */
- CloudDevice input_;
-
- /** \brief the original cloud the Host */
- PointCloudHostPtr host_cloud_;
-
- /** \brief A pointer to the spatial search object. */
- GPUTreePtr tree_;
-
- /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */
- double cluster_tolerance_ {0};
-
- /** \brief The minimum number of points that a cluster needs to contain in order to be considered valid (default = 1). */
- int min_pts_per_cluster_ {1};
-
- /** \brief The maximum number of points that a cluster needs to contain in order to be considered valid (default = MAXINT). */
- int max_pts_per_cluster_ {std::numeric_limits<int>::max()};
-
- /** \brief Class getName method. */
- virtual std::string getClassName () const { return ("gpu::EuclideanLabeledClusterExtraction"); }
- };
- /** \brief Sort clusters method (for std::sort).
- * \ingroup segmentation
- */
- inline bool
- compareLabeledPointClusters (const pcl::PointIndices &a, const pcl::PointIndices &b)
- {
- return (a.indices.size () < b.indices.size ());
- }
+ return (min_pts_per_cluster_);
}
+
+ /** \brief Set the maximum number of points that a cluster needs to contain in order
+ * to be considered valid.
+ * \param max_cluster_size the maximum cluster size
+ */
+ inline void
+ setMaxClusterSize(int max_cluster_size)
+ {
+ max_pts_per_cluster_ = max_cluster_size;
+ }
+
+ /** \brief Get the maximum number of points that a cluster needs to contain in order
+ * to be considered valid. */
+ inline int
+ getMaxClusterSize()
+ {
+ return (max_pts_per_cluster_);
+ }
+
+ inline void
+ setInput(CloudDevice input)
+ {
+ input_ = input;
+ }
+
+ inline void
+ setHostCloud(PointCloudHostPtr host_cloud)
+ {
+ host_cloud_ = host_cloud;
+ }
+
+ /** \brief extract clusters of a PointCloud given by <setInputCloud(), setIndices()>
+ * \param clusters the resultant point clusters
+ */
+ void
+ extract(std::vector<PointIndices>& clusters);
+
+protected:
+ /** \brief the input cloud on the GPU */
+ CloudDevice input_;
+
+ /** \brief the original cloud the Host */
+ PointCloudHostPtr host_cloud_;
+
+ /** \brief A pointer to the spatial search object. */
+ GPUTreePtr tree_;
+
+ /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */
+ double cluster_tolerance_{0};
+
+ /** \brief The minimum number of points that a cluster needs to contain in order to be
+ * considered valid (default = 1). */
+ int min_pts_per_cluster_{1};
+
+ /** \brief The maximum number of points that a cluster needs to contain in order to be
+ * considered valid (default = MAXINT). */
+ int max_pts_per_cluster_{std::numeric_limits<int>::max()};
+
+ /** \brief Class getName method. */
+ virtual std::string
+ getClassName() const
+ {
+ return ("gpu::EuclideanLabeledClusterExtraction");
+ }
+};
+/** \brief Sort clusters method (for std::sort).
+ * \ingroup segmentation
+ */
+inline bool
+compareLabeledPointClusters(const pcl::PointIndices& a, const pcl::PointIndices& b)
+{
+ return (a.indices.size() < b.indices.size());
}
+} // namespace gpu
+} // namespace pcl
#pragma once
-#include <pcl/point_types.h>
-#include <pcl/point_cloud.h>
#include <pcl/PointIndices.h>
#include <pcl/pcl_macros.h>
+#include <pcl/point_cloud.h>
+#include <pcl/point_types.h>
-namespace pcl
-{
- namespace gpu
+namespace pcl {
+namespace gpu {
+void
+seededHueSegmentation(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& host_cloud_,
+ const pcl::gpu::Octree::Ptr& tree,
+ float tolerance,
+ PointIndices& clusters_in,
+ PointIndices& clusters_out,
+ float delta_hue = 0.0);
+
+class SeededHueSegmentation {
+public:
+ using PointType = pcl::PointXYZ;
+ using PointCloudHost = pcl::PointCloud<pcl::PointXYZ>;
+ using PointCloudHostPtr = PointCloudHost::Ptr;
+ using PointCloudHostConstPtr = PointCloudHost::ConstPtr;
+
+ using PointIndicesPtr = PointIndices::Ptr;
+ using PointIndicesConstPtr = PointIndices::ConstPtr;
+
+ using GPUTree = pcl::gpu::Octree;
+ using GPUTreePtr = pcl::gpu::Octree::Ptr;
+
+ using CloudDevice = pcl::gpu::Octree::PointCloud;
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ /** \brief Empty constructor. */
+ SeededHueSegmentation() = default;
+
+ /** \brief Provide a pointer to the search object.
+ * \param tree a pointer to the spatial search object.
+ */
+ inline void
+ setSearchMethod(const GPUTreePtr& tree)
{
- void
- seededHueSegmentation (const pcl::PointCloud<pcl::PointXYZRGB>::Ptr &host_cloud_,
- const pcl::gpu::Octree::Ptr &tree,
- float tolerance,
- PointIndices &clusters_in,
- PointIndices &clusters_out,
- float delta_hue = 0.0);
-
- class SeededHueSegmentation
- {
- public:
- using PointType = pcl::PointXYZ;
- using PointCloudHost = pcl::PointCloud<pcl::PointXYZ>;
- using PointCloudHostPtr = PointCloudHost::Ptr;
- using PointCloudHostConstPtr = PointCloudHost::ConstPtr;
-
- using PointIndicesPtr = PointIndices::Ptr;
- using PointIndicesConstPtr = PointIndices::ConstPtr;
-
- using GPUTree = pcl::gpu::Octree;
- using GPUTreePtr = pcl::gpu::Octree::Ptr;
-
- using CloudDevice = pcl::gpu::Octree::PointCloud;
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /** \brief Empty constructor. */
- SeededHueSegmentation () = default;
-
- /** \brief Provide a pointer to the search object.
- * \param tree a pointer to the spatial search object.
- */
- inline void setSearchMethod (const GPUTreePtr &tree) { tree_ = tree; }
-
- /** \brief Get a pointer to the search method used.
- * @todo fix this for a generic search tree
- */
- inline GPUTreePtr getSearchMethod () { return (tree_); }
-
- /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space
- * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean space
- */
- inline void setClusterTolerance (double tolerance) { cluster_tolerance_ = tolerance; }
-
- /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. */
- inline double getClusterTolerance () { return (cluster_tolerance_); }
-
- inline void setInput (CloudDevice input) {input_ = input;}
-
- inline void setHostCloud (PointCloudHostPtr host_cloud) {host_cloud_ = host_cloud;}
-
- /** \brief Set the tollerance on the hue
- * \param[in] delta_hue the new delta hue
- */
- inline void
- setDeltaHue (float delta_hue) { delta_hue_ = delta_hue; }
-
- /** \brief Get the tolerance on the hue */
- inline float
- getDeltaHue () { return (delta_hue_); }
-
- /** \brief Cluster extraction in a PointCloud given by <setInputCloud (), setIndices ()>
- * \param indices_in
- * \param indices_out
- */
- void segment (PointIndices &indices_in, PointIndices &indices_out);
-
- protected:
- /** \brief the input cloud on the GPU */
- CloudDevice input_;
-
- /** \brief the original cloud the Host */
- PointCloudHostPtr host_cloud_;
-
- /** \brief A pointer to the spatial search object. */
- GPUTreePtr tree_;
-
- /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */
- double cluster_tolerance_ {0};
-
- /** \brief The allowed difference on the hue*/
- float delta_hue_ {0.0};
-
- /** \brief Class getName method. */
- virtual std::string getClassName () const { return ("gpu::SeededHueSegmentation"); }
- };
- /** \brief Sort clusters method (for std::sort).
- * \ingroup segmentation
- */
- inline bool
- comparePointClusters (const pcl::PointIndices &a, const pcl::PointIndices &b)
- {
- return (a.indices.size () < b.indices.size ());
- }
+ tree_ = tree;
}
+
+ /** \brief Get a pointer to the search method used.
+ * @todo fix this for a generic search tree
+ */
+ inline GPUTreePtr
+ getSearchMethod()
+ {
+ return (tree_);
+ }
+
+ /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space
+ * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean
+ * space
+ */
+ inline void
+ setClusterTolerance(double tolerance)
+ {
+ cluster_tolerance_ = tolerance;
+ }
+
+ /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space.
+ */
+ inline double
+ getClusterTolerance()
+ {
+ return (cluster_tolerance_);
+ }
+
+ inline void
+ setInput(CloudDevice input)
+ {
+ input_ = input;
+ }
+
+ inline void
+ setHostCloud(PointCloudHostPtr host_cloud)
+ {
+ host_cloud_ = host_cloud;
+ }
+
+ /** \brief Set the tollerance on the hue
+ * \param[in] delta_hue the new delta hue
+ */
+ inline void
+ setDeltaHue(float delta_hue)
+ {
+ delta_hue_ = delta_hue;
+ }
+
+ /** \brief Get the tolerance on the hue */
+ inline float
+ getDeltaHue()
+ {
+ return (delta_hue_);
+ }
+
+ /** \brief extract clusters of a PointCloud given by <setInputCloud(), setIndices()>
+ * \param indices_in
+ * \param indices_out
+ */
+ void
+ segment(PointIndices& indices_in, PointIndices& indices_out);
+
+protected:
+ /** \brief the input cloud on the GPU */
+ CloudDevice input_;
+
+ /** \brief the original cloud the Host */
+ PointCloudHostPtr host_cloud_;
+
+ /** \brief A pointer to the spatial search object. */
+ GPUTreePtr tree_;
+
+ /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */
+ double cluster_tolerance_{0};
+
+ /** \brief The allowed difference on the hue*/
+ float delta_hue_{0.0};
+
+ /** \brief Class getName method. */
+ virtual std::string
+ getClassName() const
+ {
+ return ("gpu::SeededHueSegmentation");
+ }
+};
+/** \brief Sort clusters method (for std::sort).
+ * \ingroup segmentation
+ */
+inline bool
+comparePointClusters(const pcl::PointIndices& a, const pcl::PointIndices& b)
+{
+ return (a.indices.size() < b.indices.size());
}
+} // namespace gpu
+} // namespace pcl
} // namespace detail
} // namespace pcl
-template <typename PointT> void
-pcl::gpu::extractEuclideanClusters (const typename pcl::PointCloud<PointT>::Ptr &host_cloud_,
- const pcl::gpu::Octree::Ptr &tree,
- float tolerance,
- std::vector<PointIndices> &clusters,
- unsigned int min_pts_per_cluster,
- unsigned int max_pts_per_cluster)
+template <typename PointT>
+void
+pcl::gpu::extractEuclideanClusters(
+ const typename pcl::PointCloud<PointT>::Ptr& host_cloud_,
+ const pcl::gpu::Octree::Ptr& tree,
+ float tolerance,
+ std::vector<PointIndices>& clusters,
+ unsigned int min_pts_per_cluster,
+ unsigned int max_pts_per_cluster)
{
// Create a bool vector of processed point indices, and initialize it to false
// cloud is a DeviceArray<PointType>
PCL_DEBUG("[pcl::gpu::extractEuclideanClusters]\n");
- std::vector<bool> processed (host_cloud_->size (), false);
+ std::vector<bool> processed(host_cloud_->size(), false);
int max_answers;
- if(max_pts_per_cluster > host_cloud_->size())
+ if (max_pts_per_cluster > host_cloud_->size())
max_answers = host_cloud_->size();
else
max_answers = max_pts_per_cluster;
// Host buffer for results
pcl::Indices sizes, data, cpu_tmp;
// Process all points in the cloud
- for (std::size_t i = 0; i < host_cloud_->size (); ++i)
- {
+ for (std::size_t i = 0; i < host_cloud_->size(); ++i) {
// if we already processed this point continue with the next one
if (processed[i])
continue;
pcl::copyPoint((*host_cloud_)[i], p);
// Push the starting point in the vector
- queries_host.push_back (p);
+ queries_host.push_back(p);
// Clear vector
r.indices.clear();
// Push the starting point in
r.indices.push_back(i);
- unsigned int found_points = queries_host.size ();
+ unsigned int found_points = queries_host.size();
unsigned int previous_found_points = 0;
pcl::gpu::NeighborIndices result_device;
// once the area stop growing, stop also iterating.
- do
- {
+ do {
data.clear();
// if the number of queries is not high enough implement search on Host here
- if(queries_host.size () <= 10) ///@todo: adjust this to a variable number settable with method
+ if (queries_host.size() <=
+ 10) ///@todo: adjust this to a variable number settable with method
{
PCL_DEBUG(" CPU: ");
- for(std::size_t p = 0; p < queries_host.size (); p++)
- {
+ for (std::size_t p = 0; p < queries_host.size(); p++) {
// Execute the radiusSearch on the host
cpu_tmp.clear();
tree->radiusSearchHost(queries_host[p], tolerance, cpu_tmp, max_answers);
}
}
// If number of queries is high enough do it here
- else
- {
+ else {
PCL_DEBUG(" GPU: ");
sizes.clear();
// Copy buffer
- queries_device = DeviceArray<PointXYZ>(queries_device_buffer.ptr(),queries_host.size());
+ queries_device =
+ DeviceArray<PointXYZ>(queries_device_buffer.ptr(), queries_host.size());
// Move queries to GPU
queries_device.upload(queries_host);
// Execute search
// Clear queries list
queries_host.clear();
- if(data.size () == 1)
+ if (data.size() == 1)
continue;
// Process the results
- for(auto idx : data)
- {
- if(processed[idx])
+ for (auto idx : data) {
+ if (processed[idx])
continue;
processed[idx] = true;
PointXYZ p;
pcl::copyPoint((*host_cloud_)[idx], p);
- queries_host.push_back (p);
+ queries_host.push_back(p);
found_points++;
r.indices.push_back(idx);
}
- PCL_DEBUG(" data.size: %i, foundpoints: %i, previous: %i", data.size() ,
- found_points, previous_found_points);
- PCL_DEBUG(" new points: %i, next queries size: %i\n", found_points - previous_found_points,
- queries_host.size());
- }
- while (previous_found_points < found_points);
+ PCL_DEBUG(" data.size: %i, foundpoints: %i, previous: %i",
+ data.size(),
+ found_points,
+ previous_found_points);
+ PCL_DEBUG(" new points: %i, next queries size: %i\n",
+ found_points - previous_found_points,
+ queries_host.size());
+ } while (previous_found_points < found_points);
// If this queue is satisfactory, add to the clusters
- if (found_points >= min_pts_per_cluster && found_points <= max_pts_per_cluster)
- {
- std::sort (r.indices.begin (), r.indices.end ());
+ if (found_points >= min_pts_per_cluster && found_points <= max_pts_per_cluster) {
+ std::sort(r.indices.begin(), r.indices.end());
// @todo: check if the following is actually still needed
- //r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()), r.indices.end ());
+ // r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()),
+ // r.indices.end ());
r.header = host_cloud_->header;
- clusters.push_back (r); // We could avoid a copy by working directly in the vector
+ clusters.push_back(r); // We could avoid a copy by working directly in the vector
}
}
}
-template <typename PointT> void
-pcl::gpu::EuclideanClusterExtraction<PointT>::extract (std::vector<pcl::PointIndices> &clusters)
+template <typename PointT>
+void
+pcl::gpu::EuclideanClusterExtraction<PointT>::extract(
+ std::vector<pcl::PointIndices>& clusters)
{
-/*
- // Initialize the GPU search tree
- if (!tree_)
- {
- tree_.reset (new pcl::gpu::Octree());
- ///@todo what do we do if input isn't a PointXYZ cloud?
- tree_.setCloud(input_);
- }
-*/
- if (!tree_->isBuilt())
- {
+ /*
+ // Initialize the GPU search tree
+ if (!tree_)
+ {
+ tree_.reset (new pcl::gpu::Octree());
+ ///@todo what do we do if input isn't a PointXYZ cloud?
+ tree_.setCloud(input_);
+ }
+ */
+ if (!tree_->isBuilt()) {
tree_->build();
}
-/*
- if(tree_->cloud_.size() != host_cloud.size ())
- {
- PCL_ERROR("[pcl::gpu::EuclideanClusterExtraction] size of host cloud and device cloud don't match!\n");
- return;
- }
-*/
+ /*
+ if(tree_->cloud_.size() != host_cloud.size ())
+ {
+ PCL_ERROR("[pcl::gpu::EuclideanClusterExtraction] size of host cloud and device
+ cloud don't match!\n"); return;
+ }
+ */
// Extract the actual clusters
- extractEuclideanClusters<PointT> (host_cloud_, tree_, cluster_tolerance_, clusters, min_pts_per_cluster_, max_pts_per_cluster_);
+ extractEuclideanClusters<PointT>(host_cloud_,
+ tree_,
+ cluster_tolerance_,
+ clusters,
+ min_pts_per_cluster_,
+ max_pts_per_cluster_);
PCL_DEBUG("INFO: end of extractEuclideanClusters\n");
// Sort the clusters based on their size (largest one first)
- //std::sort (clusters.rbegin (), clusters.rend (), comparePointClusters);
+ // std::sort (clusters.rbegin (), clusters.rend (), comparePointClusters);
}
-#define PCL_INSTANTIATE_extractEuclideanClusters(T) template void PCL_EXPORTS pcl::gpu::extractEuclideanClusters<T> (const typename pcl::PointCloud<T>::Ptr &, const pcl::gpu::Octree::Ptr &,float, std::vector<PointIndices> &, unsigned int, unsigned int);
-#define PCL_INSTANTIATE_EuclideanClusterExtraction(T) template class PCL_EXPORTS pcl::gpu::EuclideanClusterExtraction<T>;
+#define PCL_INSTANTIATE_extractEuclideanClusters(T) \
+ template void PCL_EXPORTS pcl::gpu::extractEuclideanClusters<T>( \
+ const typename pcl::PointCloud<T>::Ptr&, \
+ const pcl::gpu::Octree::Ptr&, \
+ float, \
+ std::vector<PointIndices>&, \
+ unsigned int, \
+ unsigned int);
+#define PCL_INSTANTIATE_EuclideanClusterExtraction(T) \
+ template class PCL_EXPORTS pcl::gpu::EuclideanClusterExtraction<T>;
#include <pcl/gpu/segmentation/gpu_extract_labeled_clusters.h>
-template <typename PointT> void
-pcl::gpu::extractLabeledEuclideanClusters (const typename pcl::PointCloud<PointT>::Ptr &host_cloud_,
- const pcl::gpu::Octree::Ptr &tree,
- float tolerance,
- std::vector<PointIndices> &clusters,
- unsigned int min_pts_per_cluster,
- unsigned int max_pts_per_cluster)
+template <typename PointT>
+void
+pcl::gpu::extractLabeledEuclideanClusters(
+ const typename pcl::PointCloud<PointT>::Ptr& host_cloud_,
+ const pcl::gpu::Octree::Ptr& tree,
+ float tolerance,
+ std::vector<PointIndices>& clusters,
+ unsigned int min_pts_per_cluster,
+ unsigned int max_pts_per_cluster)
{
// Create a bool vector of processed point indices, and initialize it to false
// cloud is a DeviceArray<PointType>
- std::vector<bool> processed (host_cloud_->size (), false);
+ std::vector<bool> processed(host_cloud_->size(), false);
int max_answers;
- if(max_pts_per_cluster > host_cloud_->size ())
- max_answers = static_cast<int> (host_cloud_->size ());
+ if (max_pts_per_cluster > host_cloud_->size())
+ max_answers = static_cast<int>(host_cloud_->size());
else
max_answers = max_pts_per_cluster;
pcl::PointIndices r;
// Process all points in the cloud
- for (std::size_t i = 0; i < host_cloud_->size (); ++i)
- {
+ for (std::size_t i = 0; i < host_cloud_->size(); ++i) {
// if we already processed this point continue with the next one
if (processed[i])
continue;
// Buffer in a new PointXYZ type
PointT t = (*host_cloud_)[i];
PointXYZ p;
- p.x = t.x; p.y = t.y; p.z = t.z;
+ p.x = t.x;
+ p.y = t.y;
+ p.z = t.z;
// Push the starting point in the vector
- queries_host.push_back (p);
+ queries_host.push_back(p);
// Clear vector
- r.indices.clear ();
+ r.indices.clear();
// Push the starting point in
- r.indices.push_back (static_cast<int> (i));
+ r.indices.push_back(static_cast<int>(i));
- unsigned int found_points = static_cast<unsigned int> (queries_host.size ());
+ unsigned int found_points = static_cast<unsigned int>(queries_host.size());
unsigned int previous_found_points = 0;
pcl::gpu::NeighborIndices result_device;
// once the area stop growing, stop also iterating.
- while (previous_found_points < found_points)
- {
+ while (previous_found_points < found_points) {
// Move queries to GPU
queries_device.upload(queries_host);
// Execute search
std::vector<int> sizes, data;
// Copy results from GPU to Host
- result_device.sizes.download (sizes);
- result_device.data.download (data);
-
- for(std::size_t qp = 0; qp < sizes.size (); qp++)
- {
- for(int qp_r = 0; qp_r < sizes[qp]; qp_r++)
- {
- if(processed[data[qp_r + qp * max_answers]])
+ result_device.sizes.download(sizes);
+ result_device.data.download(data);
+
+ for (std::size_t qp = 0; qp < sizes.size(); qp++) {
+ for (int qp_r = 0; qp_r < sizes[qp]; qp_r++) {
+ if (processed[data[qp_r + qp * max_answers]])
continue;
// Only add if label matches the original label
- if((*host_cloud_)[i].label == (*host_cloud_)[data[qp_r + qp * max_answers]].label)
- {
+ if ((*host_cloud_)[i].label ==
+ (*host_cloud_)[data[qp_r + qp * max_answers]].label) {
processed[data[qp_r + qp * max_answers]] = true;
PointT t_l = (*host_cloud_)[data[qp_r + qp * max_answers]];
PointXYZ p_l;
- p_l.x = t_l.x; p_l.y = t_l.y; p_l.z = t_l.z;
- queries_host.push_back (p_l);
+ p_l.x = t_l.x;
+ p_l.y = t_l.y;
+ p_l.z = t_l.z;
+ queries_host.push_back(p_l);
found_points++;
r.indices.push_back(data[qp_r + qp * max_answers]);
}
}
}
// If this queue is satisfactory, add to the clusters
- if (found_points >= min_pts_per_cluster && found_points <= max_pts_per_cluster)
- {
- std::sort (r.indices.begin (), r.indices.end ());
+ if (found_points >= min_pts_per_cluster && found_points <= max_pts_per_cluster) {
+ std::sort(r.indices.begin(), r.indices.end());
// @todo: check if the following is actually still needed
- //r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()), r.indices.end ());
+ // r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()),
+ // r.indices.end ());
r.header = host_cloud_->header;
- clusters.push_back (r); // We could avoid a copy by working directly in the vector
+ clusters.push_back(r); // We could avoid a copy by working directly in the vector
}
}
}
-template <typename PointT> void
-pcl::gpu::EuclideanLabeledClusterExtraction<PointT>::extract (std::vector<PointIndices> &clusters)
+template <typename PointT>
+void
+pcl::gpu::EuclideanLabeledClusterExtraction<PointT>::extract(
+ std::vector<PointIndices>& clusters)
{
// Initialize the GPU search tree
- if (!tree_)
- {
- tree_.reset (new pcl::gpu::Octree());
+ if (!tree_) {
+ tree_.reset(new pcl::gpu::Octree());
///@todo what do we do if input isn't a PointXYZ cloud?
tree_->setCloud(input_);
}
- if (!tree_->isBuilt())
- {
+ if (!tree_->isBuilt()) {
tree_->build();
}
-/*
- if(tree_->cloud_.size() != host_cloud.size ())
- {
- PCL_ERROR("[pcl::gpu::EuclideanClusterExtraction] size of host cloud and device cloud don't match!\n");
- return;
- }
-*/
+ /*
+ if(tree_->cloud_.size() != host_cloud.size ())
+ {
+ PCL_ERROR("[pcl::gpu::EuclideanClusterExtraction] size of host cloud and device
+ cloud don't match!\n"); return;
+ }
+ */
// Extract the actual clusters
- extractLabeledEuclideanClusters<PointT> (host_cloud_, tree_, cluster_tolerance_, clusters, min_pts_per_cluster_, max_pts_per_cluster_);
+ extractLabeledEuclideanClusters<PointT>(host_cloud_,
+ tree_,
+ cluster_tolerance_,
+ clusters,
+ min_pts_per_cluster_,
+ max_pts_per_cluster_);
// Sort the clusters based on their size (largest one first)
- std::sort (clusters.rbegin (), clusters.rend (), compareLabeledPointClusters);
+ std::sort(clusters.rbegin(), clusters.rend(), compareLabeledPointClusters);
}
-#define PCL_INSTANTIATE_extractLabeledEuclideanClusters(T) template void PCL_EXPORTS pcl::gpu::extractLabeledEuclideanClusters<T> (const typename pcl::PointCloud<T>::Ptr &, const pcl::gpu::Octree::Ptr &,float, std::vector<PointIndices> &, unsigned int, unsigned int);
-#define PCL_INSTANTIATE_EuclideanLabeledClusterExtraction(T) template class PCL_EXPORTS pcl::gpu::EuclideanLabeledClusterExtraction<T>;
+#define PCL_INSTANTIATE_extractLabeledEuclideanClusters(T) \
+ template void PCL_EXPORTS pcl::gpu::extractLabeledEuclideanClusters<T>( \
+ const typename pcl::PointCloud<T>::Ptr&, \
+ const pcl::gpu::Octree::Ptr&, \
+ float, \
+ std::vector<PointIndices>&, \
+ unsigned int, \
+ unsigned int);
+#define PCL_INSTANTIATE_EuclideanLabeledClusterExtraction(T) \
+ template class PCL_EXPORTS pcl::gpu::EuclideanLabeledClusterExtraction<T>;
//////////////////////////////////////////////////////////////////////////////////////////////
void
-seededHueSegmentation (const pcl::PointCloud<pcl::PointXYZRGB>::Ptr &host_cloud_,
- const pcl::gpu::Octree::Ptr &tree,
- float tolerance,
- PointIndices &indices_in,
- PointIndices &indices_out,
- float delta_hue)
+seededHueSegmentation(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr& host_cloud_,
+ const pcl::gpu::Octree::Ptr& tree,
+ float tolerance,
+ PointIndices& indices_in,
+ PointIndices& indices_out,
+ float delta_hue)
{
// Create a bool vector of processed point indices, and initialize it to false
// cloud is a DeviceArray<PointType>
- std::vector<bool> processed (host_cloud_->size (), false);
+ std::vector<bool> processed(host_cloud_->size(), false);
const auto max_answers = host_cloud_->size();
// Process all points in the indices vector
- for (std::size_t k = 0; k < indices_in.indices.size (); ++k)
- {
+ for (std::size_t k = 0; k < indices_in.indices.size(); ++k) {
int i = indices_in.indices[k];
// if we already processed this point continue with the next one
if (processed[i])
// now we will process this point
processed[i] = true;
- PointXYZRGB p;
+ PointXYZRGB p;
p = (*host_cloud_)[i];
PointXYZHSV h;
PointXYZRGBtoXYZHSV(p, h);
// Create the query queue on the host
pcl::PointCloud<pcl::PointXYZ>::VectorType queries_host;
// Push the starting point in the vector
- queries_host.push_back ((*host_cloud_)[i]);
+ queries_host.push_back((*host_cloud_)[i]);
- unsigned int found_points = queries_host.size ();
+ unsigned int found_points = queries_host.size();
unsigned int previous_found_points = 0;
pcl::gpu::NeighborIndices result_device;
std::vector<int> sizes, data;
// once the area stop growing, stop also iterating.
- while (previous_found_points < found_points)
- {
+ while (previous_found_points < found_points) {
// Move queries to GPU
queries_device.upload(queries_host);
// Execute search
previous_found_points = found_points;
// Clear the Host vectors
- sizes.clear (); data.clear ();
+ sizes.clear();
+ data.clear();
// Copy results from GPU to Host
- result_device.sizes.download (sizes);
- result_device.data.download (data);
-
- for(std::size_t qp = 0; qp < sizes.size (); qp++)
- {
- for(int qp_r = 0; qp_r < sizes[qp]; qp_r++)
- {
- if(processed[data[qp_r + qp * max_answers]])
+ result_device.sizes.download(sizes);
+ result_device.data.download(data);
+
+ for (std::size_t qp = 0; qp < sizes.size(); qp++) {
+ for (int qp_r = 0; qp_r < sizes[qp]; qp_r++) {
+ if (processed[data[qp_r + qp * max_answers]])
continue;
- PointXYZRGB p_l;
+ PointXYZRGB p_l;
p_l = (*host_cloud_)[data[qp_r + qp * max_answers]];
PointXYZHSV h_l;
PointXYZRGBtoXYZHSV(p_l, h_l);
- if (std::abs(h_l.h - h.h) < delta_hue)
- {
+ if (std::abs(h_l.h - h.h) < delta_hue) {
processed[data[qp_r + qp * max_answers]] = true;
- queries_host.push_back ((*host_cloud_)[data[qp_r + qp * max_answers]]);
+ queries_host.push_back((*host_cloud_)[data[qp_r + qp * max_answers]]);
found_points++;
}
}
}
}
- for(std::size_t qp = 0; qp < sizes.size (); qp++)
- {
- for(int qp_r = 0; qp_r < sizes[qp]; qp_r++)
- {
+ for (std::size_t qp = 0; qp < sizes.size(); qp++) {
+ for (int qp_r = 0; qp_r < sizes[qp]; qp_r++) {
indices_out.indices.push_back(data[qp_r + qp * max_answers]);
}
}
// @todo: do we need to sort here and remove double points?
}
-void
-pcl::gpu::SeededHueSegmentation::segment (PointIndices &indices_in, PointIndices &indices_out)
+void
+pcl::gpu::SeededHueSegmentation::segment(PointIndices& indices_in,
+ PointIndices& indices_out)
{
// Initialize the GPU search tree
- if (!tree_)
- {
- tree_.reset (new pcl::gpu::Octree());
+ if (!tree_) {
+ tree_.reset(new pcl::gpu::Octree());
///@todo what do we do if input isn't a PointXYZ cloud?
tree_->setCloud(input_);
}
- if (!tree_->isBuild())
- {
+ if (!tree_->isBuild()) {
tree_->build();
}
-/*
- if(tree_->cloud_.size() != host_cloud.size ())
- {
- PCL_ERROR("[pcl::gpu::SeededHueSegmentation] size of host cloud and device cloud don't match!\n");
- return;
- }
-*/
+ /*
+ if(tree_->cloud_.size() != host_cloud.size ())
+ {
+ PCL_ERROR("[pcl::gpu::SeededHueSegmentation] size of host cloud and device cloud
+ don't match!\n"); return;
+ }
+ */
// Extract the actual clusters
- seededHueSegmentation (host_cloud_, tree_, cluster_tolerance_, indices_in, indices_out, delta_hue_);
+ seededHueSegmentation(
+ host_cloud_, tree_, cluster_tolerance_, indices_in, indices_out, delta_hue_);
}
-#endif //PCL_GPU_SEGMENTATION_IMPL_SEEDED_HUE_SEGMENTATION_H_
+#endif // PCL_GPU_SEGMENTATION_IMPL_SEEDED_HUE_SEGMENTATION_H_
set(SUBSYS_NAME gpu_surface)
set(SUBSYS_PATH gpu/surface)
set(SUBSYS_DESC "Surface algorithms with GPU")
-set(SUBSYS_DEPS common gpu_containers gpu_utils visualization geometry)
+set(SUBSYS_DEPS common gpu_containers gpu_utils geometry)
set(build FALSE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" OFF)
list(APPEND srcs ${utils} ${cuda})
-
-include_directories(SYSTEM ${VTK_INCLUDE_DIRS})
-
set(LIB_NAME "pcl_${SUBSYS_NAME}")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src/cuda")
PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs})
-target_link_libraries("${LIB_NAME}" pcl_gpu_containers pcl_visualization)
+target_link_libraries("${LIB_NAME}" pcl_gpu_containers)
set(EXT_DEPS "")
#set(EXT_DEPS CUDA)
set(SUBSYS_NAME io)
set(SUBSYS_DESC "Point cloud IO library")
set(SUBSYS_DEPS common octree)
+set(SUBSYS_EXT_DEPS boost eigen)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
if(WIN32)
- PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK dssdk rssdk rssdk2 pcap png vtk)
+ PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK dssdk rssdk rssdk2 pcap png vtk EXT_DEPS ${SUBSYS_EXT_DEPS})
else()
- PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK dssdk pcap png vtk libusb)
+ PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK dssdk pcap png vtk libusb EXT_DEPS ${SUBSYS_EXT_DEPS})
endif()
PCL_ADD_DOC("${SUBSYS_NAME}")
src/vtk_lib_io.cpp
src/png_io.cpp
)
- set(VTK_IO_TARGET_LINK_LIBRARIES vtkCommon vtkWidgets vtkIO vtkImaging vtkHybrid vtkGraphics vtkRendering vtkFiltering vtkVolumeRendering)
+
# Indicates that we can rely on VTK to be present
set(VTK_DEFINES -DPCL_BUILT_WITH_VTK)
endif()
endif()
PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/ply" ${PLY_INCLUDES})
target_include_directories(pcl_io_ply PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
+target_link_libraries(pcl_io_ply Boost::boost)
set(srcs
src/debayer.cpp
src/robot_eye_grabber.cpp
src/auto_io.cpp
src/io_exception.cpp
+ src/tim_grabber.cpp
${VTK_IO_SOURCE}
${OPENNI_GRABBER_SOURCES}
${OPENNI2_GRABBER_SOURCES}
"include/pcl/${SUBSYS_NAME}/robot_eye_grabber.h"
"include/pcl/${SUBSYS_NAME}/point_cloud_image_extractors.h"
"include/pcl/${SUBSYS_NAME}/io_exception.h"
+ "include/pcl/${SUBSYS_NAME}/tim_grabber.h"
${VTK_IO_INCLUDES}
${OPENNI_GRABBER_INCLUDES}
${OPENNI2_GRABBER_INCLUDES}
target_include_directories(${LIB_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
-target_link_libraries("${LIB_NAME}" pcl_common pcl_io_ply)
+target_link_libraries("${LIB_NAME}" Boost::boost Boost::filesystem Boost::iostreams pcl_common pcl_io_ply)
+
if(VTK_FOUND)
- if(${VTK_VERSION} VERSION_LESS 9.0)
- link_directories(${VTK_LINK_DIRECTORIES})
- target_link_libraries("${LIB_NAME}" ${VTK_LIBRARIES})
- else()
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
target_link_libraries("${LIB_NAME}"
VTK::IOImage
VTK::IOGeometry
VTK::IOPLY)
+ else()
+ link_directories(${VTK_LINK_DIRECTORIES})
+ target_link_libraries("${LIB_NAME}"
+ vtkIOImage
+ vtkIOGeometry
+ vtkIOMPIImage
+ vtkIOMPIParallel
+ vtkIOPLY
+ )
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 7.0 AND ${VTK_VERSION} VERSION_LESS 8.0)
+ target_link_libraries("${LIB_NAME}" vtkFiltersParallelDIY2)
+ endif()
endif()
endif()
target_link_libraries("${LIB_NAME}" ${PCAP_LIBRARIES})
endif()
-set(EXT_DEPS eigen3)
+set(EXT_DEPS boost eigen3)
if(WITH_OPENNI)
list(APPEND EXT_DEPS libopenni)
std::uint32_t compressedColorSize;
// PNG decoded parameters
- std::size_t png_width = 0;
- std::size_t png_height = 0;
unsigned int png_channels = 1;
// sync to frame header
compressedColor.resize (compressedColorSize);
compressedDataIn_arg.read (reinterpret_cast<char*> (&compressedColor[0]), compressedColorSize * sizeof(std::uint8_t));
+ std::size_t png_width = 0;
+ std::size_t png_height = 0;
+
// decode PNG compressed disparity data
decodePNGToImage (compressedDisparity, disparityData, png_width, png_height, png_channels);
{
int queryPoint[3] = {i, j, 0};
vtkIdType pointId = vtkStructuredData::ComputePointId (dimensions, queryPoint);
- double coordinate[3];
if (structured_grid->IsPointVisible (pointId))
{
+ double coordinate[3];
structured_grid->GetPoint (pointId, coordinate);
pcl::setFieldValue<PointT, float> (cloud (i, j), x_idx, coordinate[0]);
pcl::setFieldValue<PointT, float> (cloud (i, j), y_idx, coordinate[1]);
{
int queryPoint[3] = {i, j, 0};
vtkIdType pointId = vtkStructuredData::ComputePointId (dimensions, queryPoint);
- float normal[3];
if (structured_grid->IsPointVisible (pointId))
{
+ float normal[3];
normals->GetTupleValue (i, normal);
pcl::setFieldValue<PointT, float> (cloud (i, j), normal_x_idx, normal[0]);
pcl::setFieldValue<PointT, float> (cloud (i, j), normal_y_idx, normal[1]);
public:
/** \brief Constructor
* \param[in] file_name_or_serial_number used for either loading bag file or specific device by serial number
+ * \param[in] repeat_playback whether to repeat playback when reading from file
*/
RealSense2Grabber ( const std::string& file_name_or_serial_number = "", const bool repeat_playback = true );
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2020-, Open Perception
+ * Copyright (c) 2020, ysuzuki19
+ *
+ * All rights reserved
+ */
+
+#pragma once
+
+#include <pcl/pcl_exports.h>
+#include <pcl/console/print.h>
+#include <pcl/common/time.h>
+#include <pcl/io/grabber.h>
+#include <pcl/point_types.h>
+#include <pcl/point_cloud.h>
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+#include <vector>
+#include <string>
+#include <thread>
+
+namespace pcl
+{
+
+//// note: Protcol named CoLaA (used by SICK) has some information.
+//// In this Grabber, only the amount_of_data is used, so other information is truncated.
+//// Details of the protocol can be found at the following URL.
+
+//// pp.87~89 (table)
+
+//// https://cdn.sickcn.com/media/docs/7/27/927/technical_information_telegram_listing_ranging_sensors_lms1xx_lms5xx_tim2xx_tim5xx_tim7xx_lms1000_mrs1000_mrs6000_nav310_ld_oem15xx_ld_lrs36xx_lms4000_en_im0045927.pdf
+
+
+//// By this PDF, the header contains the following information in order
+
+/////////////////////////////////////////////////////
+//// command type
+//// command
+//// version number
+//// device number
+//// serial number (2 value)
+//// device status
+//// Telegram counter
+//// Scan counter
+//// Time since start up
+//// Time of transmission
+//// Status of digital inputs (2 value)
+//// Status of digital outputs (2 value)
+//// Reserved
+//// scan frequency
+//// measurement frequency
+//// Amount of encoder
+//// Amount of 16 bit channels
+//// Content
+//// Scale factor according to IEEE754
+//// Scale factor offset according to IEEE754
+//// Start angle
+//// Size of single angular step
+//// Amount of data
+//// distance_1
+//// distance_2
+//// distance_3
+//// ...
+//// distance_n
+/////////////////////////////////////////////////////
+
+
+class PCL_EXPORTS TimGrabber : public Grabber
+{
+ public:
+ using sig_cb_sick_tim_scan_point_cloud_xyz = void (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&);
+
+ TimGrabber ();
+ TimGrabber (const boost::asio::ip::address& ipAddress, const std::uint16_t port);
+ ~TimGrabber () noexcept;
+
+ void
+ start () override;
+
+ void
+ stop () override;
+
+ std::string
+ getName () const override;
+
+ bool
+ isRunning () const override;
+
+ protected:
+ pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_xyz_ptr_;
+ boost::signals2::signal<sig_cb_sick_tim_scan_point_cloud_xyz>* point_cloud_xyz_signal_;
+
+ void
+ publishSignal ();
+
+ //// parse received packet
+ //// used by GTEST
+ void
+ processTimPacket (std::string const& packet);
+
+ //// check size of lookup tables
+ //// rebuild if lookup tables have different size
+ void
+ updateLookupTables ();
+
+ //// convert std::vector (distance) to pcl::PointCloud
+ //// used by GTEST
+ void
+ toPointClouds ();
+
+ private:
+ constexpr static float angle_start_ = - 1.0 * M_PI / 4.0;
+ constexpr static float angle_range_ = 2.0 * M_PI * 3.0 / 4.0;
+
+ //// lookup tables for calculaing 2d-coordinate
+ //// reset lookup tables if amount of received data is different
+ std::vector<float> cos_dynamic_lookup_table_;
+ std::vector<float> sin_dynamic_lookup_table_;
+
+ std::array<char, 4000> received_packet_;
+ std::size_t length_;
+ std::istringstream iss_;
+
+ std::size_t amount_of_data_ = 811;
+ std::vector<float> distances_;
+
+ boost::asio::ip::tcp::endpoint tcp_endpoint_;
+ boost::asio::io_service tim_io_service_;
+ boost::asio::ip::tcp::socket tim_socket_;
+ //// wait time for receiving data (on the order of milliseconds)
+ unsigned int wait_time_milliseconds_ = 0;
+
+ pcl::EventFrequency frequency_;
+ mutable boost::mutex frequency_mutex_;
+
+ std::thread grabber_thread_;
+ bool is_running_ = false;
+
+ void
+ initialize ();
+
+ float
+ getFramesPerSecond () const override;
+
+ void
+ buildLookupTables ();
+
+ //// check received packet is valid
+ bool
+ isValidPacket () const;
+
+ //// receive packet (named CoLaA; SICK sensors Communication Language)
+ void
+ receiveTimPacket ();
+
+ void
+ parsePacketHeader (std::string const& header);
+ void
+ parsePacketBody (std::string const& body);
+
+ void
+ processGrabbing ();
+};
+}
std::string format_string, version;
char space_format_format_string, space_format_string_version;
stringstream >> space_format_format_string >> std::ws >> format_string >> space_format_string_version >> std::ws >> version;
+ if (!stringstream.eof ())
+ {
+ stringstream >> std::ws;
+ warning_callback_ (line_number_, "parse warning: trailing whitespaces in the header");
+ }
if (!stringstream ||
!stringstream.eof () ||
!isspace (space_format_format_string) ||
std::size_t count;
char space_element_name, space_name_count;
stringstream >> space_element_name >> std::ws >> name >> space_name_count >> std::ws >> count;
+ if (!stringstream.eof ())
+ {
+ stringstream >> std::ws;
+ warning_callback_ (line_number_, "parse warning: trailing whitespaces in the header");
+ }
if (!stringstream ||
!stringstream.eof () ||
!isspace (space_element_name) ||
return false;
}
}
- else if ((size_type_string == type_traits<uint32>::name ()) || (size_type_string == type_traits<uint32>::old_name ()))
+ // It is safe to use size_type = uint32 here even if it is actually int32, because the size/number of list entries is never negative,
+ // uint32 and int32 have the same width, and all allowed (non-negative) values have the same binary encoding in int32 and uint32.
+ else if ((size_type_string == type_traits<uint32>::name ()) || (size_type_string == type_traits<uint32>::old_name ()) ||
+ (size_type_string == type_traits< int32>::name ()) || (size_type_string == type_traits< int32>::old_name ()))
{
using size_type = uint32;
if ((scalar_type_string == type_traits<int8>::name ()) || (scalar_type_string == type_traits<int8>::old_name ()))
vertex_offset_before_ += static_cast<int> (sizeof (ContentType));
}
- template <>
- std::tuple<std::function<void (pcl::io::ply::uint8)>, std::function<void (pcl::io::ply::int32)>, std::function<void ()> >
+ template <typename SizeType, typename ContentType>
+ std::tuple<std::function<void (SizeType)>, std::function<void (ContentType)>, std::function<void ()> >
pcl::PLYReader::listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
{
if ((element_name == "range_grid") && (property_name == "vertex_indices" || property_name == "vertex_index"))
{
- return std::tuple<std::function<void (pcl::io::ply::uint8)>, std::function<void (pcl::io::ply::int32)>, std::function<void ()> > (
- [this] (pcl::io::ply::uint8 size) { rangeGridVertexIndicesBeginCallback (size); },
- [this] (pcl::io::ply::int32 vertex_index) { rangeGridVertexIndicesElementCallback (vertex_index); },
+ return std::tuple<std::function<void (SizeType)>, std::function<void (ContentType)>, std::function<void ()> > (
+ [this] (SizeType size) { rangeGridVertexIndicesBeginCallback (size); },
+ [this] (ContentType vertex_index) { rangeGridVertexIndicesElementCallback (vertex_index); },
[this] { rangeGridVertexIndicesEndCallback (); }
);
}
if ((element_name == "face") && (property_name == "vertex_indices" || property_name == "vertex_index") && polygons_)
{
- return std::tuple<std::function<void (pcl::io::ply::uint8)>, std::function<void (pcl::io::ply::int32)>, std::function<void ()> > (
- [this] (pcl::io::ply::uint8 size) { faceVertexIndicesBeginCallback (size); },
- [this] (pcl::io::ply::int32 vertex_index) { faceVertexIndicesElementCallback (vertex_index); },
+ return std::tuple<std::function<void (SizeType)>, std::function<void (ContentType)>, std::function<void ()> > (
+ [this] (SizeType size) { faceVertexIndicesBeginCallback (size); },
+ [this] (ContentType vertex_index) { faceVertexIndicesElementCallback (vertex_index); },
[this] { faceVertexIndicesEndCallback (); }
);
}
- if (element_name == "vertex")
- {
- cloud_->fields.emplace_back();
- pcl::PCLPointField ¤t_field = cloud_->fields.back ();
- current_field.name = property_name;
- current_field.offset = cloud_->point_step;
- current_field.datatype = pcl::traits::asEnum<pcl::io::ply::int32>::value;
- current_field.count = 1u; // value will be updated once first vertex is read
- if (sizeof (pcl::io::ply::int32) + cloud_->point_step < std::numeric_limits<std::uint32_t>::max ())
- cloud_->point_step += static_cast<std::uint32_t> (sizeof (pcl::io::ply::int32));
- else
- cloud_->point_step = static_cast<std::uint32_t> (std::numeric_limits<std::uint32_t>::max ());
- do_resize_ = true;
- return std::tuple<std::function<void (pcl::io::ply::uint8)>, std::function<void (pcl::io::ply::int32)>, std::function<void ()> > (
- std::bind (&pcl::PLYReader::vertexListPropertyBeginCallback<pcl::io::ply::uint8>, this, property_name, std::placeholders::_1),
- [this] (pcl::io::ply::int32 value) { vertexListPropertyContentCallback<pcl::io::ply::int32> (value); },
- [this] { vertexListPropertyEndCallback (); }
- );
- }
- return {};
- }
-
- template <typename SizeType, typename ContentType>
- std::tuple<std::function<void (SizeType)>, std::function<void (ContentType)>, std::function<void ()> >
- pcl::PLYReader::listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
- {
if (element_name == "vertex")
{
cloud_->fields.emplace_back();
[this] { vertexListPropertyEndCallback (); }
);
}
+ PCL_WARN("[pcl::PLYReader::listPropertyDefinitionCallback] no fitting callbacks. element_name=%s, property_name=%s\n", element_name.c_str(), property_name.c_str());
return {};
}
}
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2020-, Open Perception
+ * Copyright (c) 2020, ysuzuki19
+ *
+ * All rights reserved
+ */
+
+#include <pcl/io/tim_grabber.h>
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+pcl::TimGrabber::TimGrabber () :
+ tim_socket_ (tim_io_service_)
+{
+ initialize ();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+pcl::TimGrabber::TimGrabber (const boost::asio::ip::address& ipAddress,
+ const std::uint16_t port) :
+ tcp_endpoint_ (ipAddress, port),
+ tim_socket_ (tim_io_service_)
+{
+ initialize ();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+pcl::TimGrabber::~TimGrabber () noexcept
+{
+ stop ();
+
+ disconnect_all_slots<sig_cb_sick_tim_scan_point_cloud_xyz> ();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::initialize ()
+{
+ buildLookupTables ();
+
+ point_cloud_xyz_signal_ = createSignal<sig_cb_sick_tim_scan_point_cloud_xyz> ();
+
+ point_cloud_xyz_ptr_.reset (new pcl::PointCloud<pcl::PointXYZ>);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+float
+pcl::TimGrabber::getFramesPerSecond () const
+{
+ boost::mutex::scoped_lock lock (frequency_mutex_);
+ return (frequency_.getFrequency ());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::buildLookupTables () {
+ const float angle_step = angle_range_ / static_cast<float> (amount_of_data_);
+ float angle = angle_start_;
+
+ cos_dynamic_lookup_table_.reserve (amount_of_data_);
+ cos_dynamic_lookup_table_.clear ();
+ sin_dynamic_lookup_table_.reserve (amount_of_data_);
+ sin_dynamic_lookup_table_.clear ();
+
+ for (std::size_t i = 0; i < amount_of_data_; i++, angle += angle_step)
+ {
+ cos_dynamic_lookup_table_.push_back (std::cos (angle));
+ sin_dynamic_lookup_table_.push_back (std::sin (angle));
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::updateLookupTables () {
+ //// note: cos, sin are the same size
+ if (cos_dynamic_lookup_table_.size () != amount_of_data_)
+ buildLookupTables ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+bool
+pcl::TimGrabber::isValidPacket () const {
+ return received_packet_.data ()[length_-1] == '\03';
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::receiveTimPacket ()
+{
+ if (!tim_socket_.is_open ())
+ return;
+
+ tim_socket_.send (boost::asio::buffer ("\x02sRN LMDscandata 1\x03\0"));
+
+ std::this_thread::sleep_for (std::chrono::milliseconds (wait_time_milliseconds_));
+
+ length_ = tim_socket_.receive (boost::asio::buffer (received_packet_));
+
+ if (!isValidPacket ()) {
+ //// Countup wait_time
+ //// Because fit wait_time to network latency
+ wait_time_milliseconds_++;
+
+ //// Clear invalid packet in socket
+ while (!isValidPacket ())
+ length_ = tim_socket_.receive (boost::asio::buffer (received_packet_));
+
+ //// If received packet is invalid, recurse
+ receiveTimPacket ();
+ }
+}
+
+void
+pcl::TimGrabber::parsePacketHeader (std::string const& header) {
+ //// note: Please following part, if you want to use other information in the header.
+ //std::size_t pos = header.find (' ');
+ //for (int i=0; i<24; ++i)
+ //pos = header.find (' ', pos+1);
+
+ std::size_t pos = header.rfind (' ');
+ amount_of_data_ = std::stoi (header.substr (pos+1), nullptr, 16);
+}
+
+void
+pcl::TimGrabber::parsePacketBody (std::string const& body) {
+ iss_.clear ();
+ iss_.str (body);
+ iss_.setf (std::ios::hex, std::ios::basefield);
+ int d;
+ for (auto& distance : distances_) {
+ iss_ >> d;
+ distance = d / 1000.0;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::processTimPacket (std::string const& packet)
+{
+ std::size_t header_body_splitter = packet.find (' ');
+ for (int i=0; i<25; ++i)
+ header_body_splitter = packet.find (' ', header_body_splitter + 1);
+
+ //// packet contains header and body.
+ //// header has 26 spaces, the rest is body
+ std::string header (packet.substr (0, header_body_splitter));
+ std::string body (packet.substr (header_body_splitter + 1));
+
+ parsePacketHeader (header);
+
+ distances_.resize (amount_of_data_);
+
+ parsePacketBody (body);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::toPointClouds () {
+ point_cloud_xyz_ptr_->resize (distances_.size ());
+ for (std::size_t i=0; i<distances_.size (); ++i) {
+ point_cloud_xyz_ptr_->points[i].x = distances_[i] * cos_dynamic_lookup_table_[i];
+ point_cloud_xyz_ptr_->points[i].y = distances_[i] * sin_dynamic_lookup_table_[i];
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::publishSignal ()
+{
+ point_cloud_xyz_signal_->operator () (point_cloud_xyz_ptr_);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::start ()
+{
+ if (isRunning ())
+ return;
+
+ is_running_ = true;
+
+ try {
+ boost::asio::ip::tcp::resolver resolver (tim_io_service_);
+ tcp_endpoint_ = *resolver.resolve (tcp_endpoint_);
+ tim_socket_.connect (tcp_endpoint_);
+ }
+ catch (std::exception& e)
+ {
+ PCL_ERROR ("[pcl::TimGrabber::start] Unable to bind to socket! %s\n", e.what ());
+ return;
+ }
+ grabber_thread_ = std::thread (&TimGrabber::processGrabbing, this);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::stop ()
+{
+ if (is_running_) {
+ is_running_ = false;
+ grabber_thread_.join ();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+bool
+pcl::TimGrabber::isRunning () const
+{
+ return is_running_;
+}
+
+std::string
+pcl::TimGrabber::getName () const
+{
+ return (std::string ("Sick Tim Grabber"));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+void
+pcl::TimGrabber::processGrabbing ()
+{
+ while (is_running_)
+ {
+ frequency_mutex_.lock ();
+ frequency_.event ();
+ frequency_mutex_.unlock ();
+
+ receiveTimPacket ();
+ processTimPacket (received_packet_.data ());
+
+ updateLookupTables ();
+ toPointClouds ();
+
+ publishSignal ();
+ }
+}
PCL_ADD_EXECUTABLE(pcl_openni_pcd_recorder COMPONENT ${SUBSYS_NAME} SOURCES openni_pcd_recorder.cpp)
- target_link_libraries(pcl_openni_pcd_recorder pcl_common pcl_io)
+ target_link_libraries(pcl_openni_pcd_recorder pcl_common pcl_io Boost::date_time)
endif()
PCL_ADD_EXECUTABLE(pcl_pcd_convert_NaN_nan COMPONENT ${SUBSYS_NAME} SOURCES pcd_convert_NaN_nan.cpp)
* @brief Comaptibility template function to allow use of various types of indices with
* FLANN
* @details Template is used for all params to not constrain any FLANN side capability
- * @param[in|out] index A index searcher, of type ::flann::Index<Dist> or similar, where
+ * @param[in,out] index A index searcher, of type ::flann::Index<Dist> or similar, where
* Dist is a template for computing distance between 2 points
* @param[in] query A ::flann::Matrix<float> or compatible matrix representation of the
* query point
* @brief Comaptibility template function to allow use of various types of indices with
* FLANN
* @details Template is used for all params to not constrain any FLANN side capability
- * @param[in|out] index A index searcher, of type ::flann::Index<Dist> or similar, where
+ * @param[in,out] index A index searcher, of type ::flann::Index<Dist> or similar, where
* Dist is a template for computing distance between 2 points
* @param[in] query A ::flann::Matrix<float> or compatible matrix representation of the
* query point
* @param[out] indices Neighboring k indices found
* @param[out] dists Computed distance matrix
- * @param[in] radius Threshold for consideration
- * @param[in] params Any parameters to pass to the radius_search call
+ * @param[in] k Number of neighbors to search for
+ * @param[in] params Any parameters to pass to the knn_search call
*/
template <class FlannIndex,
class Query,
normals_ = normals;
}
+//////////////////////////////////////////////////////////////////////////////////////////////
+template<typename PointInT, typename PointOutT, typename NormalT> void
+pcl::ISSKeypoint3D<PointInT, PointOutT, NormalT>::setNumberOfThreads (unsigned int nr_threads)
+{
+ if (nr_threads == 0)
+#ifdef _OPENMP
+ threads_ = omp_get_num_procs();
+#else
+ threads_ = 1;
+#endif
+ else
+ threads_ = nr_threads;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointInT, typename PointOutT, typename NormalT> bool*
pcl::ISSKeypoint3D<PointInT, PointOutT, NormalT>::getBoundaryPoints (PointCloudIn &input, double border_radius, float angle_threshold)
{
name_ = "ISSKeypoint3D";
search_radius_ = salient_radius_;
+ setNumberOfThreads(threads_); // Reset number of threads with the member's initialization value to apply input validation.
}
/** \brief Destructor. */
/** \brief Initialize the scheduler and set the number of threads to use.
* \param[in] nr_threads the number of hardware threads to use (0 sets the value back to automatic)
*/
- inline void
- setNumberOfThreads (unsigned int nr_threads = 0) { threads_ = nr_threads; }
+ void
+ setNumberOfThreads (unsigned int nr_threads = 0);
protected:
// the member function get_Q is for getting one column from the Q Matrix
//
+namespace pcl {
class QMatrix {
public:
swap_index(int i, int j) const = 0;
virtual ~QMatrix() {}
};
+} // namespace pcl
-class Kernel : public QMatrix {
+class Kernel : public pcl::QMatrix {
public:
Kernel(int l, svm_node* const* x, const svm_parameter& param);
void
Solve(int l,
- const QMatrix& Q,
+ const pcl::QMatrix& Q,
const double* p_,
const schar* y_,
double* alpha_,
enum { LOWER_BOUND, UPPER_BOUND, FREE };
char* alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE
double* alpha;
- const QMatrix* Q;
+ const pcl::QMatrix* Q;
const double* QD;
double eps;
double Cp, Cn;
void
Solver::Solve(int l,
- const QMatrix& Q,
+ const pcl::QMatrix& Q,
const double* p_,
const schar* y_,
double* alpha_,
void
Solve(int l,
- const QMatrix& Q,
+ const pcl::QMatrix& Q,
const double* p,
const schar* y,
double* alpha,
/** \brief Constructor.
* \param[in] octree_arg Octree to be iterated. Initially the iterator is set to its
* root node.
- * \param[in] max_depth_arg Depth limitation during traversal
*/
OctreeIteratorBase(OctreeT* octree_arg) : OctreeIteratorBase(octree_arg, 0u) {}
#pragma once
// VTK
+#include <vtkVersion.h>
+#if VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION == 0
+#include <limits> // This must be included before vtkPolyData.h
+#endif
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
// SSE macros
#cmakedefine HAVE_POSIX_MEMALIGN
#cmakedefine HAVE_MM_MALLOC
-#cmakedefine HAVE_SSE4_2_EXTENSIONS
-#cmakedefine HAVE_SSE4_1_EXTENSIONS
-#cmakedefine HAVE_SSSE3_EXTENSIONS
-#cmakedefine HAVE_SSE3_EXTENSIONS
-#cmakedefine HAVE_SSE2_EXTENSIONS
-#cmakedefine HAVE_SSE_EXTENSIONS
#cmakedefine HAVE_PNG
set(LIB_NAME "pcl_${SUBSYS_NAME}")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
+
PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs})
+target_link_libraries(${LIB_NAME} pcl_common pcl_filters pcl_kdtree pcl_sample_consensus pcl_segmentation pcl_visualization)
+
PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS})
# Install include files
PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}" ${incs})
/** \brief Provide a pointer to the input target
* (e.g., the point cloud that we want to align the input source to)
*
- * \param[in] cloud the input point cloud target
+ * \param[in] target the input point cloud target
*/
void
setInputTarget(const PointCloudTargetConstPtr& target) override;
public:
HuberPenalty(float threshold) : threshold_(threshold) {}
- virtual float
- operator()(float e) const
+ float
+ operator()(float e) const override
{
if (e <= threshold_)
return (0.5 * e * e);
update_visualizer_(output, pcl::Indices(), *target_, pcl::Indices());
const double cos_angle =
- 0.5 * transformation_.template block<3, 3>(0, 0).trace() - 1;
+ 0.5 * (transformation_.template block<3, 3>(0, 0).trace() - 1);
const double translation_sqr =
transformation_.template block<3, 1>(0, 3).squaredNorm();
angular_hessian_.row(3).noalias() =
Eigen::Vector4d((sx * cy * cz), (-sx * cy * sz), (sx * sy), 0.0f); // b3
+ // The sign of 'sx * sz' in c2 is incorrect in the thesis, and is fixed here.
angular_hessian_.row(4).noalias() = Eigen::Vector4d(
(-sx * cz - cx * sy * sz), (sx * sz - cx * sy * cz), 0, 0.0f); // c2
angular_hessian_.row(5).noalias() = Eigen::Vector4d(
(cx * cz - sx * sy * sz), (-sx * sy * cz - cx * sz), 0, 0.0f); // c3
angular_hessian_.row(6).noalias() =
- Eigen::Vector4d((-cy * cz), (cy * sz), (sy), 0.0f); // d1
+ Eigen::Vector4d((-cy * cz), (cy * sz), (-sy), 0.0f); // d1
angular_hessian_.row(7).noalias() =
Eigen::Vector4d((-sx * sy * cz), (sx * sy * sz), (sx * cy), 0.0f); // d2
angular_hessian_.row(8).noalias() =
float alpha =
search_method_->alpha_m_[model_reference_index][model_point_index] -
alpha_s;
- unsigned int alpha_discretized = static_cast<unsigned int>(
- std::floor(alpha) +
- std::floor(M_PI / search_method_->getAngleDiscretizationStep()));
+ if (alpha < -M_PI) {
+ alpha += (2 * M_PI);
+ }
+ else if (alpha > M_PI) {
+ alpha -= (2 * M_PI);
+ }
+ unsigned int alpha_discretized = static_cast<unsigned int>(std::floor(
+ (alpha + M_PI) / search_method_->getAngleDiscretizationStep()));
accumulator_array[model_reference_index][alpha_discretized]++;
}
}
rotation_mg);
Eigen::Affine3f max_transform =
transform_sg.inverse() *
- Eigen::AngleAxisf((static_cast<float>(max_votes_j) -
- std::floor(static_cast<float>(M_PI) /
- search_method_->getAngleDiscretizationStep())) *
- search_method_->getAngleDiscretizationStep(),
+ Eigen::AngleAxisf((static_cast<float>(max_votes_j + 0.5) *
+ search_method_->getAngleDiscretizationStep() -
+ M_PI),
Eigen::Vector3f::UnitX()) *
transform_mg;
pp.matrix () = line_pt + k * line_dir;
Eigen::Vector4f dir = p - pp;
+ dir[3] = 0.0f;
dir.normalize ();
// Calculate the projection of the point onto the cylinder
pp.matrix () = line_pt + k * line_dir;
Eigen::Vector4f dir = p - pp;
+ dir[3] = 0.0f;
dir.normalize ();
// Calculate the projection of the point onto the cylinder
{
// Compute the principal directions via PCA
Eigen::Vector4f xyz_centroid;
- Eigen::Matrix3f covariance_matrix = Eigen::Matrix3f::Zero ();
+ Eigen::Matrix3f covariance_matrix;
- computeMeanAndCovarianceMatrix (*cloud, covariance_matrix, xyz_centroid);
+ if (computeMeanAndCovarianceMatrix (*cloud, covariance_matrix, xyz_centroid) == 0) {
+ PCL_ERROR ("[pcl::SampleConsensusModelRegistration::computeSampleDistanceThreshold] No valid points in cloud!\n");
+ return;
+ }
// Check if the covariance matrix is finite or not.
for (int i = 0; i < 3; ++i)
// Compute the principal directions via PCA
Eigen::Vector4f xyz_centroid;
Eigen::Matrix3f covariance_matrix;
- computeMeanAndCovarianceMatrix (*cloud, indices, covariance_matrix, xyz_centroid);
+ if (computeMeanAndCovarianceMatrix (*cloud, indices, covariance_matrix, xyz_centroid) == 0) {
+ PCL_ERROR ("[pcl::SampleConsensusModelRegistration::computeSampleDistanceThreshold] No valid points given by cloud and indices!\n");
+ return;
+ }
// Check if the covariance matrix is finite or not.
for (int i = 0; i < 3; ++i)
}
}
+// There is no cpp file containing template instantiations of FlannSearch
+#include <pcl/search/impl/flann_search.hpp>
+
#define PCL_INSTANTIATE_FlannSearch(T) template class PCL_EXPORTS pcl::search::FlannSearch<T>;
target_link_libraries("${LIB_NAME}" pcl_common pcl_search pcl_kdtree pcl_octree ${ON_NURBS_LIBRARIES})
if(VTK_FOUND)
- if(${VTK_VERSION} VERSION_LESS 9.0)
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
+ target_link_libraries("${LIB_NAME}"
+ VTK::CommonDataModel
+ VTK::CommonExecutionModel
+ VTK::FiltersModeling
+ VTK::FiltersCore)
+ else()
include_directories(SYSTEM ${VTK_INCLUDE_DIRS})
link_directories(${VTK_LIBRARY_DIRS})
- target_link_libraries("${LIB_NAME}" ${VTK_LIBRARIES})
- else()
- target_link_libraries("${LIB_NAME}" VTK::CommonDataModel
- VTK::CommonExecutionModel
- VTK::FiltersModeling
- VTK::FiltersCore)
+ target_link_libraries("${LIB_NAME}"
+ vtkCommonCore
+ vtkCommonDataModel
+ vtkCommonExecutionModel
+ vtkFiltersModeling
+ vtkFiltersCore)
endif()
endif()
if(QHULL_FOUND)
- target_link_libraries("${LIB_NAME}" ${QHULL_LIBRARIES})
+ target_link_libraries("${LIB_NAME}" QHULL::QHULL)
endif()
PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS})
(*vertexCount)[key1].second--;
(*vertexCount)[key2].second++;
}
- else fprintf( stderr , "Bad Edge 1: %d %d\n" , ri1.key , ri2.key );
+ else fprintf( stderr , "Bad Edge 1: %lld %lld\n" , ri1.key , ri2.key );
}
}
{
int r1 = MarchingCubes::HasEdgeRoots( node->nodeData.mcIndex , isoTri[j*3+k] );
int r2 = MarchingCubes::HasEdgeRoots( node->nodeData.mcIndex , isoTri[j*3+((k+1)%3)] );
- fprintf( stderr , "Bad Edge 2: %d %d\t%d %d\n" , ri1.key , ri2.key , r1 , r2 );
+ fprintf( stderr , "Bad Edge 2: %lld %lld\t%d %d\n" , ri1.key , ri2.key , r1 , r2 );
}
}
}
for( int i=0 ; i<int(edges.size()) ; i++ )
{
- if( vertexCount.count( edges[i].first.key )==0 ) printf( "Could not find vertex: %lld\n" , edges[i].first );
+ if( vertexCount.count( edges[i].first.key )==0 ) printf( "Could not find vertex: %lld\n" , edges[i].first.key );
else if( vertexCount[ edges[i].first.key ].second )
{
RootInfo ri;
}
}
- if( vertexCount.count( edges[i].second.key )==0 ) printf( "Could not find vertex: %lld\n" , edges[i].second );
+ if( vertexCount.count( edges[i].second.key )==0 ) printf( "Could not find vertex: %lld\n" , edges[i].second.key );
else if( vertexCount[edges[i].second.key].second )
{
RootInfo ri;
return (d);
}
-Eigen::Vector2f
-pcl::MLSResult::calculatePrincipalCurvatures (const double u, const double v) const
-{
- Eigen::Vector2f k (1e-5, 1e-5);
-
- // Note: this use the Monge Patch to derive the Gaussian curvature and Mean Curvature found here http://mathworld.wolfram.com/MongePatch.html
- // Then:
- // k1 = H + sqrt(H^2 - K)
- // k2 = H - sqrt(H^2 - K)
- if (order > 1 && c_vec.size () >= (order + 1) * (order + 2) / 2 && std::isfinite (c_vec[0]))
- {
- const PolynomialPartialDerivative d = getPolynomialPartialDerivative (u, v);
- const double Z = 1 + d.z_u * d.z_u + d.z_v * d.z_v;
- const double Zlen = std::sqrt (Z);
- const double K = (d.z_uu * d.z_vv - d.z_uv * d.z_uv) / (Z * Z);
- const double H = ((1.0 + d.z_v * d.z_v) * d.z_uu - 2.0 * d.z_u * d.z_v * d.z_uv + (1.0 + d.z_u * d.z_u) * d.z_vv) / (2.0 * Zlen * Zlen * Zlen);
- const double disc2 = H * H - K;
- assert (disc2 >= 0.0);
- const double disc = std::sqrt (disc2);
- k[0] = H + disc;
- k[1] = H - disc;
-
- if (std::abs (k[0]) > std::abs (k[1])) std::swap (k[0], k[1]);
- }
- else
- {
- PCL_ERROR ("No Polynomial fit data, unable to calculate the principal curvatures!\n");
- }
-
- return (k);
-}
-
pcl::MLSResult::MLSProjectionResults
pcl::MLSResult::projectPointOrthogonalToPolynomialSurface (const double u, const double v, const double w) const
{
int last_column = input_->width - triangle_pixel_size_columns_;
int last_row = input_->height - triangle_pixel_size_rows_;
- int i = 0, index_down = 0, index_right = 0, index_down_right = 0, idx = 0;
+ int idx = 0;
int y_big_incr = triangle_pixel_size_rows_ * input_->width,
x_big_incr = y_big_incr + triangle_pixel_size_columns_;
// Reserve enough space
for (int y = 0; y < last_row; y += triangle_pixel_size_rows_)
{
// Initialize a new row
- i = y * input_->width;
- index_right = i + triangle_pixel_size_columns_;
- index_down = i + y_big_incr;
- index_down_right = i + x_big_incr;
+ int i = y * input_->width;
+ int index_right = i + triangle_pixel_size_columns_;
+ int index_down = i + y_big_incr;
+ int index_down_right = i + x_big_incr;
// Go over the columns
for (int x = 0; x < last_column; x += triangle_pixel_size_columns_,
// processing for each face
for (std::size_t i = 0; i < tex_mesh.tex_polygons[m].size (); ++i)
{
- std::size_t idx;
-
// get facet information
for (std::size_t j = 0; j < tex_mesh.tex_polygons[m][i].vertices.size (); ++j)
{
- idx = tex_mesh.tex_polygons[m][i].vertices[j];
+ std::size_t idx = tex_mesh.tex_polygons[m][i].vertices[j];
memcpy (&x, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[0].offset], sizeof(float));
memcpy (&y, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[1].offset], sizeof(float));
memcpy (&z, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[2].offset], sizeof(float));
/** \brief Calculate the principal curvatures using the polynomial surface.
* \param[in] u The u-coordinate of the point in local MLS frame.
* \param[in] v The v-coordinate of the point in local MLS frame.
- * \return The principal curvature [k1, k2] at the provided ub coordinates.
+ * \return The principal curvature [k1, k2] at the provided uv coordinates.
* \note If an error occurs then 1e-5 is returned.
*/
PCL_DEPRECATED(1, 15, "use calculatePrincipalCurvatures() instead")
inline MLSProjectionResults
projectQueryPoint (ProjectionMethod method, int required_neighbors = 0) const;
- /** \brief Smooth a given point and its neighborghood using Moving Least Squares.
+ /** \brief Smooth a given point and its neighborhood using Moving Least Squares.
+ * \param[in] cloud the input cloud, used together with index and nn_indices
* \param[in] index the index of the query point in the input cloud
* \param[in] nn_indices the set of nearest neighbors indices for pt
* \param[in] search_radius the search radius used to find nearest neighbors for pt
# pragma GCC system_header
#endif
+#include <vtkVersion.h>
+#if VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION == 0
+#include <limits> // This must be included before vtkPolyData.h
+#endif
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <pcl/surface/mls.h>
#include <pcl/surface/impl/mls.hpp>
+Eigen::Vector2f
+pcl::MLSResult::calculatePrincipalCurvatures (const double u, const double v) const
+{
+ Eigen::Vector2f k (1e-5, 1e-5);
+
+ // Note: this use the Monge Patch to derive the Gaussian curvature and Mean Curvature found here http://mathworld.wolfram.com/MongePatch.html
+ // Then:
+ // k1 = H + sqrt(H^2 - K)
+ // k2 = H - sqrt(H^2 - K)
+ if (order > 1 && c_vec.size () >= (order + 1) * (order + 2) / 2 && std::isfinite (c_vec[0]))
+ {
+ const PolynomialPartialDerivative d = getPolynomialPartialDerivative (u, v);
+ const double Z = 1 + d.z_u * d.z_u + d.z_v * d.z_v;
+ const double Zlen = std::sqrt (Z);
+ const double K = (d.z_uu * d.z_vv - d.z_uv * d.z_uv) / (Z * Z);
+ const double H = ((1.0 + d.z_v * d.z_v) * d.z_uu - 2.0 * d.z_u * d.z_v * d.z_uv + (1.0 + d.z_u * d.z_u) * d.z_vv) / (2.0 * Zlen * Zlen * Zlen);
+ const double disc2 = H * H - K;
+ assert (disc2 >= 0.0);
+ const double disc = std::sqrt (disc2);
+ k[0] = H + disc;
+ k[1] = H - disc;
+
+ if (std::abs (k[0]) > std::abs (k[1])) std::swap (k[0], k[1]);
+ }
+ else
+ {
+ PCL_ERROR ("No Polynomial fit data, unable to calculate the principal curvatures!\n");
+ }
+
+ return (k);
+}
+
#ifndef PCL_NO_PRECOMPILE
#include <pcl/point_types.h>
#include <pcl/impl/instantiate.hpp>
# Args: name, executable_name
PCL_ADD_TEST(common_test_wrappers test_wrappers FILES test_wrappers.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_test_macros test_macros FILES test_macros.cpp LINK_WITH pcl_gtest pcl_common)
-PCL_ADD_TEST(common_vector_average test_vector_average FILES test_vector_average.cpp LINK_WITH pcl_gtest)
+PCL_ADD_TEST(common_vector_average test_vector_average FILES test_vector_average.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_common test_common FILES test_common.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_pointcloud test_pointcloud FILES test_pointcloud.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_parse test_parse FILES test_parse.cpp LINK_WITH pcl_gtest pcl_common)
//////////////////////////////////////////////
struct pointCloudTest : public testing::Test {
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
protected:
PointCloud<PointXYZ> cloud;
};
EXPECT_EQ (normals->size (), indices.size ());
}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+TEST (PCL, TranslatedNormalEstimation)
+{
+ Eigen::Vector4f plane_parameters;
+ float curvature;
+
+ NormalEstimation<PointXYZ, Normal> n;
+
+ PointCloud<PointXYZ> translatedCloud(cloud);
+ for(size_t i = 0; i < translatedCloud.size(); ++i) {
+ translatedCloud[i].x += 100;
+ translatedCloud[i].y += 100;
+ translatedCloud[i].z += 100;
+ }
+
+ // computePointNormal (indices, Vector)
+ computePointNormal (translatedCloud, indices, plane_parameters, curvature);
+ EXPECT_NEAR (std::abs (plane_parameters[0]), 0.035592, 1e-4);
+ EXPECT_NEAR (std::abs (plane_parameters[1]), 0.369596, 1e-4);
+ EXPECT_NEAR (std::abs (plane_parameters[2]), 0.928511, 1e-4);
+// The points have moved so the location (not orientation is expected to change)
+// EXPECT_NEAR (std::abs (plane_parameters[3]), 0.0622552, 1e-4);
+ EXPECT_NEAR (curvature, 0.0693136, 1e-4);
+
+ float nx, ny, nz;
+ // computePointNormal (indices)
+ n.computePointNormal (translatedCloud, indices, nx, ny, nz, curvature);
+ EXPECT_NEAR (std::abs (nx), 0.035592, 1e-4);
+ EXPECT_NEAR (std::abs (ny), 0.369596, 1e-4);
+ EXPECT_NEAR (std::abs (nz), 0.928511, 1e-4);
+ EXPECT_NEAR (curvature, 0.0693136, 1e-4);
+
+ // computePointNormal (Vector)
+ computePointNormal (translatedCloud, plane_parameters, curvature);
+ EXPECT_NEAR (plane_parameters[0], 0.035592, 1e-4);
+ EXPECT_NEAR (plane_parameters[1], 0.369596, 1e-4);
+ EXPECT_NEAR (plane_parameters[2], 0.928511, 1e-4);
+// The points have moved so the location (not orientation is expected to change)
+// EXPECT_NEAR (plane_parameters[3], -0.0622552, 1e-4);
+ EXPECT_NEAR (curvature, 0.0693136, 1e-4);
+
+ // flipNormalTowardsViewpoint (Vector)
+ flipNormalTowardsViewpoint (translatedCloud.points[0], 0, 0, 0, plane_parameters);
+ EXPECT_NEAR (plane_parameters[0], -0.035592, 1e-4);
+ EXPECT_NEAR (plane_parameters[1], -0.369596, 1e-4);
+ EXPECT_NEAR (plane_parameters[2], -0.928511, 1e-4);
+// The points have moved so the location (not orientation is expected to change)
+// EXPECT_NEAR (plane_parameters[3], 0.0799743, 1e-4);
+
+ // flipNormalTowardsViewpoint
+ flipNormalTowardsViewpoint (translatedCloud.points[0], 0, 0, 0, nx, ny, nz);
+ EXPECT_NEAR (nx, -0.035592, 1e-4);
+ EXPECT_NEAR (ny, -0.369596, 1e-4);
+ EXPECT_NEAR (nz, -0.928511, 1e-4);
+
+ // Object
+ PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
+
+ // set parameters
+ PointCloud<PointXYZ>::Ptr cloudptr = translatedCloud.makeShared ();
+ n.setInputCloud (cloudptr);
+ EXPECT_EQ (n.getInputCloud (), cloudptr);
+ pcl::IndicesPtr indicesptr (new pcl::Indices (indices));
+ n.setIndices (indicesptr);
+ EXPECT_EQ (n.getIndices (), indicesptr);
+ n.setSearchMethod (tree);
+ EXPECT_EQ (n.getSearchMethod (), tree);
+ n.setKSearch (static_cast<int> (indices.size ()));
+
+ // estimate
+ n.compute (*normals);
+ EXPECT_EQ (normals->size (), indices.size ());
+
+ for (const auto &point : normals->points)
+ {
+ EXPECT_NEAR (point.normal[0], -0.035592, 1e-4);
+ EXPECT_NEAR (point.normal[1], -0.369596, 1e-4);
+ EXPECT_NEAR (point.normal[2], -0.928511, 1e-4);
+ EXPECT_NEAR (point.curvature, 0.0693136, 1e-4);
+ }
+
+ PointCloud<PointXYZ>::Ptr surfaceptr = cloudptr;
+ n.setSearchSurface (surfaceptr);
+ EXPECT_EQ (n.getSearchSurface (), surfaceptr);
+
+ // Additional test for searchForNeigbhors
+ surfaceptr.reset (new PointCloud<PointXYZ>);
+ *surfaceptr = *cloudptr;
+ surfaceptr->points.resize (640 * 480);
+ surfaceptr->width = 640;
+ surfaceptr->height = 480;
+ EXPECT_EQ (surfaceptr->size (), surfaceptr->width * surfaceptr->height);
+ n.setSearchSurface (surfaceptr);
+ tree.reset ();
+ n.setSearchMethod (tree);
+
+ // estimate
+ n.compute (*normals);
+ EXPECT_EQ (normals->size (), indices.size ());
+}
+
+TEST (NormalEstimation, FarFromOrigin)
+{ // Test if estimated normals are the same if the cloud is moved far away from the origin
+ pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne1;
+ ne1.setInputCloud(cloud.makeShared());
+ ne1.setKSearch(15);
+ pcl::PointCloud<pcl::Normal> normals1;
+ ne1.compute(normals1);
+
+ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_translated(new pcl::PointCloud<pcl::PointXYZ>(cloud));
+ for(auto& point : (*cloud_translated)) {
+ point.x += 123.0;
+ point.y += -45.0;
+ point.z += 98.0;
+ }
+ pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne2;
+ ne2.setInputCloud(cloud_translated);
+ ne2.setKSearch(15);
+ ne2.setViewPoint(123.0, -45.0, 98.0); // Has to be set so that normals are oriented/flipped the same way
+ pcl::PointCloud<pcl::Normal> normals2;
+ ne2.compute(normals2);
+
+ ASSERT_EQ(normals1.size(), normals2.size());
+ for(std::size_t i=0; i<normals1.size(); ++i) {
+ EXPECT_NEAR(std::abs(normals1[i].getNormalVector3fMap().dot(normals2[i].getNormalVector3fMap())), 1.0, 1e-6);
+ EXPECT_NEAR(normals1[i].normal_x, normals2[i].normal_x, 5e-4);
+ EXPECT_NEAR(normals1[i].normal_y, normals2[i].normal_y, 5e-4);
+ EXPECT_NEAR(normals1[i].normal_z, normals2[i].normal_z, 5e-4);
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// There was an issue where the vectors for the indices and the
// distances of the neighbor search weren't initialized correctly
baseOffsetList_.emplace_back(10, 1, 5);
baseOffsetList_.emplace_back(10, 5, 1);
}
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
protected:
void
crop_hull_filter.setInputCloud(test_data.input_cloud_);
pcl::Indices filtered_indices;
crop_hull_filter.filter(filtered_indices);
+ ASSERT_EQ(test_data.inside_indices_.size(), filtered_indices.size());
+ pcl::test::EXPECT_EQ_VECTORS(test_data.inside_indices_, filtered_indices);
+ }
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// checking that the result is independent of the original state of the output_indices
+TYPED_TEST (PCLCropHullTestFixture, non_empty_output_indices)
+{
+ for (auto & entry : this->data_)
+ {
+ auto & crop_hull_filter = entry.first;
+ for (TestData const & test_data : entry.second)
+ {
+ crop_hull_filter.setInputCloud(test_data.input_cloud_);
+ // the size of indices array does not matter. only that it is not empty
+ pcl::Indices filtered_indices(42);
+ crop_hull_filter.filter(filtered_indices);
+ ASSERT_EQ(test_data.inside_indices_.size(), filtered_indices.size());
pcl::test::EXPECT_EQ_VECTORS(test_data.inside_indices_, filtered_indices);
}
}
}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+TYPED_TEST (PCLCropHullTestFixture, test_keep_organized)
+{
+ for (auto & entry : this->data_)
+ {
+ auto & crop_hull_filter = entry.first;
+ crop_hull_filter.setKeepOrganized(true);
+ crop_hull_filter.setUserFilterValue(-10.);
+ const pcl::PointXYZ defaultPoint(-10., -10., -10.);
+ for (TestData const & test_data : entry.second)
+ {
+ crop_hull_filter.setInputCloud(test_data.input_cloud_);
+ pcl::PointCloud<pcl::PointXYZ> filteredCloud;
+ crop_hull_filter.filter(filteredCloud);
+ ASSERT_EQ (test_data.input_cloud_->size(), filteredCloud.size());
+ for (size_t i = 0; i < test_data.input_cloud_->size(); ++i)
+ {
+ pcl::PointXYZ expectedPoint = test_data.inside_mask_[i] ? test_data.input_cloud_->at(i) : defaultPoint;
+ ASSERT_XYZ_NEAR(expectedPoint, filteredCloud[i], 1e-5);
+ }
+ }
+ }
+}
+
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// this test will pass only for 2d case //
template <class T>
shared_ptr<PointCloud<PointXYZ>> cloud;
PointCloud<PointXYZ> out_cloud, negative_cloud, positive_cloud;
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
};
TEST_P(FunctorFilterRandom, functioning)
cloud.resize(2);
}
PointCloud<PointXYZ> cloud;
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
};
TYPED_TEST_SUITE_P(FunctorFilterFunctionObject);
covariance_sampling.setNumberOfSamples (static_cast<unsigned int> (cloud_turtle_normals->size ()) / 8);
double cond_num_turtle = covariance_sampling.computeConditionNumber ();
- // Conditioning number should be loosely close to the expected number. Adopting 10% of the reference value
- EXPECT_NEAR (cond_num_turtle, 20661.7663, 2e4);
+ // Conditioning number should be loosely close to the expected number
+ EXPECT_NEAR (cond_num_turtle, 102982728.6578, 2e4);
IndicesPtr turtle_indices (new pcl::Indices ());
covariance_sampling.filter (*turtle_indices);
covariance_sampling.setIndices (turtle_indices);
double cond_num_turtle_sampled = covariance_sampling.computeConditionNumber ();
- // Conditioning number should be loosely close to the expected number. Adopting 10% of the reference value
- EXPECT_NEAR (cond_num_turtle_sampled, 5795.5057, 5e3);
+ // Conditioning number should be loosely close to the expected number
+ EXPECT_NEAR (cond_num_turtle_sampled, 15697094.2996, 5e3);
// Ensure it respects the requested sampling size
EXPECT_EQ (static_cast<unsigned int> (cloud_turtle_normals->size ()) / 8, turtle_indices->size ());
PCL_ADD_TEST(geometry_iterator test_iterator
FILES test_iterator.cpp
- LINK_WITH pcl_gtest pcl_common)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_mesh_circulators test_mesh_circulators
FILES test_mesh_circulators.cpp
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_mesh_conversion test_mesh_conversion
FILES test_mesh_conversion.cpp
- LINK_WITH pcl_gtest pcl_common)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_mesh_data test_mesh_data
FILES test_mesh_data.cpp
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_mesh_get_boundary test_mesh_get_boundary
FILES test_mesh_get_boundary.cpp
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_mesh_indices test_mesh_indices
FILES test_mesh_indices.cpp
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
add_definitions(-DPCL_TEST_GEOMETRY_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}")
PCL_ADD_TEST(geometry_mesh_io test_mesh_io
FILES test_mesh_io.cpp
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_mesh test_mesh
FILES test_mesh.cpp test_mesh_common_functions.h
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_polygon_mesh test_polygon_mesh
FILES test_polygon_mesh.cpp
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_quad_mesh test_quad_mesh
FILES test_quad_mesh.cpp
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
PCL_ADD_TEST(geometry_triangle_mesh test_triangle_mesh
FILES test_triangle_mesh.cpp
- LINK_WITH pcl_gtest)
+ LINK_WITH pcl_gtest pcl_geometry)
FILES test_octree_compression.cpp
LINK_WITH pcl_gtest pcl_common pcl_io pcl_octree
ARGUMENTS "${PCL_SOURCE_DIR}/test/milk_color.pcd")
+
+PCL_ADD_TEST (io_tim_grabber test_tim_grabber
+ FILES test_tim_grabber.cpp
+ LINK_WITH pcl_gtest pcl_io
+ ARGUMENTS "${PCL_SOURCE_DIR}/test/io/tim_sequences")
* POSSIBILITY OF SUCH DAMAGE.
*
*/
+#include <pcl/common/io.h>
#include <pcl/io/ply_io.h>
#include <pcl/conversions.h>
#include <pcl/PolygonMesh.h>
ASSERT_FALSE (cloud.empty());
}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+TEST_F (PLYTest, EmptyCloud)
+{
+ // create file
+ std::ofstream fs;
+ fs.open (mesh_file_ply_.c_str ());
+ fs << "ply\n"
+ "format ascii 1.0\n"
+ "element vertex 0\n"
+ "property float x\n"
+ "property float y\n"
+ "property float z\n"
+ "end_header\n";
+ fs.close ();
+
+ // Set up cloud
+ pcl::PointCloud<pcl::PointXYZ> cloud;
+
+ // check if loading is ok
+ const int res = pcl::io::loadPLYFile (PLYTest::mesh_file_ply_, cloud);
+ ASSERT_EQ (res, 0);
+
+ ASSERT_TRUE (cloud.empty());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+TEST_F (PLYTest, Float64Cloud)
+{
+ pcl::PointCloud<pcl::PointXYZ> cloud;
+ cloud.push_back(pcl::PointXYZ(4.23, 0.42, 1.61));
+ cloud.push_back(pcl::PointXYZ(-1.61, 4.32, 3.13));
+
+ // create file
+ std::ofstream fs;
+ fs.open (mesh_file_ply_.c_str ());
+ fs << "ply\n"
+ "format ascii 1.0\n"
+ "element vertex 2\n"
+ "property float64 x\n"
+ "property float64 y\n"
+ "property float64 z\n"
+ "end_header\n"
+ << cloud[0].x << " " << cloud[0].y << " " << cloud[0].z << "\n"
+ << cloud[1].x << " " << cloud[1].y << " " << cloud[1].z << "\n"
+ ;
+ fs.close ();
+
+ pcl::PCLPointCloud2 cloud2;
+ const int res = pcl::io::loadPLYFile (PLYTest::mesh_file_ply_, cloud2);
+ ASSERT_EQ (res, 0);
+
+ ASSERT_EQ (cloud2.height*cloud2.width, cloud.size());
+ for (auto & field : cloud2.fields) {
+ ASSERT_EQ (field.datatype, pcl::PCLPointField::FLOAT64);
+ }
+ for (size_t pointIdx = 0; pointIdx < cloud.size(); ++pointIdx)
+ {
+ unsigned char const * ptr = &cloud2.data[0] + pointIdx*cloud2.point_step;
+ double xValue, yValue, zValue;
+ memcpy(
+ reinterpret_cast<char*>(&xValue),
+ ptr + cloud2.fields.at(getFieldIndex(cloud2, "x")).offset,
+ 8);
+ memcpy(
+ reinterpret_cast<char*>(&yValue),
+ ptr + cloud2.fields.at(getFieldIndex(cloud2, "y")).offset,
+ 8);
+ memcpy(
+ reinterpret_cast<char*>(&zValue),
+ ptr + cloud2.fields.at(getFieldIndex(cloud2, "z")).offset,
+ 8);
+
+ EXPECT_FLOAT_EQ(cloud[pointIdx].x, xValue);
+ EXPECT_FLOAT_EQ(cloud[pointIdx].y, yValue);
+ EXPECT_FLOAT_EQ(cloud[pointIdx].z, zValue);
+ }
+}
+
/* ---[ */
int
main (int argc, char** argv)
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2020-, Open Perception
+ * Copyright (c) 2020, ysuzuki19
+ *
+ * All rights reserved
+ */
+
+#include <pcl/test/gtest.h>
+#include <pcl/point_types.h>
+#include <pcl/io/pcd_io.h>
+#include <pcl/io/tim_grabber.h>
+
+#include <string>
+#include <random>
+
+using PointT = pcl::PointXYZ;
+using CloudT = pcl::PointCloud<PointT>;
+
+struct TestableTimGrabber : public pcl::TimGrabber {
+ using TimGrabber::TimGrabber;
+ using TimGrabber::point_cloud_xyz_ptr_;
+ using TimGrabber::processTimPacket;
+ using TimGrabber::updateLookupTables;
+ using TimGrabber::toPointClouds;
+};
+
+class TimGrabberTest : public ::testing::Test {
+ protected:
+ TimGrabberTest () = default;
+ ~TimGrabberTest () override {}
+
+ std::vector<std::string> packets_;
+ std::vector<CloudT> correct_clouds_;
+ TestableTimGrabber grabber_;
+
+ virtual void SetUp () override {
+ constexpr float angle_start = - 1.0 * M_PI / 4.0;
+ constexpr float angle_range = 2.0 * M_PI * 3.0 / 4.0;
+
+ std::default_random_engine generator;
+ std::uniform_int_distribution<int> i_distribution (0, 1000);
+ std::uniform_real_distribution<float> f_distribution (0.0, 20.0);
+
+ CloudT cloud;
+
+ for (int i=0; i<1000; ++i) {
+ const size_t amount_of_data = i_distribution (generator);
+
+ cloud.reserve (amount_of_data);
+ cloud.clear ();
+
+ std::ostringstream ss;
+ ss << std::hex;
+ ss << " " << amount_of_data;
+
+ float angle = angle_start;
+ const float angle_step = angle_range / amount_of_data;
+
+ for (size_t i=0; i<amount_of_data; ++i, angle += angle_step) {
+ float distance = f_distribution (generator);
+ cloud.emplace_back (distance * std::cos (angle), distance * std::sin (angle), 0.0);
+ ss << " " << static_cast<int>(distance * 1000);
+ }
+ correct_clouds_.push_back (cloud);
+
+ std::string header_sample = "sRA LMDscandata 1 1 1291B11 0 0 AED5 AED7 FDB36397 FDB3779F 0 0 1 0 0 5DC A2 0 1 DIST1 3F800000 00000000 FFF92230 D05";
+ std::string packet = header_sample + ss.str ();
+ packets_.push_back (packet);
+ }
+ }
+};
+
+TEST_F (TimGrabberTest, Test1)
+{
+ CloudT::ConstPtr answer_cloud = grabber_.point_cloud_xyz_ptr_;
+
+ for (std::size_t i=0; i<packets_.size (); ++i) {
+ std::string packet = packets_.at(i);
+
+ grabber_.processTimPacket (packet);
+ grabber_.updateLookupTables ();
+ grabber_.toPointClouds ();
+
+ ASSERT_EQ (correct_clouds_.at(i).size (), answer_cloud->size ());
+
+ for (std::size_t j = 0; j < correct_clouds_.at(i).size (); j++) {
+ PointT const& correct_point = correct_clouds_.at(i).at(j);
+ PointT const& answer_point = answer_cloud->at(j);
+ EXPECT_NEAR (correct_point.x, answer_point.x, 1.0e-3);
+ EXPECT_NEAR (correct_point.y, answer_point.y, 1.0e-3);
+ EXPECT_NEAR (correct_point.z, answer_point.z, 1.0e-3);
+ }
+ }
+}
+
+/* ---[ */
+int
+main (int argc, char** argv)
+{
+ ::testing::InitGoogleTest (&argc, argv);
+ return (RUN_ALL_TESTS ());
+}
+/* ]--- */
include_directories(SYSTEM ${VTK_INCLUDE_DIRS})
PCL_ADD_TEST(a_people_detection_test test_people_detection
FILES test_people_groundBasedPeopleDetectionApp.cpp
- LINK_WITH pcl_gtest pcl_common pcl_io pcl_kdtree pcl_search pcl_features pcl_sample_consensus pcl_filters pcl_io pcl_segmentation pcl_people
+ LINK_WITH pcl_gtest pcl_common pcl_io pcl_kdtree pcl_search pcl_features pcl_sample_consensus pcl_filters pcl_segmentation pcl_people
ARGUMENTS "${PCL_SOURCE_DIR}/people/data/trainedLinearSVMForPeopleDetectionWithHOG.yaml" "${PCL_SOURCE_DIR}/test/five_people.pcd")
#include <pcl/test/gtest.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
-#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/people/ground_based_people_detection_app.h>
}
}
+TEST (SampleConsensusModelPlane, OptimizeFarFromOrigin)
+{ // Test if the model can successfully optimize a plane that is far from the origin
+ pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
+ Eigen::Vector3d x(-0.435197968, 0.598251061, -0.672828654);
+ Eigen::Vector3d y(-0.547340139, 0.417556627, 0.725303548);
+ Eigen::Vector3d z( 0.714857680, 0.683916759, 0.145727023); // This is the normal of the plane
+ Eigen::Vector3d center(7380.86467, -8350.60056617, 4324.22814107);
+ for(double i=-0.5; i<0.5; i+=0.01)
+ for(double j=-0.5; j<0.5; j+=0.01) {
+ Eigen::Vector3d p = center + i*x + j*y;
+ cloud->emplace_back(p[0], p[1], p[2]);
+ }
+ pcl::SampleConsensusModelPlane<pcl::PointXYZ> model(cloud, true);
+ pcl::Indices inliers;
+ for(std::size_t i=0; i<cloud->size(); ++i) inliers.push_back(i);
+ Eigen::VectorXf coeffs(4); // Doesn't have to be initialized, the function doesn't use them
+ Eigen::VectorXf optimized_coeffs(4);
+ model.optimizeModelCoefficients(inliers, coeffs, optimized_coeffs);
+ EXPECT_NEAR(optimized_coeffs[0], z[0], 5e-6);
+ EXPECT_NEAR(optimized_coeffs[1], z[1], 5e-6);
+ EXPECT_NEAR(optimized_coeffs[2], z[2], 5e-6);
+ EXPECT_NEAR(optimized_coeffs[3], -z.dot(center), 5e-2);
+}
+
int
main (int argc, char** argv)
{
*/
#include <pcl/test/gtest.h>
+#include <pcl/pcl_tests.h> // for EXPECT_XYZ_NEAR
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_sphere.h>
EXPECT_NEAR ( 0.0, coeff_refined[6], 1e-3);
}
+TEST (SampleConsensusModelCylinder, projectPoints)
+{
+ Eigen::VectorXf model_coefficients(7);
+ model_coefficients << -0.59, 0.85, -0.80, 0.22, -0.70, 0.68, 0.18;
+
+ pcl::PointCloud<pcl::PointXYZ>::Ptr input(new pcl::PointCloud<pcl::PointXYZ>);
+ input->emplace_back(-0.616358, 0.713315, -0.885120); // inlier, dist from axis=0.16
+ input->emplace_back( 0.595892, 0.455094, 0.025545); // outlier, not projected
+ input->emplace_back(-0.952749, 1.450040, -1.305640); // inlier, dist from axis=0.19
+ input->emplace_back(-0.644947, 1.421240, -1.421170); // inlier, dist from axis=0.14
+ input->emplace_back(-0.242308, -0.561036, -0.365535); // outlier, not projected
+ input->emplace_back(-0.502111, 0.694671, -0.878344); // inlier, dist from axis=0.18
+ input->emplace_back(-0.664129, 0.557583, -0.750060); // inlier, dist from axis=0.21
+ input->emplace_back(-0.033891, 0.624537, -0.606994); // outlier, not projected
+
+ pcl::SampleConsensusModelCylinder<pcl::PointXYZ, pcl::Normal> model(input);
+ // not necessary to set normals for model here because projectPoints does not use them
+ pcl::Indices inliers = {0, 2, 3, 5, 6};
+
+ pcl::PointCloud<pcl::PointXYZ> projected_truth;
+ projected_truth.emplace_back(-0.620532, 0.699027, -0.898478);
+ projected_truth.emplace_back(-0.943418, 1.449510, -1.309200);
+ projected_truth.emplace_back(-0.608243, 1.417710, -1.436680);
+ projected_truth.emplace_back(-0.502111, 0.694671, -0.878344);
+ projected_truth.emplace_back(-0.646557, 0.577140, -0.735612);
+
+ pcl::PointCloud<pcl::PointXYZ> projected_points;
+ model.projectPoints(inliers, model_coefficients, projected_points, false);
+ EXPECT_EQ(projected_points.size(), 5);
+ for(int i=0; i<5; ++i)
+ EXPECT_XYZ_NEAR(projected_points[i], projected_truth[i], 1e-5);
+
+ pcl::PointCloud<pcl::PointXYZ> projected_points_all;
+ model.projectPoints(inliers, model_coefficients, projected_points_all, true);
+ EXPECT_EQ(projected_points_all.size(), 8);
+ EXPECT_XYZ_NEAR(projected_points_all[0], projected_truth[0], 1e-5);
+ EXPECT_XYZ_NEAR(projected_points_all[1], (*input)[1], 1e-5);
+ EXPECT_XYZ_NEAR(projected_points_all[2], projected_truth[1], 1e-5);
+ EXPECT_XYZ_NEAR(projected_points_all[3], projected_truth[2], 1e-5);
+ EXPECT_XYZ_NEAR(projected_points_all[4], (*input)[4], 1e-5);
+ EXPECT_XYZ_NEAR(projected_points_all[5], projected_truth[3], 1e-5);
+ EXPECT_XYZ_NEAR(projected_points_all[6], projected_truth[4], 1e-5);
+ EXPECT_XYZ_NEAR(projected_points_all[7], (*input)[7], 1e-5);
+}
+
int
main (int argc, char** argv)
{
#include <pcl/common/distances.h>
#include <pcl/common/time.h>
#include <pcl/search/kdtree.h> // for pcl::search::KdTree
-#include <pcl/search/impl/flann_search.hpp>
+#include <pcl/search/flann_search.h> // for pcl::search::FlannSearch
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
PCL_ADD_TEST(random_walker test_random_walker
FILES test_random_walker.cpp
- LINK_WITH pcl_gtest
+ LINK_WITH pcl_gtest pcl_segmentation
ARGUMENTS "${PCL_SOURCE_DIR}/test/segmentation/data")
PCL_ADD_TEST(a_segmentation_test test_segmentation
set(SUBSYS_NAME tools)
set(SUBSYS_DESC "Useful PCL-based command line tools")
set(SUBSYS_DEPS common io filters sample_consensus segmentation search kdtree features surface octree registration recognition geometry keypoints ml)
-set(SUBSYS_OPT_DEPS visualization)
+set(SUBSYS_OPT_DEPS vtk visualization)
set(DEFAULT ON)
set(REASON "")
PCL_ADD_EXECUTABLE(pcl_obj2pcd COMPONENT ${SUBSYS_NAME} SOURCES obj2pcd.cpp)
target_link_libraries(pcl_obj2pcd pcl_common pcl_io)
- #TODO: Update when CMAKE 3.10 is available
- if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
+
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
target_link_libraries(pcl_obj2pcd VTK::FiltersCore)
endif()
PCL_ADD_EXECUTABLE(pcl_vtk2pcd COMPONENT ${SUBSYS_NAME} SOURCES vtk2pcd.cpp)
target_link_libraries(pcl_vtk2pcd pcl_common pcl_io)
- #TODO: Update when CMAKE 3.10 is available
- if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
+
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
target_link_libraries(pcl_vtk2pcd VTK::FiltersCore)
endif()
target_link_libraries(pcl_octree_viewer pcl_common pcl_io pcl_octree pcl_visualization pcl_kdtree pcl_filters)
PCL_ADD_EXECUTABLE(pcl_mesh2pcd COMPONENT ${SUBSYS_NAME} SOURCES mesh2pcd.cpp)
- target_link_libraries(pcl_mesh2pcd pcl_common pcl_io pcl_visualization pcl_filters ${VTK_LIBRARIES})
+ target_link_libraries(pcl_mesh2pcd pcl_common pcl_io pcl_visualization pcl_filters)
PCL_ADD_EXECUTABLE(pcl_mesh_sampling COMPONENT ${SUBSYS_NAME} SOURCES mesh_sampling.cpp)
- target_link_libraries(pcl_mesh_sampling pcl_common pcl_io pcl_visualization pcl_filters ${VTK_LIBRARIES})
+ target_link_libraries(pcl_mesh_sampling pcl_common pcl_io pcl_visualization pcl_filters)
PCL_ADD_EXECUTABLE(pcl_virtual_scanner COMPONENT ${SUBSYS_NAME} SOURCES virtual_scanner.cpp)
- target_link_libraries(pcl_virtual_scanner pcl_common pcl_io pcl_filters pcl_visualization ${VTK_LIBRARIES})
+ target_link_libraries(pcl_virtual_scanner pcl_common pcl_io pcl_filters pcl_visualization)
PCL_ADD_EXECUTABLE(pcl_voxel_grid_occlusion_estimation COMPONENT ${SUBSYS_NAME} SOURCES voxel_grid_occlusion_estimation.cpp)
target_link_libraries (pcl_voxel_grid_occlusion_estimation pcl_common pcl_io pcl_filters pcl_visualization)
if(WITH_OPENNI)
PCL_ADD_EXECUTABLE(pcl_openni_save_image COMPONENT ${SUBSYS_NAME} SOURCES openni_save_image.cpp)
- target_link_libraries(pcl_openni_save_image pcl_common pcl_io pcl_visualization)
+ target_link_libraries(pcl_openni_save_image pcl_common pcl_io pcl_visualization Boost::date_time)
PCL_ADD_EXECUTABLE(pcl_pcd_grabber_viewer COMPONENT ${SUBSYS_NAME} SOURCES pcd_grabber_viewer.cpp BUNDLE)
target_link_libraries(pcl_pcd_grabber_viewer pcl_common pcl_io pcl_kdtree pcl_visualization)
target_link_libraries(pcl_openni_viewer pcl_common pcl_io pcl_kdtree pcl_visualization)
PCL_ADD_EXECUTABLE(pcl_openni_image COMPONENT ${SUBSYS_NAME} SOURCES openni_image.cpp BUNDLE)
- target_link_libraries(pcl_openni_image pcl_common pcl_io pcl_kdtree pcl_visualization)
+ target_link_libraries(pcl_openni_image pcl_common pcl_io pcl_kdtree pcl_visualization Boost::date_time)
endif()
if(WITH_OPENNI2)
#include <vtkImageData.h> // for vtkImageData
#include <vtkSmartPointer.h>
-#include <vtkImageViewer2.h>
#include <vtkTIFFReader.h>
-#include <vtkRenderWindow.h>
-#include <vtkRenderWindowInteractor.h>
-#include <vtkRenderer.h>
using namespace pcl;
)
endif()
-if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
+if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
if(NOT (";${VTK_AVAILABLE_COMPONENTS};" MATCHES ";RenderingContextOpenGL2;"))
list(REMOVE_ITEM incs
target_link_libraries("${LIB_NAME}" pcl_common pcl_io pcl_kdtree ${OPENGL_LIBRARIES})
-if(${VTK_VERSION} VERSION_LESS 9.0)
- target_include_directories("${LIB_NAME}" SYSTEM PUBLIC ${VTK_INCLUDE_DIRS})
- target_link_libraries("${LIB_NAME}" ${VTK_LIBRARIES})
-else()
+if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
#Some libs are referenced through depending on IO
target_link_libraries("${LIB_NAME}"
VTK::ChartsCore
VTK::RenderingOpenGL2
VTK::ViewsContext2D)
- if(";${VTK_AVAILABLE_COMPONENTS};" MATCHES ";RenderingContextOpenGL2;")
+ if("RenderingContextOpenGL2" IN_LIST VTK_AVAILABLE_COMPONENTS)
target_link_libraries("${LIB_NAME}" VTK::RenderingContextOpenGL2)
endif()
+else()
+ target_include_directories("${LIB_NAME}" SYSTEM PUBLIC ${VTK_INCLUDE_DIRS})
+ target_link_libraries("${LIB_NAME}"
+ vtkChartsCore
+ vtkFiltersExtraction
+ vtkFiltersGeometry
+ vtkFiltersModeling
+ vtkImagingCore
+ vtkImagingSources
+ vtkInteractionStyle
+ vtkRenderingAnnotation
+ vtkRenderingContext2D
+ vtkRenderingContext${VTK_RENDERING_BACKEND}
+ vtkRenderingFreeType
+ vtkRenderingLOD
+ vtkRendering${VTK_RENDERING_BACKEND}
+ vtkViewsContext2D)
+ if(${VTK_VERSION} VERSION_LESS 7.0)
+ target_link_libraries("${LIB_NAME}" vtkRenderingVolume${VTK_RENDERING_BACKEND})
+ endif()
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 7.0 AND ${VTK_VERSION} VERSION_LESS 9.0)
+ target_link_libraries("${LIB_NAME}" vtkRenderingGL2PS${VTK_RENDERING_BACKEND})
+ endif()
+
+ # These two libraries are present and required in ubuntu 18.04 VTK 6, but not present in later versions of ubuntu using VTK 6.
+ # They are also present on later versions of VTK on later versions of ubuntu.
+ if("vtkRenderingFreeTypeFontConfig" IN_LIST VTK_MODULES_ENABLED)
+ target_link_libraries("${LIB_NAME}" vtkRenderingFreeTypeFontConfig)
+ endif()
+ if("vtkRenderingMatplotlib" IN_LIST VTK_MODULES_ENABLED)
+ target_link_libraries("${LIB_NAME}" vtkRenderingMatplotlib)
+ endif()
+endif()
+
+if(HAVE_QVTK)
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
+ target_link_libraries("${LIB_NAME}" VTK::GUISupportQt)
+ else()
+ target_link_libraries("${LIB_NAME}" vtkGUISupportQt)
+ endif()
endif()
set(EXT_DEPS "")
scalars->SetNumberOfTuples (nr_points);
unsigned char* colors = scalars->GetPointer (0);
- int j = 0;
// If XYZ present, check if the points are invalid
int x_idx = -1;
for (std::size_t d = 0; d < fields_.size (); ++d)
pcl::RGB rgb;
if (x_idx != -1)
{
+ int j = 0;
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp)
{
getCameraFile () const;
/** \brief Update camera parameters and render. */
- void
- updateCamera ();
+ PCL_DEPRECATED(1,15,"updateCamera will be removed, as it does nothing.")
+ inline void
+ updateCamera () {};
/** \brief Reset camera parameters and render. */
void
*/
#include <vtkVersion.h>
+#if VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION == 0
+#include <limits> // This must be included before vtkPolyData.h
+#endif
#include <vtkPolyData.h>
#include <vtkCleanPolyData.h>
#include <vtkSmartPointer.h>
*/
#include <vtkVersion.h>
+#if VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION == 0
+#include <limits> // This must be included before vtkDoubleArray.h
+#endif
+#include <vtkDoubleArray.h>
#include <vtkSmartPointer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderWindow.h>
#include <vtkContextScene.h>
#include <vtkAxis.h>
#include <vtkPlot.h>
-#include <vtkDoubleArray.h>
#include <vtkTable.h>
#include <fstream>