image: pointcloudlibrary/env:winx86
- container: winx64
image: pointcloudlibrary/env:winx64
- - container: fmt
- image: pointcloudlibrary/fmt
- container: env1804
image: pointcloudlibrary/env:18.04
- container: env2004
image: pointcloudlibrary/env:20.04
- - container: env2010
- image: pointcloudlibrary/env:20.10
+ - container: env2204
+ image: pointcloudlibrary/env:22.04
stages:
- stage: formatting
CXX: g++
BUILD_GPU: ON
CMAKE_ARGS: '-DPCL_WARNINGS_ARE_ERRORS=ON'
- 20.10 GCC: # latest Ubuntu
- CONTAINER: env2010
+ 22.04 GCC: # latest Ubuntu
+ CONTAINER: env2204
CC: gcc
CXX: g++
- BUILD_GPU: OFF
+ BUILD_GPU: OFF # There are currently incompatibilities between GCC 11.2 and CUDA 11.5
container: $[ variables['CONTAINER'] ]
timeoutInMinutes: 0
variables:
vmImage: '$(VMIMAGE)'
strategy:
matrix:
- Catalina 10.15:
- VMIMAGE: 'macOS-10.15'
- OSX_VERSION: '10.15'
Big Sur 11:
VMIMAGE: 'macOS-11'
OSX_VERSION: '11'
+ Monterey 12:
+ VMIMAGE: 'macOS-12'
+ OSX_VERSION: '12'
timeoutInMinutes: 0
variables:
BUILD_DIR: '$(Agent.WorkFolder)/build'
-DBUILD_apps_cloud_composer=ON \
-DBUILD_apps_in_hand_scanner=ON \
-DBUILD_apps_modeler=ON \
- -DBUILD_apps_point_cloud_editor=ON
+ -DBUILD_apps_point_cloud_editor=ON \
+ -DBoost_USE_DEBUG_RUNTIME=OFF
displayName: 'CMake Configuration'
- script: |
cd $BUILD_DIR
stages:
- build_gcc
containers:
- - container: fmt # for formatting.yaml
- image: pointcloudlibrary/fmt
- container: doc # for documentation.yaml
image: pointcloudlibrary/doc
- - container: env1804 # for tutorials.yaml
- image: pointcloudlibrary/env:18.04
+ - container: env2204 # for tutorials.yaml
+ image: pointcloudlibrary/env:22.04
stages:
- stage: formatting
strategy:
matrix:
Ubuntu 18.04:
- CUDA_VERSION: 10.2
- UBUNTU_DISTRO: 18.04
- USE_CUDA: true
- VTK_VERSION: 6
+ # Test the oldest supported version of Ubuntu
+ UBUNTU_VERSION: 18.04
+ VTK_VERSION: 7
+ ENSENSOSDK_VERSION: 2.3.1570
TAG: 18.04
Ubuntu 20.04:
- CUDA_VERSION: 11.2.1
- UBUNTU_DISTRO: 20.04
+ UBUNTU_VERSION: 20.04
VTK_VERSION: 7
- USE_CUDA: true
TAG: 20.04
- Ubuntu 20.10:
- CUDA_VERSION: 11.2.1
- UBUNTU_DISTRO: 20.10
- VTK_VERSION: 7
- # nvidia-cuda docker image has not been released for 20.10 yet
- USE_CUDA: ""
- TAG: 20.10
- Ubuntu 21.04:
- CUDA_VERSION: 11.2.1
- UBUNTU_DISTRO: 21.04
+ # Test the latest LTS version of Ubuntu
+ Ubuntu 22.04:
+ UBUNTU_VERSION: 22.04
VTK_VERSION: 9
- # nvidia-cuda docker image has not been released for 21.04 yet
- USE_CUDA: ""
- TAG: 21.04
+ TAG: 22.04
+ Ubuntu 22.10:
+ UBUNTU_VERSION: 22.10
+ USE_LATEST_CMAKE: true
+ VTK_VERSION: 9
+ TAG: 22.10
steps:
+ - script: |
+ dockerBuildArgs="" ; \
+ if [ -n "$UBUNTU_VERSION" ]; then \
+ dockerBuildArgs="$dockerBuildArgs --build-arg UBUNTU_VERSION=$UBUNTU_VERSION" ; \
+ fi ; \
+ if [ -n "$ENSENSOSDK_VERSION" ]; then \
+ dockerBuildArgs="$dockerBuildArgs --build-arg ENSENSOSDK_VERSION=$ENSENSOSDK_VERSION" ; \
+ fi ; \
+ if [ -n "$VTK_VERSION" ]; then \
+ dockerBuildArgs="$dockerBuildArgs --build-arg VTK_VERSION=$VTK_VERSION" ; \
+ fi ; \
+ if [ -n "$USE_LATEST_CMAKE" ]; then \
+ dockerBuildArgs="$dockerBuildArgs --build-arg USE_LATEST_CMAKE=$USE_LATEST_CMAKE" ; \
+ fi
+ echo "##vso[task.setvariable variable=dockerBuildArgs]$dockerBuildArgs"
+ displayName: "Prepare docker build arguments"
- task: Docker@2
displayName: "Build docker image"
inputs:
command: build
arguments: |
--no-cache
- --build-arg CUDA_VERSION=$(CUDA_VERSION)
- --build-arg UBUNTU_DISTRO=$(UBUNTU_DISTRO)
- --build-arg USE_CUDA=$(USE_CUDA)
- --build-arg VTK_VERSION=$(VTK_VERSION)
+ $(dockerBuildArgs)
-t $(dockerHubID)/env:$(TAG)
dockerfile: '$(Build.SourcesDirectory)/.dev/docker/env/Dockerfile'
tags: "$(TAG)"
PLATFORM: x86
TAG: winx86
GENERATOR: "'Visual Studio 16 2019' -A Win32"
- VCPKGCOMMIT: 5568f110b509a9fd90711978a7cb76bae75bb092
+ VCPKGCOMMIT: acc3bcf76b84ae5041c86ab55fe138ae7b8255c7
Winx64:
PLATFORM: x64
TAG: winx64
- job: formatting
displayName: Check code formatting
pool:
- vmImage: 'Ubuntu 20.04'
- container: fmt
+ vmImage: 'ubuntu-22.04'
steps:
- checkout: self
# find the commit hash on a quick non-forced update too
displayName: Building Tutorials
pool:
vmImage: 'Ubuntu 20.04'
- container: env1804
+ container: env2204
timeoutInMinutes: 0
variables:
BUILD_DIR: '$(Agent.BuildDirectory)/build'
--- /dev/null
+trigger:
+ branches:
+ include:
+ - master
+ paths:
+ include:
+ - .dev/docker/ubuntu-variety
+ - .ci/azure-pipelines/ubuntu-variety.yaml
+
+pr:
+ paths:
+ include:
+ - .dev/docker/ubuntu-variety
+ - .ci/azure-pipelines/ubuntu-variety.yaml
+
+schedules:
+- cron: "0 0 * * 6"
+ displayName: "Saturday midnight build"
+ branches:
+ include:
+ - master
+
+resources:
+- repo: self
+
+jobs:
+- job: BuildUbuntuVariety
+ timeoutInMinutes: 360
+ displayName: "BuildUbuntuVariety"
+ steps:
+ - script: |
+ POSSIBLE_VTK_VERSION=("7" "9") \
+ POSSIBLE_CMAKE_CXX_STANDARD=("14" "17" "20") \
+ POSSIBLE_CMAKE_BUILD_TYPE=("None" "Debug" "Release" "RelWithDebInfo" "MinSizeRel") \
+ POSSIBLE_COMPILER_PACKAGE=("g++" "g++-10" "g++-11" "g++-12" "clang" "clang-11" "clang-12" "clang-13" "clang-14" "clang-15") \
+ POSSIBLE_CMAKE_C_COMPILER=("gcc" "gcc-10" "gcc-11" "gcc-12" "clang" "clang-11" "clang-12" "clang-13" "clang-14" "clang-15") \
+ POSSIBLE_CMAKE_CXX_COMPILER=("g++" "g++-10" "g++-11" "g++-12" "clang++" "clang++-11" "clang++-12" "clang++-13" "clang++-14" "clang++-15") \
+ CHOSEN_COMPILER=$[RANDOM%${#POSSIBLE_COMPILER_PACKAGE[@]}] \
+ dockerBuildArgs="--build-arg VTK_VERSION=${POSSIBLE_VTK_VERSION[$[RANDOM%${#POSSIBLE_VTK_VERSION[@]}]]} --build-arg CMAKE_CXX_STANDARD=${POSSIBLE_CMAKE_CXX_STANDARD[$[RANDOM%${#POSSIBLE_CMAKE_CXX_STANDARD[@]}]]} --build-arg CMAKE_BUILD_TYPE=${POSSIBLE_CMAKE_BUILD_TYPE[$[RANDOM%${#POSSIBLE_CMAKE_BUILD_TYPE[@]}]]} --build-arg COMPILER_PACKAGE=${POSSIBLE_COMPILER_PACKAGE[$CHOSEN_COMPILER]} --build-arg CMAKE_C_COMPILER=${POSSIBLE_CMAKE_C_COMPILER[$CHOSEN_COMPILER]} --build-arg CMAKE_CXX_COMPILER=${POSSIBLE_CMAKE_CXX_COMPILER[$CHOSEN_COMPILER]}" ; \
+ echo "##vso[task.setvariable variable=dockerBuildArgs]$dockerBuildArgs"
+ displayName: "Prepare docker build arguments"
+ - task: Docker@2
+ displayName: "Build docker image"
+ inputs:
+ command: build
+ arguments: |
+ --no-cache
+ $(dockerBuildArgs)
+ dockerfile: '$(Build.SourcesDirectory)/.dev/docker/ubuntu-variety/Dockerfile'
--- /dev/null
+---
+Checks: '-*,modernize-use-auto,modernize-deprecated-headers,modernize-redundant-void-arg,modernize-replace-random-shuffle,modernize-use-equals-default,modernize-use-equals-delete,modernize-use-nullptr,modernize-use-override,modernize-use-using,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-type-promotion-in-math-fn,cppcoreguidelines-pro-type-cstyle-cast,cppcoreguidelines-pro-type-static-cast-downcast'
+WarningsAsErrors: '-*,modernize-use-auto,modernize-deprecated-headers,modernize-redundant-void-arg,modernize-replace-random-shuffle,modernize-use-equals-default,modernize-use-equals-delete,modernize-use-nullptr,modernize-use-override,modernize-use-using,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-type-promotion-in-math-fn,cppcoreguidelines-pro-type-cstyle-cast,cppcoreguidelines-pro-type-static-cast-downcast'
+CheckOptions:
+- {key: modernize-use-auto.MinTypeNameLength, value: 7}
-FROM pointcloudlibrary/env:20.04
+FROM pointcloudlibrary/env:22.04
ENV DEBIAN_FRONTEND=noninteractive
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install Jinja2 sphinx sphinxcontrib-doxylink sphinx_rtd_theme requests grip
-
-# Use eps2eps to solve https://github.com/doxygen/doxygen/issues/7484 before Doxygen 1.8.18
-RUN update-alternatives --install /usr/local/bin/ps2epsi ps2epsi /usr/bin/ps2epsi 1 \
- && update-alternatives --install /usr/local/bin/ps2epsi ps2epsi /usr/bin/eps2eps 1000
-# For valid combinations, check the following repo:
-# https://gitlab.com/nvidia/container-images/cuda/tree/master/dist
-# To enable cuda, use "--build-arg USE_CUDA=true" during image build process
-ARG USE_CUDA
-ARG CUDA_VERSION="9.2"
-ARG UBUNTU_DISTRO="16.04"
-ARG BASE_CUDA_IMAGE=${USE_CUDA:+"nvidia/cuda:${CUDA_VERSION}-devel-ubuntu${UBUNTU_DISTRO}"}
-ARG BASE_IMAGE=${BASE_CUDA_IMAGE:-"ubuntu:${UBUNTU_DISTRO}"}
+ARG UBUNTU_VERSION=20.04
-FROM ${BASE_IMAGE}
+FROM "ubuntu:${UBUNTU_VERSION}"
+# Eigen patch (https://eigen.tuxfamily.org/bz/show_bug.cgi?id=1462) to fix issue metioned
+# in https://github.com/PointCloudLibrary/pcl/issues/3729 is available in Eigen 3.3.7.
+# Not needed from 20.04 since it is the default version from apt
+ARG EIGEN_MINIMUM_VERSION=3.3.7
+
+# See https://www.optonic.com/support/download/ensenso-sdk/archiv/ for available versions
+ARG ENSENSOSDK_VERSION=3.2.489
+
+# See https://github.com/IntelRealSense/librealsense/tags for available tags of releases
+ARG REALSENSE_VERSION=2.50.0
+
+# Check https://packages.ubuntu.com/search?suite=all&arch=any&searchon=names&keywords=libvtk%20qt-dev
+# for available packes for choosen UBUNTU_VERSION
ARG VTK_VERSION=6
+
+# Use the latest version of CMake by adding the Kitware repository if true,
+# otherwise use the default version of CMake of the system.
+ARG USE_LATEST_CMAKE=false
+
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
- && apt-get install -y \
- xvfb \
- cmake \
- g++ \
+ && apt-get -V install -y \
+ build-essential \
clang \
- wget \
+ clang-tidy \
+ libbenchmark-dev \
+ libblas-dev \
libboost-date-time-dev \
libboost-filesystem-dev \
libboost-iostreams-dev \
- libeigen3-dev \
- libblas-dev \
libflann-dev \
libglew-dev \
libgtest-dev \
- libbenchmark-dev \
libopenni-dev \
libopenni2-dev \
libproj-dev \
libusb-1.0-0-dev \
libvtk${VTK_VERSION}-dev \
libvtk${VTK_VERSION}-qt-dev \
+ lsb-release \
qtbase5-dev \
software-properties-common \
+ wget \
+ xvfb \
+ && if [ "$USE_LATEST_CMAKE" = true ] ; then \
+ cmake_ubuntu_version=$(lsb_release -cs) ; \
+ if ! wget -q --method=HEAD "https://apt.kitware.com/ubuntu/dists/$cmake_ubuntu_version/Release"; then \
+ cmake_ubuntu_version="focal" ; \
+ fi ; \
+ wget -qO - https://apt.kitware.com/kitware-archive.sh | bash -s -- --release $cmake_ubuntu_version ; \
+ apt-get update ; \
+ fi \
+ && apt-get -V install -y cmake \
+ && if [ "$(lsb_release -sr)" = "18.04" ]; then \
+ apt-get -V install -y nvidia-cuda-toolkit g++-6 ; \
+ else \
+ apt-get -V install -y nvidia-cuda-toolkit-gcc ; \
+ fi \
&& rm -rf /var/lib/apt/lists/*
-# Eigen patch (https://eigen.tuxfamily.org/bz/show_bug.cgi?id=1462) to fix issue metioned
-# in https://github.com/PointCloudLibrary/pcl/issues/3729 is available in Eigen 3.3.7
-# Not needed from 20.04 since it is the default version from apt
-RUN if [ `pkg-config --modversion eigen3 | cut -d. -f3` -lt 7 ]; then \
- wget -qO- https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz | tar xz \
- && apt install -y libblas-dev \
- && cd eigen-3.3.7 \
- && mkdir build \
- && cd build \
- && cmake .. \
- && make install \
- && cd ../.. \
- && rm -rf eigen-3.3.7/ \
- && rm -f eigen-3.3.7.tar.gz ; \
- fi
-
-# To avoid CUDA build errors on CUDA 9.2+ GCC 7 is required
-RUN if [ `gcc -dumpversion | cut -d. -f1` -lt 7 ]; then add-apt-repository ppa:ubuntu-toolchain-r/test \
- && apt update \
- && apt install g++-7 -y \
- && update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 --slave /usr/bin/g++ g++ /usr/bin/g++-7 \
- && update-alternatives --config gcc ; \
+# Use libeigen3-dev if it meets the minimal version.
+# In most cases libeigen3-dev is already installed as a dependency of libvtk6-dev & libvtk7-dev, but not in every case (libvtk9 doesn't seem to have this dependency),
+# so install it from apt if the version is sufficient.
+RUN if dpkg --compare-versions $(apt-cache show --no-all-versions libeigen3-dev | grep -P -o 'Version:\s*\K.*') ge ${EIGEN_MINIMUM_VERSION}; then \
+ apt-get -V install -y libeigen3-dev ; \
+ else \
+ wget -qO- https://gitlab.com/libeigen/eigen/-/archive/${EIGEN_MINIMUM_VERSION}/eigen-${EIGEN_MINIMUM_VERSION}.tar.gz | tar xz \
+ && cd eigen-${EIGEN_MINIMUM_VERSION} \
+ && mkdir build \
+ && cd build \
+ && cmake .. \
+ && make -j$(nproc) install \
+ && cd ../.. \
+ && rm -rf eigen-${EIGEN_MINIMUM_VERSION}/ ; \
fi
-RUN wget -qO- https://github.com/IntelRealSense/librealsense/archive/v2.23.0.tar.gz | tar xz \
- && cd librealsense-2.23.0 \
+RUN wget -qO- https://github.com/IntelRealSense/librealsense/archive/v${REALSENSE_VERSION}.tar.gz | tar xz \
+ && cd librealsense-${REALSENSE_VERSION} \
&& mkdir build \
&& cd build \
&& cmake .. -DBUILD_EXAMPLES=OFF -DBUILD_GRAPHICAL_EXAMPLES=OFF \
- && make -j2 \
- && make install \
+ && make -j$(nproc) install \
&& cd ../.. \
- && rm -rf librealsense-2.23.0
+ && rm -rf librealsense-${REALSENSE_VERSION}
-RUN wget -qO ensenso.deb https://download.ensenso.com/s/ensensosdk/download?files=ensenso-sdk-2.2.160-x64.deb \
+RUN wget -qO ensenso.deb https://download.ensenso.com/s/ensensosdk/download?files=ensenso-sdk-${ENSENSOSDK_VERSION}-x64.deb \
&& dpkg -i ensenso.deb \
&& rm ensenso.deb
+++ /dev/null
-# Azure needs node shadow, sudo and the label
-FROM node:lts-alpine
-
-# clang-10 needed alpine edge as of 2020-Apr-28
-RUN apk add \
- --no-cache \
- --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main \
- bash clang git shadow sudo
-
-LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"
-
-CMD [ "bash" ]
--- /dev/null
+# TODO maybe also rolling and latest?
+FROM "ubuntu:devel"
+
+# TODO PCL_INDEX_SIZE and PCL_INDEX_SIGNED
+# TODO test more versions of cmake, boost, vtk, eigen, qt, maybe flann, maybe other compilers?
+ARG VTK_VERSION
+ARG CMAKE_CXX_STANDARD
+ARG CMAKE_BUILD_TYPE
+ARG COMPILER_PACKAGE
+ARG CMAKE_C_COMPILER
+ARG CMAKE_CXX_COMPILER
+RUN echo VTK_VERSION=${VTK_VERSION} CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} COMPILER_PACKAGE=${COMPILER_PACKAGE} CMAKE_C_COMPILER=${CMAKE_C_COMPILER} CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
+
+ENV DEBIAN_FRONTEND=noninteractive
+RUN apt update
+RUN apt install -y git cmake ${COMPILER_PACKAGE}
+RUN apt install -y libeigen3-dev libflann-dev
+RUN apt install -y libboost-filesystem-dev libboost-date-time-dev libboost-iostreams-dev
+RUN apt install -y libgtest-dev libbenchmark-dev
+RUN apt install -y qtbase5-dev libvtk${VTK_VERSION}-dev libvtk${VTK_VERSION}-qt-dev
+
+RUN cd \
+ && git clone --depth=1 https://github.com/PointCloudLibrary/pcl \
+ && mkdir pcl/build \
+ && cd pcl/build \
+ && cmake .. -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DBUILD_simulation=ON -DBUILD_surface_on_nurbs=ON -DBUILD_global_tests=ON -DBUILD_benchmarks=ON -DBUILD_examples=ON -DBUILD_tools=ON -DBUILD_apps=ON -DBUILD_apps_3d_rec_framework=ON -DBUILD_apps_cloud_composer=ON -DBUILD_apps_in_hand_scanner=ON -DBUILD_apps_modeler=ON -DBUILD_apps_point_cloud_editor=ON \
+ && cmake --build . -- -j2 -k \
+ && cmake --build . -- tests
+# TODO maybe also build tutorials?
"C:\TEMP\VisualStudio.chman", `
"--add", `
"Microsoft.VisualStudio.Workload.VCTools", `
+ "Microsoft.Net.Component.4.7.2.SDK", `
+ "Microsoft.VisualStudio.Component.VC.ATLMFC", `
"--includeRecommended" `
-Wait -PassThru; `
del c:\temp\vs_buildtools.exe;
RUN cd .\vcpkg; `
.\bootstrap-vcpkg.bat; `
- .\vcpkg install boost flann eigen3 qhull vtk[qt,opengl] gtest benchmark --triplet $Env:PLATFORM-windows-rel --clean-after-build;
+ .\vcpkg install boost flann eigen3 qhull vtk[qt,opengl] gtest benchmark openni2 --triplet $Env:PLATFORM-windows-rel --clean-after-build;
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 gpu/segmentation"
+ local whitelist="apps/3d_rec_framework apps/in_hand_scanner 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
+# EditorConfig file, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+tab_width = 2
+trim_trailing_whitespace = true
+
+# Visual C++ Code Style settings
+cpp_generate_documentation_comments = doxygen_slash_star
**To Reproduce**
-Provide a link to a live example, or an unambiguous set of steps to reproduce this bug. A reproducible example helps to provide faster answers.
+Provide a link to a live example, or an unambiguous set of steps to reproduce this bug. A reproducible example helps to provide faster answers. If you load data e.g. from a PCD or PLY file, please provide the file.
**Screenshots/Code snippets**
- OS: [e.g. Ubuntu 16.04]
- Compiler: [:eg GCC 8.1]
- PCL Version [e.g. 1.10, HEAD] (NB: please ensure you don't have multiple versions available)
- - PCL Type: [Installed/Compiled from source]
+ - PCL Type: [e.g. Installed with VCPKG/Installed with apt/Compiled from source]
If PCL was compiled from source or failure in compiling PCL itself:
- GPU, Kinfu, CUDA enabled? Yes/No
--- /dev/null
+name: clang-tidy
+
+on: [push, pull_request]
+
+jobs:
+ tidy:
+ runs-on: ubuntu-latest
+ container:
+ image: pointcloudlibrary/env:22.04
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Run clang-tidy
+ run: |
+ bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
+ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_COMPILER=/usr/bin/clang-14 -DCMAKE_C_COMPILER=/usr/bin/clang-14 . \
+ -DBUILD_benchmarks=ON \
+ -DBUILD_examples=ON \
+ -DBUILD_simulation=ON \
+ -DBUILD_global_tests=ON
+
+ run-clang-tidy -header-filter='.*'
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS vtk)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS vtk)
PCL_ADD_DOC("${SUBSYS_NAME}")
Convolution<ImageType> conv_2d;
public:
- Keypoint() {}
+ Keypoint() = default;
void
harrisCorner(ImageType& output,
public:
using PCLBase<PointT>::input_;
- Morphology() {}
+ Morphology() = default;
/** \brief This function performs erosion followed by dilation.
* It is useful for removing noise in the form of small blobs and patches.
# ChangeList
+## = 1.13.0 (10 December 2022) =
+
+### Notable changes
+
+**New features** *added to PCL*
+
+* **[ci]** Add new CI to cover uncommon configurations, running weekly [[#5208](https://github.com/PointCloudLibrary/pcl/pull/5208)]
+* **[common]** Added PointCloudXYZHSVtoXYZRGB function [[#5220](https://github.com/PointCloudLibrary/pcl/pull/5220)]
+* **[visualization]** Add option to enable EDL rendering. [[#4941](https://github.com/PointCloudLibrary/pcl/pull/4941)]
+* **[io]** Add empty point cloud support at pcd file. [[#5400](https://github.com/PointCloudLibrary/pcl/pull/5400)]
+* **[filters]** FrustumCulling: allowing infinite far plane distance [[#5433](https://github.com/PointCloudLibrary/pcl/pull/5433)]
+* **[filters]** FrustumCulling: asymmetrical Field of View [[#5438](https://github.com/PointCloudLibrary/pcl/pull/5438)]
+* **[filters]** Add farthest point sampling filter [[#3723](https://github.com/PointCloudLibrary/pcl/pull/3723)]
+* **[sample_consensus]** Adds Ellipse3D SacModel Class [[#5512](https://github.com/PointCloudLibrary/pcl/pull/5512)]
+
+**Deprecation** *of public APIs, scheduled to be removed after two minor releases*
+
+* **[gpu]** Use C++11 `std::atomic` instead of non-standard extensions [[#4807](https://github.com/PointCloudLibrary/pcl/pull/4807)]
+* **[registration]** Use likelihood instead of probability in `ndt` [[#5073](https://github.com/PointCloudLibrary/pcl/pull/5073)]
+* **[gpu]** Remove hand-rolled `static_assert` [[#4797](https://github.com/PointCloudLibrary/pcl/pull/4797)]
+* Deprecate remaining three boost.h headers [[#5486](https://github.com/PointCloudLibrary/pcl/pull/5486)]
+
+**Removal** *of the public APIs deprecated in previous releases*
+
+* Remove deprecated code before PCL 1.13.0 release [[#5375](https://github.com/PointCloudLibrary/pcl/pull/5375)]
+
+**Behavior changes** *in classes, apps, or tools*
+
+* **[cmake]** Drop version from pkg-config files, now accessible as `pcl_{module}.pc` [[#4977](https://github.com/PointCloudLibrary/pcl/pull/4977)]
+
+**API changes** *that did not go through the proper deprecation and removal cycle*
+
+* **[filters]** applyFilter() made protected [[#4933](https://github.com/PointCloudLibrary/pcl/pull/4933)]
+
+**ABI changes** *that are still API compatible*
+
+* **[filters]** Add `PCL_MAKE_ALIGNED_OPERATOR_NEW` to CropBox for better Eigen support [[#4962](https://github.com/PointCloudLibrary/pcl/pull/4962)]
+* **[features]** Add more configuration options to GRSDEstimation [[#4852](https://github.com/PointCloudLibrary/pcl/pull/4852)]
+* **[sample_consensus]** Implement `SampleConsensusModelSphere<PointT>::projectPoints` properly [[#5095](https://github.com/PointCloudLibrary/pcl/pull/5095)]
+* **[filters]** applyFilter() made protected [[#4933](https://github.com/PointCloudLibrary/pcl/pull/4933)]
+* **[io]** Introduce buffer for texture coordinate indices in TextureMesh [[#4971](https://github.com/PointCloudLibrary/pcl/pull/4971)]
+* **[filters]** Added region of interest for frustum culling [[#5136](https://github.com/PointCloudLibrary/pcl/pull/5136)]
+* **[common]** constexpr constructors for point types [[#4646](https://github.com/PointCloudLibrary/pcl/pull/4646)]
+
+### Changes grouped by module
+
+#### CMake:
+
+* **[behavior change]** Drop version from pkg-config files, now accessible as `pcl_{module}.pc` [[#4977](https://github.com/PointCloudLibrary/pcl/pull/4977)]
+* Don't require boost in pkg-config [[#5110](https://github.com/PointCloudLibrary/pcl/pull/5110)]
+* Link against atomic if needed (found on armel) [[#5117](https://github.com/PointCloudLibrary/pcl/pull/5117)]
+* Add more error handling to some PCL CMake functions [[#5344](https://github.com/PointCloudLibrary/pcl/pull/5344)]
+* Combine `PCL_SUBSUBSYS_DEPEND` with `PCL_SUBSYS_DEPEND` [[#5387](https://github.com/PointCloudLibrary/pcl/pull/5387)]
+* Allow compilation with Boost 1.80 [[#5391](https://github.com/PointCloudLibrary/pcl/pull/5391)]
+* Fix issue with `TARGET_PDB_FILE` [[#5396](https://github.com/PointCloudLibrary/pcl/pull/5396)]
+* Fix append multiple BOOST_ALL_NO_LIB in preprocessor macro [[#5221](https://github.com/PointCloudLibrary/pcl/pull/5221)]
+* Add define for static build google benchmark. [[#5492](https://github.com/PointCloudLibrary/pcl/pull/5492)]
+
+#### libpcl_common:
+
+* Fix division and subtraction operators [[#4909](https://github.com/PointCloudLibrary/pcl/pull/4909)]
+* Add `PointXY` specific behavior to `transformPointCloud()` [[#4943](https://github.com/PointCloudLibrary/pcl/pull/4943)]
+* Fix division by 0 width in `PointCloud` structured `assign` [[#5113](https://github.com/PointCloudLibrary/pcl/pull/5113)]
+* RangeImage: add check before accessing lookup table [[#5149](https://github.com/PointCloudLibrary/pcl/pull/5149)]
+* Fix build errors [[#5155](https://github.com/PointCloudLibrary/pcl/pull/5155)]
+* **[new feature]** Added PointCloudXYZHSVtoXYZRGB function [[#5220](https://github.com/PointCloudLibrary/pcl/pull/5220)]
+* **[ABI break]** constexpr constructors for point types [[#4646](https://github.com/PointCloudLibrary/pcl/pull/4646)]
+* Add `bool`, `std::{u}int64_t` as possible point field types [[#4133](https://github.com/PointCloudLibrary/pcl/pull/4133)]
+
+#### libpcl_cuda:
+
+* Fix build errors [[#5155](https://github.com/PointCloudLibrary/pcl/pull/5155)]
+* Remove `using namespace thrust` [[#5326](https://github.com/PointCloudLibrary/pcl/pull/5326)]
+* Fix linking error for Kinfu [[#5327](https://github.com/PointCloudLibrary/pcl/pull/5327)]
+
+#### libpcl_features:
+
+* **[ABI break]** Add more configuration options to GRSDEstimation [[#4852](https://github.com/PointCloudLibrary/pcl/pull/4852)]
+* Fix segfault executing multiscale feature persistence [[#5109](https://github.com/PointCloudLibrary/pcl/pull/5109)]
+* Remove unnecessary member in SHOTEstimationBase [[#5434](https://github.com/PointCloudLibrary/pcl/pull/5434)]
+
+#### libpcl_filters:
+
+* **[ABI break]** Add `PCL_MAKE_ALIGNED_OPERATOR_NEW` to CropBox for better Eigen support [[#4962](https://github.com/PointCloudLibrary/pcl/pull/4962)]
+* **[API break][ABI break]** applyFilter() made protected [[#4933](https://github.com/PointCloudLibrary/pcl/pull/4933)]
+* Use `-FLT_MAX` instead of `FLT_MIN` for minimum value [[#5119](https://github.com/PointCloudLibrary/pcl/pull/5119)]
+* **[ABI break]** Added region of interest for frustum culling [[#5136](https://github.com/PointCloudLibrary/pcl/pull/5136)]
+* Fix missing definition "boost::optional" [[#5213](https://github.com/PointCloudLibrary/pcl/pull/5213)]
+* Fix CropHull::applyFilter3D() [[#5255](https://github.com/PointCloudLibrary/pcl/pull/5255)]
+* Fix UniformSampling filter by correcting distance calculation to voxel center [[#4328](https://github.com/PointCloudLibrary/pcl/pull/4328)]
+* Fix error due to multiple declarations of template member function specializations in pyramid [[#3973](https://github.com/PointCloudLibrary/pcl/pull/3973)]
+* Fix segfault of NDT for sparse clouds [[#5399](https://github.com/PointCloudLibrary/pcl/pull/5399)]
+* **[new feature]** FrustumCulling: allowing infinite far plane distance [[#5433](https://github.com/PointCloudLibrary/pcl/pull/5433)]
+* **[new feature]** FrustumCulling: asymmetrical Field of View [[#5438](https://github.com/PointCloudLibrary/pcl/pull/5438)]
+* **[new feature]** Add farthest point sampling filter [[#3723](https://github.com/PointCloudLibrary/pcl/pull/3723)]
+* PassThrough: add more checks for field type and name [[#5490](https://github.com/PointCloudLibrary/pcl/pull/5490)]
+
+#### libpcl_gpu:
+
+* **[deprecation]** Use C++11 `std::atomic` instead of non-standard extensions [[#4807](https://github.com/PointCloudLibrary/pcl/pull/4807)]
+* **[deprecation]** Remove hand-rolled `static_assert` [[#4797](https://github.com/PointCloudLibrary/pcl/pull/4797)]
+* Remove `using namespace thrust` [[#5326](https://github.com/PointCloudLibrary/pcl/pull/5326)]
+* Fix linking error for Kinfu [[#5327](https://github.com/PointCloudLibrary/pcl/pull/5327)]
+
+#### libpcl_io:
+
+* **[ABI break]** Introduce buffer for texture coordinate indices in TextureMesh [[#4971](https://github.com/PointCloudLibrary/pcl/pull/4971)]
+* Fix wrong header when saving PolygonMesh to ply file [[#5169](https://github.com/PointCloudLibrary/pcl/pull/5169)]
+* Reimplement boost::split and optimize tokenization [[#5285](https://github.com/PointCloudLibrary/pcl/pull/5285)]
+* Fixes Crash in pcl::PLYReader::amendProperty [[#5331](https://github.com/PointCloudLibrary/pcl/pull/5331)]
+* Fix multiple memory corruption errors revealed by fuzzing [[#5342](https://github.com/PointCloudLibrary/pcl/pull/5342)]
+* **[new feature]** Add empty point cloud support at pcd file. [[#5400](https://github.com/PointCloudLibrary/pcl/pull/5400)]
+* Fix compile issues when compiling OpenNIDriver [[#5452](https://github.com/PointCloudLibrary/pcl/pull/5452)]
+* PCDReader: remove fields with zero count instead of throwing exception while reading [[#4623](https://github.com/PointCloudLibrary/pcl/pull/4623)]
+* PLYReader: Return empty handler if rgb doesn't exist when trying to add alpha value [[#5415](https://github.com/PointCloudLibrary/pcl/pull/5415)]
+
+#### libpcl_keypoints:
+
+* Fix HarrisKeypoint3D::refineCorners [[#5365](https://github.com/PointCloudLibrary/pcl/pull/5365)]
+* Fix OpenMP compile issue under MSVC [[#5453](https://github.com/PointCloudLibrary/pcl/pull/5453)]
+
+#### libpcl_octree:
+
+* getSize: should return 0 when data_ is invalid [[#5352](https://github.com/PointCloudLibrary/pcl/pull/5352)]
+* deleteTree: max_x_ was not reset [[#5353](https://github.com/PointCloudLibrary/pcl/pull/5353)]
+
+#### libpcl_recognition:
+
+* fix quantized normals' bin boundaries not consistent in different places in linemod [[#5464](https://github.com/PointCloudLibrary/pcl/pull/5464)]
+* fix linemod binindex wrong range bug in surface normal modality [[#5444](https://github.com/PointCloudLibrary/pcl/pull/5444)]
+
+#### libpcl_registration:
+
+* Fix doxygen comment blocks in `ndt.h` [[#5080](https://github.com/PointCloudLibrary/pcl/pull/5080)]
+* **[deprecation]** Use likelihood instead of probability in `ndt` [[#5073](https://github.com/PointCloudLibrary/pcl/pull/5073)]
+* fix: use `similarity_threshold_squared_` instead of `cardinality_` in… [[#5236](https://github.com/PointCloudLibrary/pcl/pull/5236)]
+* Fix of IterativeClosestPointWithNormals shared_ptr [[#4438](https://github.com/PointCloudLibrary/pcl/pull/4438)]
+* print loss as debug for TransformationEstimationSVD and TransformationEstimationPointToPlaneLLS [[#5279](https://github.com/PointCloudLibrary/pcl/pull/5279)]
+* add Scalar template variable to RegistrationVisualizer [[#5290](https://github.com/PointCloudLibrary/pcl/pull/5290)]
+* add Scalar template variable to NormalDistributionsTransform [[#5291](https://github.com/PointCloudLibrary/pcl/pull/5291)]
+* add Scalar template variable to GeneralizedIterativeClosestPoint [[#5312](https://github.com/PointCloudLibrary/pcl/pull/5312)]
+* Fix segfault of NDT for sparse clouds [[#5399](https://github.com/PointCloudLibrary/pcl/pull/5399)]
+* Fix can't compile getMeanPointDensity [[#5447](https://github.com/PointCloudLibrary/pcl/pull/5447)]
+* GICP: correct matrix multiplication [[#5489](https://github.com/PointCloudLibrary/pcl/pull/5489)]
+
+#### libpcl_sample_consensus:
+
+* **[ABI break]** Implement `SampleConsensusModelSphere<PointT>::projectPoints` properly [[#5095](https://github.com/PointCloudLibrary/pcl/pull/5095)]
+* **[new feature]** Adds Ellipse3D SacModel Class [[#5512](https://github.com/PointCloudLibrary/pcl/pull/5512)]
+
+#### libpcl_surface:
+
+* Fix mls voxel grid hashing out of bound [[#4973](https://github.com/PointCloudLibrary/pcl/pull/4973)]
+* Fix nonsense code in pcl/surface/3rdparty/poisson4/sparse_matrix.hpp [[#5256](https://github.com/PointCloudLibrary/pcl/pull/5256)]
+* GridProjection: scale output back to original size [[#5301](https://github.com/PointCloudLibrary/pcl/pull/5301)]
+* Solve an internal compiler issue on MSVC 2022 within openNURBS [[#5463](https://github.com/PointCloudLibrary/pcl/pull/5463)]
+* Fix segfault in mls::performUpsampling [[#5483](https://github.com/PointCloudLibrary/pcl/pull/5483)]
+
+#### libpcl_visualization:
+
+* Fix Bug between addText3D and QVTKWidget [[#5054](https://github.com/PointCloudLibrary/pcl/pull/5054)]
+* Change static to const since it-stability is not guaranteed [[#5147](https://github.com/PointCloudLibrary/pcl/pull/5147)]
+* Add missing vtk library for context2d. [[#5160](https://github.com/PointCloudLibrary/pcl/pull/5160)]
+* Fix problem with spin() and spinOnce() for X Window System [[#5252](https://github.com/PointCloudLibrary/pcl/pull/5252)]
+* add Scalar template variable to RegistrationVisualizer [[#5290](https://github.com/PointCloudLibrary/pcl/pull/5290)]
+* Fix PCLVisualizer::addPointCloudPrincipalCurvatures [[#5369](https://github.com/PointCloudLibrary/pcl/pull/5369)]
+* **[new feature]** Add option to enable EDL rendering. [[#4941](https://github.com/PointCloudLibrary/pcl/pull/4941)]
+* Support handling numpad +/- key event for visualizer [[#5468](https://github.com/PointCloudLibrary/pcl/pull/5468)]
+* Fix usage of dangling pointer in PCLVisualizer::getUniqueCameraFile [[#5481](https://github.com/PointCloudLibrary/pcl/pull/5481)]
+* point and area picking improvement for cloud names [[#5476](https://github.com/PointCloudLibrary/pcl/pull/5476)]
+* Access to a potential null pointer in interactor_style (#5503) [[#5507](https://github.com/PointCloudLibrary/pcl/pull/5507)]
+
+#### PCL Apps:
+
+* fix vtk-qt crash on macos for manual_registration app [[#5432](https://github.com/PointCloudLibrary/pcl/pull/5432)]
+* Fix pcd_video_player crash on OSX [[#5421](https://github.com/PointCloudLibrary/pcl/pull/5421)]
+
+#### PCL Tutorials:
+
+* Fix alignment prerejective tutorial [[#5363](https://github.com/PointCloudLibrary/pcl/pull/5363)]
+
+#### PCL Tools:
+
+* Add check in pcd_viewer.cpp for padding fields [[#5442](https://github.com/PointCloudLibrary/pcl/pull/5442)]
+
+#### CI:
+
+* Fix benchmark compilation issue on Ubuntu 21.10 [[#5165](https://github.com/PointCloudLibrary/pcl/pull/5165)]
+* **[new feature]** Add new CI to cover uncommon configurations, running weekly [[#5208](https://github.com/PointCloudLibrary/pcl/pull/5208)]
+* Add clang-tidy in a GitHub workflow [[#4636](https://github.com/PointCloudLibrary/pcl/pull/4636)]
+* Update vcpkg to version 2022.07.25 on x86 windows to fix libharu hash value error. [[#5418](https://github.com/PointCloudLibrary/pcl/pull/5418)]
+* Install openni2 in windows dockers [[#5459](https://github.com/PointCloudLibrary/pcl/pull/5459)]
+
## = 1.12.1 (2021.12.21) =
This minor release brings in a lot of enhancements in CMake thanks to @larshg and @SunBlack.
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.1)
+project(PCL VERSION 1.13.0)
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
### ---[ Find universal dependencies
# Compiler identification
# Define a variable CMAKE_COMPILER_IS_X where X is the compiler short name.
# Note: CMake automatically defines one for GNUCXX, nothing to do in this case.
-if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_COMPILER_IS_CLANG 1)
elseif(__COMPILER_PATHSCALE)
set(CMAKE_COMPILER_IS_PATHSCALE 1)
set(CMAKE_COMPILER_IS_MINGW 1)
endif()
+# https://github.com/fish-shell/fish-shell/issues/5865
+include(CheckCXXSourceCompiles)
+CHECK_CXX_SOURCE_COMPILES("
+#include <atomic>
+struct big { int foo[64]; };
+std::atomic<big> x;
+int main() {
+ return x.load().foo[13];
+}"
+LIBATOMIC_NOT_NEEDED)
+IF (NOT LIBATOMIC_NOT_NEEDED)
+ SET(ATOMIC_LIBRARY "atomic")
+ENDIF()
+
# Create a variable with expected default CXX flags
# This will be used further down the road to check if the user explicitly provided CXX flags
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}")
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} /bigobj")
+ string(APPEND CMAKE_CXX_FLAGS " /fp:precise ${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))
endif()
# /MANIFEST:NO") # please, don't disable manifest generation, otherwise crash at start for vs2008
+ # Disable some warnings
+ string(APPEND CMAKE_CXX_FLAGS " /wd4800 /wd4521 /wd4251 /wd4275 /wd4305 /wd4355")
+
+ # Enable warnings, which are disabled by default (see https://learn.microsoft.com/de-de/cpp/preprocessor/compiler-warnings-that-are-off-by-default)
+ string(APPEND CMAKE_CXX_FLAGS " /w34265")
+
if(PCL_WARNINGS_ARE_ERRORS)
+ # MSVC supports external includes only since Visual Studio 2019 version 16.10.0.
+ # CMake supports external includes since 3.22.0 using the Ninja generator or NMake files (see https://gitlab.kitware.com/cmake/cmake/-/merge_requests/4766)
+ # CMake supports external includes for Visual Studio also since 3.24.0 (see https://gitlab.kitware.com/cmake/cmake/-/merge_requests/7238)
+ if(CMAKE_C_COMPILER_VERSION VERSION_LESS "19.29.30036.3" OR CMAKE_VERSION VERSION_LESS 3.22.0 OR (CMAKE_VERSION VERSION_LESS 3.24.0 AND CMAKE_GENERATOR MATCHES "Visual Studio"))
+ message(WARNING "With the used combination of compiler and CMake version it is not recommended to activate PCL_WARNINGS_ARE_ERRORS, "
+ "because also warnings from 3rd party components are marked as errors. It is recommended to upgrade to "
+ "Visual Studio 2019 version 16.10.0 and CMake 3.24.0 (or CMake 3.22.0 if using Ninja or NMake files).")
+ endif()
string(APPEND CMAKE_CXX_FLAGS " /WX")
endif()
if(OpenMP_FOUND)
string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS " ${OpenMP_CXX_FLAGS}")
- if(${CMAKE_VERSION} VERSION_LESS "3.7")
- message(STATUS "Found OpenMP")
- else()
- # We could use OpenMP_CXX_VERSION starting from CMake 3.9, but this value is only available on first run of CMake (see https://gitlab.kitware.com/cmake/cmake/issues/19150),
- # so we use always OpenMP_CXX_SPEC_DATE, which is available since CMake 3.7.
- message(STATUS "Found OpenMP, spec date ${OpenMP_CXX_SPEC_DATE}")
- endif()
- if(MSVC)
- if(MSVC_VERSION EQUAL 1900)
- set(OPENMP_DLL VCOMP140)
- elseif(MSVC_VERSION MATCHES "^191[0-9]$")
- 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")
- string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /DELAYLOAD:${OPENMP_DLL}.dll")
- else()
- message(WARNING "Delay loading flag for OpenMP DLL is invalid.")
- endif()
+
+ # We could use OpenMP_CXX_VERSION starting from CMake 3.9, but this value is only available on first run of CMake (see https://gitlab.kitware.com/cmake/cmake/issues/19150),
+ # so we use always OpenMP_CXX_SPEC_DATE, which is available since CMake 3.7.
+ message(STATUS "Found OpenMP, spec date ${OpenMP_CXX_SPEC_DATE}")
+
+ if((MSVC_VERSION EQUAL 1900) OR (MSVC_VERSION MATCHES "^191[0-9]$"))
+ string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /DELAYLOAD:VCOMP140D.dll")
+ string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /DELAYLOAD:VCOMP140.dll")
endif()
else()
message(STATUS "Not found OpenMP")
find_package(Threads REQUIRED)
# Eigen (required)
-find_package(Eigen 3.1 REQUIRED)
+find_package(Eigen 3.3 REQUIRED)
include_directories(SYSTEM ${EIGEN_INCLUDE_DIRS})
# FLANN (required)
set(Boost_ADDITIONAL_VERSIONS
"@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@.@Boost_SUBMINOR_VERSION@" "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@"
- "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75"
+ "1.80.0" "1.80"
+ "1.79.0" "1.79" "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")
set(BOOST_INCLUDE_DIRS "${Boost_INCLUDE_DIR}")
set(BOOST_LIBRARY_DIRS "${Boost_LIBRARY_DIRS}")
set(BOOST_LIBRARIES ${Boost_LIBRARIES})
- if(WIN32 AND NOT MINGW)
+ if(WIN32 AND NOT MINGW AND NOT "${BOOST_DEFINITIONS}" MATCHES "BOOST_ALL_NO_LIB")
string(APPEND BOOST_DEFINITIONS -DBOOST_ALL_NO_LIB)
endif()
endmacro()
elseif(NOT EIGEN_ROOT)
get_filename_component(EIGEN_ROOT "@EIGEN_INCLUDE_DIRS@" ABSOLUTE)
endif()
- find_package(Eigen 3.1)
+ find_package(Eigen 3.3)
endmacro()
#remove this as soon as qhull is shipped with FindQhull.cmake
# pcl_message("PCL found into a build tree.")
set(PCL_CONF_INCLUDE_DIR "${PCL_DIR}/include") # for pcl_config.h
set(PCL_LIBRARY_DIRS "${PCL_DIR}/@LIB_INSTALL_DIR@")
- set(PCL_SOURCES_TREE "@CMAKE_SOURCE_DIR@")
else()
pcl_report_not_found("PCL can not be found on this machine")
endif()
pcl/cuda/${cuda_component} pcl/cuda/${component}
pcl/gpu/${gpu_component} pcl/gpu/${component}
HINTS ${PCL_INCLUDE_DIRS}
- "${PCL_SOURCES_TREE}"
PATH_SUFFIXES
${component}/include
apps/${component}/include
string(REGEX REPLACE "^-D" "" def3 "${def2}")
list(APPEND definitions ${def3})
endforeach()
- if(CMAKE_VERSION VERSION_LESS 3.3)
- set_target_properties(${pcl_component}
- PROPERTIES
- INTERFACE_COMPILE_DEFINITIONS "${definitions}"
- INTERFACE_COMPILE_OPTIONS "${PCL_COMPILE_OPTIONS}"
- INTERFACE_COMPILE_FEATURES "@PCL_CXX_COMPILE_FEATURES@"
- INTERFACE_INCLUDE_DIRECTORIES "${PCL_${COMPONENT}_INCLUDE_DIRS};${PCL_CONF_INCLUDE_DIR}"
- INTERFACE_LINK_LIBRARIES "${PCL_${COMPONENT}_LINK_LIBRARIES}"
- )
- elseif(CMAKE_VERSION VERSION_LESS 3.11)
+ if(CMAKE_VERSION VERSION_LESS 3.11)
set_target_properties(${pcl_component}
PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "${definitions}"
[![Release][release-image]][releases]
[![License][license-image]][license]
-[release-image]: https://img.shields.io/badge/release-1.12.1-green.svg?style=flat
+[release-image]: https://img.shields.io/badge/release-1.13.0-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-latest-build]: https://dev.azure.com/PointCloudLibrary/pcl/_build/latest?definitionId=9&branchName=master
[ci-ubuntu-18.04]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20GCC&jobName=Ubuntu&configuration=Ubuntu%2018.04%20GCC&label=Ubuntu%2018.04%20GCC
[ci-ubuntu-20.04]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=Ubuntu&configuration=Ubuntu%2020.04%20Clang&label=Ubuntu%2020.04%20Clang
-[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-ubuntu-22.04]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20GCC&jobName=Ubuntu&configuration=Ubuntu%2022.04%20GCC&label=Ubuntu%2022.04%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-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-macos-12]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Monterey%2012&label=macOS%20Monterey%2012
[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
Build Platform | Status
------------------------ | ------------------------------------------------------------------------------------------------- |
-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] |
+Ubuntu | [![Status][ci-ubuntu-18.04]][ci-latest-build] <br> [![Status][ci-ubuntu-20.04]][ci-latest-build] <br> [![Status][ci-ubuntu-22.04]][ci-latest-build] |
Windows | [![Status][ci-windows-x86]][ci-latest-build] <br> [![Status][ci-windows-x64]][ci-latest-build] |
-macOS | [![Status][ci-macos-10.15]][ci-latest-build] <br> [![Status][ci-macos-11]][ci-latest-build] |
+macOS | [![Status][ci-macos-11]][ci-latest-build] <br> [![Status][ci-macos-12]][ci-latest-build] |
Documentation | [![Status][ci-docs]][ci-latest-docs] |
Community
endif()
PCL_SUBSUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSUBSYS_DEPEND(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" DEPS ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSUBSYS_NAME} PARENT_NAME ${SUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
if(NOT build)
return()
std::vector<CRHPointCloud::Ptr> crh_histograms_;
public:
- CRHEstimation() {}
+ CRHEstimation() = default;
void
setFeatureEstimator(
void
compute(PointInTPtr& keypoints)
{
- if (normals_ == 0 || (normals_->size() != input_->size()))
+ if (normals_ == nullptr || (normals_->size() != input_->size()))
PCL_WARN("SIFTSurfaceKeypointExtractor -- Normals are not valid\n");
keypoints.reset(new pcl::PointCloud<PointInT>);
{
keypoints.reset(new pcl::PointCloud<PointInT>);
- if (normals_ == 0 || (normals_->size() != input_->size()))
+ if (normals_ == nullptr || (normals_->size() != input_->size()))
PCL_WARN("HarrisKeypointExtractor -- Normals are not valid\n");
typename pcl::PointCloud<pcl::PointXYZI>::Ptr intensity_keypoints(
using KeypointExtractor<PointInT>::radius_;
public:
- SUSANKeypointExtractor() {}
+ SUSANKeypointExtractor() = default;
bool
needNormals()
{
keypoints.reset(new pcl::PointCloud<PointInT>);
- if (normals_ == 0 || (normals_->size() != input_->size()))
+ if (normals_ == nullptr || (normals_->size() != input_->size()))
PCL_WARN("SUSANKeypointExtractor -- Normals are not valid\n");
typename pcl::PointCloud<pcl::PointXYZI>::Ptr intensity_keypoints(
pcl::Indices nn_indices(9);
std::vector<float> nn_distances(9);
- float sum_distances = 0.0;
std::vector<float> avg_distances(input->size());
// Iterate through the source data set
for (std::size_t i = 0; i < input->size(); ++i) {
avg_dist_neighbours /= static_cast<float>(nn_indices.size());
avg_distances[i] = avg_dist_neighbours;
- sum_distances += avg_dist_neighbours;
}
- std::sort(avg_distances.begin(), avg_distances.end());
+ // median: nth_element is faster than sorting everything
+ std::nth_element(avg_distances.begin(),
+ avg_distances.begin() + (avg_distances.size() / 2 + 1),
+ avg_distances.end());
float avg = avg_distances[static_cast<int>(avg_distances.size()) / 2 + 1];
return avg;
}
std::shared_ptr<std::vector<ModelT>>
getModels(std::string& model_id)
{
-
- typename std::vector<ModelT>::iterator it = models_->begin();
- while (it != models_->end()) {
- if (model_id != (*it).id_) {
- it = models_->erase(it);
- }
- else {
- it++;
- }
- }
+ models_->erase(std::remove_if(models_->begin(),
+ models_->end(),
+ [=](ModelT& s) { return (s.id_ != model_id); }),
+ models_->end());
return models_;
}
public:
using PointInTPtr = typename pcl::PointCloud<PointInT>::Ptr;
+ virtual ~GlobalClassifier() = default;
+
virtual void
setNN(int nn) = 0;
public:
GlobalNNPipeline() { NN_ = 1; }
- ~GlobalNNPipeline() {}
-
void
setNN(int nn) override
{
do_CRH_ = true;
}
- ~GlobalNNCRHRecognizer() {}
+ ~GlobalNNCRHRecognizer() = default;
void
setNoise(float n)
use_single_categories_ = false;
}
- ~GlobalNNCVFHRecognizer() {}
+ ~GlobalNNCVFHRecognizer() = default;
void
getDescriptorDistances(std::vector<float>& ds)
threshold_accept_model_hypothesis_ = t;
}
- ~LocalRecognitionPipeline() {}
+ ~LocalRecognitionPipeline() = default;
void
setKdtreeSplits(int n)
{
float r = static_cast<float>(uniform_deviate(rand()) * totalArea);
- std::vector<double>::iterator low =
- std::lower_bound(cumulativeAreas->begin(), cumulativeAreas->end(), r);
+ auto low = std::lower_bound(cumulativeAreas->begin(), cumulativeAreas->end(), r);
vtkIdType el = static_cast<vtkIdType>(low - cumulativeAreas->begin());
double A[3], B[3], C[3];
dps.compute_fast(clusters);
dps.getIndicesClusters(indices);
Eigen::Vector4f table_plane_;
+ dps.getTableCoefficients(table_plane_);
Eigen::Vector3f normal_plane_ =
Eigen::Vector3f(table_plane_[0], table_plane_[1], table_plane_[2]);
- dps.getTableCoefficients(table_plane_);
vis.removePointCloud("frame");
vis.addPointCloud<OpenNIFrameSource::PointT>(frame, "frame");
set(DEFAULT FALSE)
set(REASON "Disabled by default")
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${SUBSYS_OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${SUBSYS_OPT_DEPS})
if(NOT build)
return()
endif()
PCL_SUBSUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSUBSYS_DEPEND(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" DEPS ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSUBSYS_NAME} PARENT_NAME ${SUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
PCL_ADD_DOC(${SUBSUBSYS_NAME})
public:
CloudViewer (QWidget* parent = nullptr);
- ~CloudViewer();
ProjectModel* getModel () const;
public Q_SLOTS:
Q_OBJECT
public:
ItemInspector (QWidget* parent = nullptr);
- ~ItemInspector();
public Q_SLOTS:
void
bool make_templated_cloud = true);
CloudItem (const CloudItem& to_copy);
- ~CloudItem ();
/** \brief This creates a CloudItem from a templated cloud type */
template <typename PointT>
const pcl::PointCloud<pcl::FPFHSignature33>::Ptr& fpfh_ptr,
double radius);
FPFHItem (const FPFHItem& to_copy);
- ~FPFHItem ();
inline int
type () const override { return FPFH_ITEM; }
const pcl::PointCloud<pcl::Normal>::Ptr& normals_ptr,
double radius);
NormalsItem (const NormalsItem& to_copy);
- ~NormalsItem ();
inline int
type () const override { return NORMALS_ITEM; }
Q_OBJECT
public:
MergeSelection (QMap <const CloudItem*, pcl::PointIndices::ConstPtr > selected_item_index_map, QObject* parent = nullptr);
- ~MergeSelection ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
vtkTypeMacro(ClickTrackballStyleInteractor,vtkInteractorStyleTrackballActor);
ClickTrackballStyleInteractor ();
-
- ~ClickTrackballStyleInteractor ();
/** \brief Pass a pointer to the actor map
* \param[in] actors the actor map that will be used with this style
vtkTypeMacro(InteractorStyleSwitch, vtkInteractorStyle);
InteractorStyleSwitch();
- ~InteractorStyleSwitch();
void
SetInteractor(vtkRenderWindowInteractor *iren) override;
ManipulationEvent ()
{}
- ~ManipulationEvent ();
-
void
addManipulation (const QString& id, const vtkSmartPointer<vtkMatrix4x4>& start, const vtkSmartPointer<vtkMatrix4x4>& end);
vtkTypeMacro(RectangularFrustumSelector,vtkInteractorStyleRubberBandPick);
RectangularFrustumSelector ();
-
- ~RectangularFrustumSelector ();
/** \brief Pass a pointer to the actor map
* \param[in] actors the actor map that will be used with this style
vtkTypeMacro(SelectedTrackballStyleInteractor,vtkInteractorStyleTrackballActor);
SelectedTrackballStyleInteractor ();
-
- ~SelectedTrackballStyleInteractor ();
/** \brief Pass a pointer to the actor map
* \param[in] actors the actor map that will be used with this style
/** \brief Constructor used for item parameters */
PropertiesModel (CloudComposerItem* parent_item, QObject *parent = nullptr);
PropertiesModel (const PropertiesModel& to_copy);
- ~PropertiesModel ();
/** \brief Helper function for adding a new property */
void
: AbstractTool (parameter_model, parent)
{}
- ~ModifyItemTool () { }
-
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
: AbstractTool (parameter_model, parent)
{}
- ~NewItemTool () { }
-
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
: AbstractTool (parameter_model, parent)
{}
- ~SplitItemTool () { }
-
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
: AbstractTool (parameter_model, parent)
{}
- ~MergeCloudTool () { }
-
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override = 0;
Q_OBJECT
public:
EuclideanClusteringTool (PropertiesModel* parameter_model, QObject* parent);
- ~EuclideanClusteringTool ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
FPFHEstimationTool (PropertiesModel* parameter_model, QObject* parent);
- ~FPFHEstimationTool ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
NormalEstimationTool (PropertiesModel* parameter_model, QObject* parent);
- ~NormalEstimationTool ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
OrganizedSegmentationTool (PropertiesModel* parameter_model, QObject* parent);
- ~OrganizedSegmentationTool ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
SanitizeCloudTool (PropertiesModel* parameter_model, QObject* parent);
- ~SanitizeCloudTool ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
StatisticalOutlierRemovalTool (PropertiesModel* parameter_model, QObject* parent);
- ~StatisticalOutlierRemovalTool ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
SupervoxelsTool (PropertiesModel* parameter_model, QObject* parent);
- ~SupervoxelsTool ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
VoxelGridDownsampleTool (PropertiesModel* parameter_model, QObject* parent);
- ~VoxelGridDownsampleTool ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
TransformClouds (QMap <QString, vtkSmartPointer<vtkMatrix4x4> > transform_map, QObject* parent = nullptr);
- ~TransformClouds ();
QList <CloudComposerItem*>
performAction (QList <const CloudComposerItem*> input_data, PointTypeFlags::PointType type = PointTypeFlags::NONE) override;
Q_OBJECT
public:
WorkQueue (QObject* parent = nullptr);
- ~WorkQueue();
public Q_SLOTS:
void
enqueueNewAction (AbstractTool* new_tool, ConstItemList input_data);
// if (background.canConvert<QBrush> ())
// painter->fillRect (option.rect, background.value<QBrush> ());
- QVariant text_color_variant = index.data (Qt::TextColorRole);
+ QVariant text_color_variant = index.data (Qt::ForegroundRole);
if (text_color_variant.canConvert<QColor> ())
{
QColor text_color = text_color_variant.value<QColor> ();
this, SLOT (modelChanged (int)));
}
-pcl::cloud_composer::CloudViewer::~CloudViewer ()
-{
-
-}
-
void
pcl::cloud_composer::CloudViewer::addModel (ProjectModel* new_model)
{
QList <QStandardItem*> removed = parent_item->takeRow (to_remove_index.row ());
}
//Restore the original items
- QMap <QStandardItem*, QStandardItem*>::iterator itr;
foreach (const CloudComposerItem* item, originals)
{
//Point iterator to the correct spot
// Find doesn't modify parameter so it should accept a const pointer, but it can't be because it is templated to the map type
// So we hack to get around this with a const cast
- itr = removed_to_parent_map_.find (const_cast<CloudComposerItem*> (item));
+ const auto& itr = removed_to_parent_map_.find (const_cast<CloudComposerItem*> (item));
QStandardItem* parent = itr.value ();
QStandardItem* original = itr.key ();
parent->appendRow (original);
addTab (parameter_view_, "Parameters");
-}
-
-pcl::cloud_composer::ItemInspector::~ItemInspector ()
-{
-
}
void
pcl::cloud_composer::CloudComposerItem::~CloudComposerItem ()
{
properties_->deleteLater ();
- qDebug () << "Cloud Composer Item Destructor";
}
pcl::cloud_composer::CloudComposerItem*
return new_item;
}
-pcl::cloud_composer::CloudItem::~CloudItem ()
-{
- qDebug () << "Cloud item destructor";
-}
-
-
void
pcl::cloud_composer::CloudItem::paintView (pcl::visualization::PCLVisualizer::Ptr vis) const
{
return new_item;
}
-pcl::cloud_composer::FPFHItem::~FPFHItem ()
-{
-}
-
QMap <QString, QWidget*>
pcl::cloud_composer::FPFHItem::getInspectorTabs ()
{
return new_item;
}
-pcl::cloud_composer::NormalsItem::~NormalsItem ()
-{
-
-}
-
void
pcl::cloud_composer::NormalsItem::paintView (pcl::visualization::PCLVisualizer::Ptr vis) const
{
}
-pcl::cloud_composer::MergeSelection::~MergeSelection ()
-{
-
-}
-
QList <pcl::cloud_composer::CloudComposerItem*>
pcl::cloud_composer::MergeSelection::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
{
transform_ = vtkSmartPointer<vtkTransform>::New ();
}
-pcl::cloud_composer::ClickTrackballStyleInteractor::~ClickTrackballStyleInteractor ()
-{
-
-}
-
void
pcl::cloud_composer::ClickTrackballStyleInteractor::OnLeftButtonDown ()
{
}
-pcl::cloud_composer::InteractorStyleSwitch::~InteractorStyleSwitch ()
-{
-
-}
-
void
pcl::cloud_composer::InteractorStyleSwitch::initializeInteractorStyles (pcl::visualization::PCLVisualizer::Ptr vis, ProjectModel* model)
{
#include <pcl/apps/cloud_composer/point_selectors/manipulation_event.h>
-pcl::cloud_composer::ManipulationEvent::~ManipulationEvent ()
-{
- //TODO Delete manipulated actor here?
-
-}
-
void
pcl::cloud_composer::ManipulationEvent::addManipulation (const QString& id, const vtkSmartPointer<vtkMatrix4x4>& start, const vtkSmartPointer<vtkMatrix4x4>& end)
{
selection_complete_event_ = interactor_events::SELECTION_COMPLETE_EVENT;
}
-pcl::cloud_composer::RectangularFrustumSelector::~RectangularFrustumSelector ()
-{
-
-}
-
-
void
pcl::cloud_composer::RectangularFrustumSelector::OnLeftButtonUp ()
{
manipulation_complete_event_ = interactor_events::MANIPULATION_COMPLETE_EVENT;
}
-pcl::cloud_composer::SelectedTrackballStyleInteractor::~SelectedTrackballStyleInteractor ()
-{
-
-}
-
void
pcl::cloud_composer::SelectedTrackballStyleInteractor::setSelectedActors ()
{
foreach (CloudItem* selected_item, selected_item_index_map_.keys())
{
qDebug () << "Setting item color back to black";
- selected_item->setForeground (QBrush (Qt::black));;
+ selected_item->setForeground (QBrush (Qt::black));
}
selected_item_index_map_.clear ();
//Set all point selected cloud items back to green text, since if they are selected they get changed to white
foreach (CloudItem* selected_item, selected_item_index_map_.keys())
{
- selected_item->setForeground (QBrush (Qt::green));;
+ selected_item->setForeground (QBrush (Qt::green));
}
}
void
pcl::cloud_composer::ProjectModel::setSelectedStyle (interactor_styles::INTERACTOR_STYLES style)
{
- QMap<interactor_styles::INTERACTOR_STYLES, bool>::iterator itr = selected_style_map_.begin();
+ auto itr = selected_style_map_.begin();
while (itr != selected_style_map_.end ())
{
itr.value() = false;
}
}
-pcl::cloud_composer::PropertiesModel::~PropertiesModel ()
-{
-}
-
void
pcl::cloud_composer::PropertiesModel::addProperty (const QString& prop_name, const QVariant& value, Qt::ItemFlags flags, const QString& category)
{
else if ( ! type_items_map.keys ().contains (input_type))
{
enabled_itr.remove ();
- disabled_tools.insert (tool_item, tr("Tool Requires item type %1 selected").arg (ITEM_TYPES_STRINGS.value (input_type - QStandardItem::UserType)));
+ disabled_tools.insert (tool_item, tr("Tool Requires item type %1 selected").arg (ITEM_TYPES_STRINGS.value (input_type - CloudComposerItem::CLOUD_COMPOSER_ITEM)));
}
//Check if any of selected items have required children
else if ( !required_children_types.empty ())
enabled_itr.remove ();
QString missing_children_string;
foreach (CloudComposerItem::ItemType type, missing_children)
- missing_children_string.append (" "+ITEM_TYPES_STRINGS.value (type - QStandardItem::UserType));
+ missing_children_string.append (" "+ITEM_TYPES_STRINGS.value (type - CloudComposerItem::CLOUD_COMPOSER_ITEM));
disabled_tools.insert (tool_item, tr ("Tool Requires child item of type(s) %1").arg (missing_children_string));
}
}
}
-pcl::cloud_composer::TransformClouds::~TransformClouds ()
-{
-
-}
-
QList <pcl::cloud_composer::CloudComposerItem*>
pcl::cloud_composer::TransformClouds::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
{
-}
-
-
-pcl::cloud_composer::WorkQueue::~WorkQueue ( )
-{
-
-
}
void
}
-pcl::cloud_composer::EuclideanClusteringTool::~EuclideanClusteringTool ()
-{
-
-}
-
QList <pcl::cloud_composer::CloudComposerItem*>
pcl::cloud_composer::EuclideanClusteringTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
{
qDebug () << "Found "<<cluster_indices.size ()<<" clusters!";
int cluster_count = 0;
pcl::ExtractIndices<pcl::PCLPointCloud2> filter;
- for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
+ for (const auto& cluster : cluster_indices)
{
filter.setInputCloud (input_cloud);
// It's annoying that I have to do this, but Euclidean returns a PointIndices struct
- pcl::PointIndices::ConstPtr indices_ptr = pcl::make_shared<pcl::PointIndices>(*it);
+ pcl::PointIndices::ConstPtr indices_ptr = pcl::make_shared<pcl::PointIndices>(cluster);
filter.setIndices (indices_ptr);
- extracted_indices->insert (extracted_indices->end (), it->indices.begin (), it->indices.end ());
+ extracted_indices->insert (extracted_indices->end (), cluster.indices.begin (), cluster.indices.end ());
//This means remove the other points
filter.setKeepOrganized (false);
pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2);
{
-}
-
-pcl::cloud_composer::FPFHEstimationTool::~FPFHEstimationTool ()
-{
-
}
QList <pcl::cloud_composer::CloudComposerItem*>
{
-}
-
-pcl::cloud_composer::NormalEstimationTool::~NormalEstimationTool ()
-{
-
}
QList <pcl::cloud_composer::CloudComposerItem*>
}
-pcl::cloud_composer::OrganizedSegmentationTool::~OrganizedSegmentationTool ()
-{
-
-}
-
QList <pcl::cloud_composer::CloudComposerItem*>
pcl::cloud_composer::OrganizedSegmentationTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
{
{
}
-pcl::cloud_composer::SanitizeCloudTool::~SanitizeCloudTool ()
-{
-}
-
QList <pcl::cloud_composer::CloudComposerItem*>
pcl::cloud_composer::SanitizeCloudTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
{
{
-}
-
-pcl::cloud_composer::StatisticalOutlierRemovalTool::~StatisticalOutlierRemovalTool ()
-{
-
}
QList <pcl::cloud_composer::CloudComposerItem*>
}
-pcl::cloud_composer::SupervoxelsTool::~SupervoxelsTool ()
-{
-
-}
-
QList <pcl::cloud_composer::CloudComposerItem*>
pcl::cloud_composer::SupervoxelsTool::performAction (ConstItemList input_data, PointTypeFlags::PointType type)
{
{
-}
-
-pcl::cloud_composer::VoxelGridDownsampleTool::~VoxelGridDownsampleTool ()
-{
-
}
QList <pcl::cloud_composer::CloudComposerItem*>
set(DEFAULT FALSE)
endif()
-pcl_subsubsys_option(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-pcl_subsubsys_depend(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
+pcl_subsubsys_option(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" ${DEFAULT} "${REASON}")
+PCL_SUBSYS_DEPEND(build NAME ${SUBSUBSYS_NAME} PARENT_NAME ${SUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
pcl_add_doc("${SUBSUBSYS_NAME}")
#pragma once
#ifdef __GNUC__
-# pragma GCC system_header
+#pragma GCC system_header
#endif
PCL_DEPRECATED_HEADER(1, 15, "Please include the needed boost headers directly.")
#include <boost/math/special_functions/fpclassify.hpp>
#pragma once
-#include <cstdint>
-
+#include <pcl/geometry/triangle_mesh.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
-#include <pcl/geometry/triangle_mesh.h>
-namespace pcl
-{
- namespace ihs
- {
- struct PointIHS;
- using CloudIHS = pcl::PointCloud<PointIHS>;
- using CloudIHSPtr = CloudIHS::Ptr;
- using CloudIHSConstPtr = CloudIHS::ConstPtr;
- } // End namespace ihs
+#include <cstdint>
+
+namespace pcl {
+namespace ihs {
+struct PointIHS;
+using CloudIHS = pcl::PointCloud<PointIHS>;
+using CloudIHSPtr = CloudIHS::Ptr;
+using CloudIHSConstPtr = CloudIHS::ConstPtr;
+} // End namespace ihs
} // End namespace pcl
#include <pcl/apps/in_hand_scanner/impl/common_types.hpp>
-POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::ihs::_PointIHS,
- (float, x, x)
- (float, y, y)
- (float, z, z)
- (float, normal_x, normal_x)
- (float, normal_y, normal_y)
- (float, normal_z, normal_z)
- (float, rgb, rgb)
- (float, weight, weight)
- (unsigned int, age, age)
- (std::uint32_t, directions, directions)
- )
-POINT_CLOUD_REGISTER_POINT_WRAPPER (pcl::ihs::PointIHS, pcl::ihs::_PointIHS)
+// clang-format off
+POINT_CLOUD_REGISTER_POINT_STRUCT(pcl::ihs::_PointIHS,
+ (float, x, x)
+ (float, y, y)
+ (float, z, z)
+ (float, normal_x, normal_x)
+ (float, normal_y, normal_y)
+ (float, normal_z, normal_z)
+ (float, rgb, rgb)
+ (float, weight, weight)
+ (unsigned int, age, age)
+ (std::uint32_t, directions, directions)
+ )
+POINT_CLOUD_REGISTER_POINT_WRAPPER(pcl::ihs::PointIHS, pcl::ihs::_PointIHS)
+// clang-format on
-namespace pcl
-{
- namespace ihs
- {
- struct MeshTraits
- {
- using VertexData = PointIHS;
- using HalfEdgeData = pcl::geometry::NoData;
- using EdgeData = pcl::geometry::NoData;
- using FaceData = pcl::geometry::NoData;
- using IsManifold = std::true_type;
- };
+namespace pcl {
+namespace ihs {
+struct MeshTraits {
+ using VertexData = PointIHS;
+ using HalfEdgeData = pcl::geometry::NoData;
+ using EdgeData = pcl::geometry::NoData;
+ using FaceData = pcl::geometry::NoData;
+ using IsManifold = std::true_type;
+};
- // NOTE: The drawMesh method in pcl::ihs::InHandScanner only supports triangles!
- using Mesh = pcl::geometry::TriangleMesh<MeshTraits>;
- using MeshPtr = Mesh::Ptr;
- using MeshConstPtr = Mesh::ConstPtr;
- } // End namespace ihs
+// NOTE: The drawMesh method in pcl::ihs::InHandScanner only supports triangles!
+using Mesh = pcl::geometry::TriangleMesh<MeshTraits>;
+using MeshPtr = Mesh::Ptr;
+using MeshConstPtr = Mesh::ConstPtr;
+} // End namespace ihs
} // End namespace pcl
#pragma once
#ifdef __GNUC__
-# pragma GCC system_header
+#pragma GCC system_header
#endif
PCL_DEPRECATED_HEADER(1, 15, "Please include the needed eigen headers directly.")
+#include <Eigen/Cholesky>
#include <Eigen/Core>
#include <Eigen/Geometry>
-#include <Eigen/Cholesky>
#include <QDialog>
-namespace Ui
-{
- class HelpWindow;
+namespace Ui {
+class HelpWindow;
}
-namespace pcl
-{
- namespace ihs
- {
- class HelpWindow : public QDialog
- {
- Q_OBJECT
+namespace pcl {
+namespace ihs {
+class HelpWindow : public QDialog {
+ Q_OBJECT
- public:
- explicit HelpWindow (QWidget* parent = nullptr);
- ~HelpWindow ();
+public:
+ explicit HelpWindow(QWidget* parent = nullptr);
+ ~HelpWindow() override;
- private:
- Ui::HelpWindow* ui;
- };
- } // End namespace ihs
+private:
+ Ui::HelpWindow* ui;
+};
+} // End namespace ihs
} // End namespace pcl
#pragma once
-#include <pcl/pcl_exports.h>
#include <pcl/apps/in_hand_scanner/common_types.h>
#include <pcl/kdtree/kdtree.h>
+#include <pcl/pcl_exports.h>
////////////////////////////////////////////////////////////////////////////////
// ICP
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- namespace ihs
- {
- /** \brief Iterative Closest Point registration.
- * \author Martin Saelzle
- * \ingroup apps
- */
- class PCL_EXPORTS ICP
- {
- public:
-
- using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
- using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
- using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
- using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
-
- using Mesh = pcl::ihs::Mesh;
- using MeshPtr = pcl::ihs::MeshPtr;
- using MeshConstPtr = pcl::ihs::MeshConstPtr;
-
- /** \brief Constructor */
- ICP ();
-
- /** @{ */
- /** \brief Convergence is detected when the change of the fitness between the current and previous iteration becomes smaller than the given epsilon (set in cm^2). The fitness is the mean squared euclidean distance between corresponding points.
- * \note Only accepted if it is greater than 0.
- */
- void
- setEpsilon (const float epsilon);
-
- float
- getEpsilon () const;
- /** @} */
-
- /** @{ */
- /** \brief The registration fails if the number of iterations exceeds the maximum number of iterations.
- * \note Must be greater than 0. Smaller values are set to 1.
- */
- void
- setMaxIterations (const unsigned int max_iter);
-
- unsigned int
- getMaxIterations () const;
- /** @} */
-
- /** @{ */
- /** \brief The registration fails at the state of convergence if the overlap between the model and data shape is smaller than a minimum overlap. The overlap is the fraction of correspondences (after rejection) to the initial number of data points.
- * \note Must be between zero and one. Values outside this range are clamped to the nearest valid value.
- */
- void
- setMinOverlap (const float overlap);
-
- float
- getMinOverlap () const;
- /** @} */
-
- /** @{ */
- /** \brief The registration fails at the state of convergence if the fitness is bigger than this threshold (set in cm^2)
- * \note Must be greater than zero.
- */
- void
- setMaxFitness (const float fitness);
-
- float
- getMaxFitness () const;
- /** @} */
-
- /** @{ */
- /** \brief Correspondences are rejected if the squared distance is above a threshold. This threshold is initialized with infinity (all correspondences are accepted in the first iteration). The threshold of the next iterations is set to the fitness of the current iteration multiplied by the factor set by this method.
- * \note Must be greater or equal one. Smaller values are set to one.
- */
- void
- setCorrespondenceRejectionFactor (const float factor);
-
- float
- getCorrespondenceRejectionFactor () const;
- /** @} */
-
- /** @{ */
- /** \brief Correspondences are rejected if the angle between the normals is bigger than this threshold. Set in degrees.
- * \note Must be between 180 degrees and 0. Values outside this range are clamped to the nearest valid value.
- */
- void
- setMaxAngle (const float angle);
-
- float
- getMaxAngle () const;
- /** @} */
-
- /** \brief Find the transformation that aligns the data cloud (source) to the model mesh (target).
- * \param[in] mesh_model Model mesh (target).
- * \param[in] cloud_data Data cloud (source).
- * \param[in] T_init Initial guess for the transformation.
- * \paran[out] T_final The computed transformation.
- * \return true if success.
- */
- bool
- findTransformation (const MeshConstPtr& mesh_model,
- const CloudXYZRGBNormalConstPtr& cloud_data,
- const Eigen::Matrix4f& T_init,
- Eigen::Matrix4f& T_final);
-
- private:
-
- using PointNormal = pcl::PointNormal;
- using CloudNormal = pcl::PointCloud<PointNormal>;
- using CloudNormalPtr = CloudNormal::Ptr;
- using CloudNormalConstPtr = CloudNormal::ConstPtr;
-
- using KdTree = pcl::KdTree<PointNormal>;
- using KdTreePtr = KdTree::Ptr;
- using KdTreeConstPtr = KdTree::ConstPtr;
-
- /** \brief Selects the model points that are pointing towards to the camera (data coordinate system = camera coordinate system).
- * \param[in] mesh_model Input mesh.
- * \param[in] T_inv Transformation that brings the model mesh into the camera coordinate system.
- * \return Cloud containing the selected points (the connectivity information of the mesh is currently not used during the registration).
- */
- CloudNormalConstPtr
- selectModelPoints (const MeshConstPtr& mesh_model,
- const Eigen::Matrix4f& T_inv) const;
-
- /** \brief Selects the valid data points. The input cloud is organized -> contains nans which are removed
- * \param[in] cloud_data Input cloud.
- * \return Cloud containing the selected points.
- */
- CloudNormalConstPtr
- selectDataPoints (const CloudXYZRGBNormalConstPtr& cloud_data) const;
-
- /** \brief Finds the transformation that minimizes the point to plane distance from the source to the target cloud. The input clouds must be arranged to have one to one correspondences (point 0 in source corresponds to point 0 in target, point 1 in source to point 1 in target and so on).
- * \param[in] cloud_source Source cloud (data).
- * \param[in] cloud_target Target cloud (model).
- * \param[out] T The computed transformation.
- * \return true if success
- */
- bool
- minimizePointPlane (const CloudNormal& cloud_source,
- const CloudNormal& cloud_target,
- Eigen::Matrix4f& T) const;
-
- ////////////////////////////////////////////////////////////////////////
- // Members
- ////////////////////////////////////////////////////////////////////////
-
- KdTreePtr kd_tree_;
-
- // Convergence
- float epsilon_; // in cm^2
-
- // Registration failure
- unsigned int max_iterations_;
- float min_overlap_; // [0 1]
- float max_fitness_; // in cm^2
-
- // Correspondence rejection
- float factor_;
- float max_angle_; // in degrees
- };
- } // End namespace ihs
+namespace pcl {
+namespace ihs {
+/** \brief Iterative Closest Point registration.
+ * \author Martin Saelzle
+ * \ingroup apps
+ */
+class PCL_EXPORTS ICP {
+public:
+ using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
+ using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
+ using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
+ using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
+
+ using Mesh = pcl::ihs::Mesh;
+ using MeshPtr = pcl::ihs::MeshPtr;
+ using MeshConstPtr = pcl::ihs::MeshConstPtr;
+
+ /** \brief Constructor */
+ ICP();
+
+ /** @{ */
+ /** \brief Convergence is detected when the change of the fitness between the current
+ * and previous iteration becomes smaller than the given epsilon (set in cm^2). The
+ * fitness is the mean squared euclidean distance between corresponding points.
+ *
+ * \note Only accepted if it is greater than 0.
+ */
+ void
+ setEpsilon(const float epsilon);
+
+ float
+ getEpsilon() const;
+ /** @} */
+
+ /** @{ */
+ /** \brief The registration fails if the number of iterations exceeds the maximum
+ * number of iterations.
+ *
+ * \note Must be greater than 0. Smaller values are set to 1.
+ */
+ void
+ setMaxIterations(const unsigned int max_iter);
+
+ unsigned int
+ getMaxIterations() const;
+ /** @} */
+
+ /** @{ */
+ /** \brief The registration fails at the state of convergence if the overlap between
+ * the model and data shape is smaller than a minimum overlap. The overlap is the
+ * fraction of correspondences (after rejection) to the initial number of data points.
+ *
+ * \note Must be between zero and one. Values outside this range are clamped to the
+ * nearest valid value.
+ */
+ void
+ setMinOverlap(const float overlap);
+
+ float
+ getMinOverlap() const;
+ /** @} */
+
+ /** @{ */
+ /** \brief The registration fails at the state of convergence if the fitness is bigger
+ * than this threshold (set in cm^2)
+ *
+ * \note Must be greater than zero.
+ */
+ void
+ setMaxFitness(const float fitness);
+
+ float
+ getMaxFitness() const;
+ /** @} */
+
+ /** @{ */
+ /** \brief Correspondences are rejected if the squared distance is above a threshold.
+ * This threshold is initialized with infinity (all correspondences are accepted in
+ * the first iteration). The threshold of the next iterations is set to the fitness of
+ * the current iteration multiplied by the factor set by this method.
+ *
+ * \note Must be greater or equal one. Smaller values are set to one.
+ */
+ void
+ setCorrespondenceRejectionFactor(const float factor);
+
+ float
+ getCorrespondenceRejectionFactor() const;
+ /** @} */
+
+ /** @{ */
+ /** \brief Correspondences are rejected if the angle between the normals is bigger
+ * than this threshold. Set in degrees.
+ *
+ * \note Must be between 180 degrees and 0. Values outside this range are clamped to
+ * the nearest valid value.
+ */
+ void
+ setMaxAngle(const float angle);
+
+ float
+ getMaxAngle() const;
+ /** @} */
+
+ /** \brief Find the transformation that aligns the data cloud (source) to the model
+ * mesh (target).
+ *
+ * \param[in] mesh_model Model mesh (target).
+ * \param[in] cloud_data Data cloud (source).
+ * \param[in] T_init Initial guess for the transformation.
+ * \param[out] T_final The computed transformation.
+ *
+ * \return true if success.
+ */
+ bool
+ findTransformation(const MeshConstPtr& mesh_model,
+ const CloudXYZRGBNormalConstPtr& cloud_data,
+ const Eigen::Matrix4f& T_init,
+ Eigen::Matrix4f& T_final);
+
+private:
+ using PointNormal = pcl::PointNormal;
+ using CloudNormal = pcl::PointCloud<PointNormal>;
+ using CloudNormalPtr = CloudNormal::Ptr;
+ using CloudNormalConstPtr = CloudNormal::ConstPtr;
+
+ using KdTree = pcl::KdTree<PointNormal>;
+ using KdTreePtr = KdTree::Ptr;
+ using KdTreeConstPtr = KdTree::ConstPtr;
+
+ /** \brief Selects the model points that are pointing towards to the camera (data
+ * coordinate system = camera coordinate system).
+ *
+ * \param[in] mesh_model Input mesh.
+ * \param[in] T_inv Transformation that brings the model mesh into the camera
+ * coordinate system.
+ *
+ * \return Cloud containing the selected points (the connectivity
+ * information of the mesh is currently not used during the registration).
+ */
+ CloudNormalConstPtr
+ selectModelPoints(const MeshConstPtr& mesh_model, const Eigen::Matrix4f& T_inv) const;
+
+ /** \brief Selects the valid data points. The input cloud is organized -> contains
+ * nans which are removed
+ *
+ * \param[in] cloud_data Input cloud.
+ *
+ * \return Cloud containing the selected points.
+ */
+ CloudNormalConstPtr
+ selectDataPoints(const CloudXYZRGBNormalConstPtr& cloud_data) const;
+
+ /** \brief Finds the transformation that minimizes the point to plane distance from
+ * the source to the target cloud. The input clouds must be arranged to have one to
+ * one correspondences (point 0 in source corresponds to point 0 in target, point 1 in
+ * source to point 1 in target and so on).
+ *
+ * \param[in] cloud_source Source cloud (data).
+ * \param[in] cloud_target Target cloud (model).
+ * \param[out] T The computed transformation.
+ *
+ * \return true if success
+ */
+ bool
+ minimizePointPlane(const CloudNormal& cloud_source,
+ const CloudNormal& cloud_target,
+ Eigen::Matrix4f& T) const;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Members
+ ////////////////////////////////////////////////////////////////////////
+
+ KdTreePtr kd_tree_;
+
+ // Convergence
+ float epsilon_; // in cm^2
+
+ // Registration failure
+ unsigned int max_iterations_;
+ float min_overlap_; // [0 1]
+ float max_fitness_; // in cm^2
+
+ // Correspondence rejection
+ float factor_;
+ float max_angle_; // in degrees
+};
+} // End namespace ihs
} // End namespace pcl
#ifndef PCL_APPS_IN_HAND_SCANNER_IMPL_COMMON_TYPES_HPP
#define PCL_APPS_IN_HAND_SCANNER_IMPL_COMMON_TYPES_HPP
-#include <limits>
-
#include <pcl/memory.h>
#include <pcl/pcl_macros.h>
-namespace pcl
-{
- namespace ihs
+#include <limits>
+
+namespace pcl {
+namespace ihs {
+struct EIGEN_ALIGN16 _PointIHS {
+ PCL_ADD_POINT4D
+ PCL_ADD_NORMAL4D
+ PCL_ADD_RGB
+ float weight;
+ unsigned int age;
+ std::uint32_t directions;
+
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+struct PointIHS : public pcl::ihs::_PointIHS {
+ // NOTE: I rely on NaN in the default constructor!
+ inline PointIHS()
+ {
+ this->x = this->y = this->z = std::numeric_limits<float>::quiet_NaN();
+ this->data[3] = 1.f;
+
+ this->normal_x = this->normal_y = this->normal_z =
+ std::numeric_limits<float>::quiet_NaN();
+ this->data_n[3] = 0.f;
+
+ this->b = this->g = this->r = 0;
+ this->a = 255;
+
+ this->weight = 0.f;
+ this->age = 0;
+ this->directions = 0;
+ }
+
+ inline PointIHS(const PointIHS& other)
{
- struct EIGEN_ALIGN16 _PointIHS
- {
- PCL_ADD_POINT4D
- PCL_ADD_NORMAL4D
- PCL_ADD_RGB
- float weight;
- unsigned int age;
- std::uint32_t directions;
-
- PCL_MAKE_ALIGNED_OPERATOR_NEW
- };
-
- struct PointIHS : public pcl::ihs::_PointIHS
- {
- // NOTE: I rely on NaN in the default constructor!
- inline PointIHS ()
- {
- this->x = this->y = this->z = std::numeric_limits<float>::quiet_NaN ();
- this->data[3] = 1.f;
-
- this->normal_x = this->normal_y = this->normal_z = std::numeric_limits<float>::quiet_NaN ();
- this->data_n[3] = 0.f;
-
- this->b = this->g = this->r = 0; this->a = 255;
-
- this->weight = 0.f;
- this->age = 0;
- this->directions = 0;
- }
-
- inline PointIHS (const PointIHS& other)
- {
- this->x = other.x;
- this->y = other.y;
- this->z = other.z;
- this->data[3] = other.data[3];
-
- this->normal_x = other.normal_x;
- this->normal_y = other.normal_y;
- this->normal_z = other.normal_z;
- this->data_n[3] = other.data_n[3];
-
- this->rgba = other.rgba;
-
- this->weight = other.weight;
- this->age = other.age;
- this->directions = other.directions;
- }
-
- inline PointIHS& operator=(const PointIHS& other) = default;
-
- inline PointIHS (const pcl::PointXYZRGBNormal& other, const float weight)
- {
- this->x = other.x;
- this->y = other.y;
- this->z = other.z;
- this->data[3] = other.data[3];
-
- this->normal_x = other.normal_x;
- this->normal_y = other.normal_y;
- this->normal_z = other.normal_z;
- this->data_n[3] = other.data_n[3];
-
- this->rgba = other.rgba;
-
- this->weight = weight;
- this->age = 0;
- this->directions = 0;
- }
-
- // inline Eigen::Vector3i getRGBVector3i () {return (Eigen::Vector3i (r, g, b));}
- inline const Eigen::Vector3i getRGBVector3i () const {return (Eigen::Vector3i (r, g, b));}
- // inline Eigen::Vector4i getRGBVector4i () {return (Eigen::Vector4i (r, g, b, a));}
- inline const Eigen::Vector4i getRGBVector4i () const {return (Eigen::Vector4i (r, g, b, a));}
- };
-
- } // End namespace ihs
+ this->x = other.x;
+ this->y = other.y;
+ this->z = other.z;
+ this->data[3] = other.data[3];
+
+ this->normal_x = other.normal_x;
+ this->normal_y = other.normal_y;
+ this->normal_z = other.normal_z;
+ this->data_n[3] = other.data_n[3];
+
+ this->rgba = other.rgba;
+
+ this->weight = other.weight;
+ this->age = other.age;
+ this->directions = other.directions;
+ }
+
+ inline PointIHS&
+ operator=(const PointIHS& other) = default;
+
+ inline PointIHS(const pcl::PointXYZRGBNormal& other, const float weight)
+ {
+ this->x = other.x;
+ this->y = other.y;
+ this->z = other.z;
+ this->data[3] = other.data[3];
+
+ this->normal_x = other.normal_x;
+ this->normal_y = other.normal_y;
+ this->normal_z = other.normal_z;
+ this->data_n[3] = other.data_n[3];
+
+ this->rgba = other.rgba;
+
+ this->weight = weight;
+ this->age = 0;
+ this->directions = 0;
+ }
+
+ inline const Eigen::Vector3i
+ getRGBVector3i() const
+ {
+ return (Eigen::Vector3i(r, g, b));
+ }
+
+ inline const Eigen::Vector4i
+ getRGBVector4i() const
+ {
+ return (Eigen::Vector4i(r, g, b, a));
+ }
+};
+
+} // End namespace ihs
} // End namespace pcl
#endif // PCL_APPS_IN_HAND_SCANNER_IMPL_COMMON_TYPES_HPP
#pragma once
+#include <pcl/apps/in_hand_scanner/common_types.h>
+#include <pcl/apps/in_hand_scanner/opengl_viewer.h>
#include <pcl/memory.h>
#include <pcl/pcl_exports.h>
#include <pcl/pcl_macros.h>
-#include <pcl/apps/in_hand_scanner/common_types.h>
-#include <pcl/apps/in_hand_scanner/opengl_viewer.h>
+
#include <boost/signals2/connection.hpp> // for connection
+
+#include <iomanip>
#include <mutex>
-#include <string>
#include <sstream>
-#include <iomanip>
+#include <string>
////////////////////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- class OpenNIGrabber;
+namespace pcl {
+class OpenNIGrabber;
- namespace ihs
- {
- class ICP;
- class InputDataProcessing;
- class Integration;
- class MeshProcessing;
- } // End namespace ihs
+namespace ihs {
+class ICP;
+class InputDataProcessing;
+class Integration;
+class MeshProcessing;
+} // End namespace ihs
} // End namespace pcl
////////////////////////////////////////////////////////////////////////////////
// InHandScanner
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- namespace ihs
+namespace pcl {
+namespace ihs {
+/** \brief
+ * \todo Add Documentation
+ */
+class PCL_EXPORTS InHandScanner : public pcl::ihs::OpenGLViewer {
+ Q_OBJECT
+
+public:
+ using Base = pcl::ihs::OpenGLViewer;
+ using Self = pcl::ihs::InHandScanner;
+
+ using InputDataProcessing = pcl::ihs::InputDataProcessing;
+ using InputDataProcessingPtr = std::shared_ptr<InputDataProcessing>;
+ using InputDataProcessingConstPtr = std::shared_ptr<const InputDataProcessing>;
+
+ using ICP = pcl::ihs::ICP;
+ using ICPPtr = std::shared_ptr<ICP>;
+ using ICPConstPtr = std::shared_ptr<const ICP>;
+
+ using Integration = pcl::ihs::Integration;
+ using IntegrationPtr = std::shared_ptr<Integration>;
+ using IntegrationConstPtr = std::shared_ptr<const Integration>;
+
+ using MeshProcessing = pcl::ihs::MeshProcessing;
+ using MeshProcessingPtr = std::shared_ptr<MeshProcessing>;
+ using MeshProcessingConstPtr = std::shared_ptr<const MeshProcessing>;
+
+ /** \brief Switch between different branches of the scanning pipeline. */
+ enum RunningMode {
+ RM_SHOW_MODEL = 0, /**< Shows the model shape (if it is available). */
+ RM_UNPROCESSED = 1, /**< Shows the unprocessed input data. */
+ RM_PROCESSED = 2, /**< Shows the processed input data. */
+ RM_REGISTRATION_CONT =
+ 3, /**< Registers new data to the first acquired data continuously. */
+ RM_REGISTRATION_SINGLE =
+ 4 /**< Registers new data once and returns to showing the processed data. */
+ };
+
+ /** \brief File type for saving and loading files. */
+ enum FileType {
+ FT_PLY = 0, /**< Polygon File Format. */
+ FT_VTK = 1 /**< VTK File Format. */
+ };
+
+ /** \brief Constructor. */
+ explicit InHandScanner(Base* parent = nullptr);
+
+ /** \brief Destructor. */
+ ~InHandScanner() override;
+
+ /** \brief Get the input data processing. */
+ inline InputDataProcessing&
+ getInputDataProcessing()
{
- /** \brief
- * \todo Add Documentation
- */
- class PCL_EXPORTS InHandScanner : public pcl::ihs::OpenGLViewer
- {
- Q_OBJECT
-
- public:
-
- using Base = pcl::ihs::OpenGLViewer;
- using Self = pcl::ihs::InHandScanner;
-
- using InputDataProcessing = pcl::ihs::InputDataProcessing;
- using InputDataProcessingPtr = std::shared_ptr<InputDataProcessing>;
- using InputDataProcessingConstPtr = std::shared_ptr<const InputDataProcessing>;
-
- using ICP = pcl::ihs::ICP;
- using ICPPtr = std::shared_ptr<ICP>;
- using ICPConstPtr = std::shared_ptr<const ICP>;
-
- using Integration = pcl::ihs::Integration;
- using IntegrationPtr = std::shared_ptr<Integration>;
- using IntegrationConstPtr = std::shared_ptr<const Integration>;
-
- using MeshProcessing = pcl::ihs::MeshProcessing;
- using MeshProcessingPtr = std::shared_ptr<MeshProcessing>;
- using MeshProcessingConstPtr = std::shared_ptr<const MeshProcessing>;
-
- /** \brief Switch between different branches of the scanning pipeline. */
- enum RunningMode
- {
- RM_SHOW_MODEL = 0, /**< Shows the model shape (if it is available). */
- RM_UNPROCESSED = 1, /**< Shows the unprocessed input data. */
- RM_PROCESSED = 2, /**< Shows the processed input data. */
- RM_REGISTRATION_CONT = 3, /**< Registers new data to the first acquired data continuously. */
- RM_REGISTRATION_SINGLE = 4 /**< Registers new data once and returns to showing the processed data. */
- };
-
- /** \brief File type for saving and loading files. */
- enum FileType
- {
- FT_PLY = 0, /**< Polygon File Format. */
- FT_VTK = 1 /**< VTK File Format. */
- };
-
- /** \brief Constructor. */
- explicit InHandScanner (Base* parent=nullptr);
-
- /** \brief Destructor. */
- ~InHandScanner ();
-
- /** \brief Get the input data processing. */
- inline InputDataProcessing&
- getInputDataProcessing () {return (*input_data_processing_);}
-
- /** \brief Get the registration. */
- inline ICP&
- getICP () {return (*icp_);}
-
- /** \brief Get the integration. */
- inline Integration&
- getIntegration () {return (*integration_);}
-
- Q_SIGNALS:
-
- /** \brief Emitted when the running mode changes. */
- void
- runningModeChanged (RunningMode new_running_mode) const;
-
- public Q_SLOTS:
-
- /** \brief Start the grabber (enables the scanning pipeline). */
- void
- startGrabber ();
-
- /** \brief Shows the unprocessed input data. */
- void
- showUnprocessedData ();
-
- /** \brief Shows the processed input data. */
- void
- showProcessedData ();
-
- /** \brief Registers new data to the first acquired data continuously. */
- void
- registerContinuously ();
-
- /** \brief Registers new data once and returns to showing the processed data. */
- void
- registerOnce ();
-
- /** \brief Show the model shape (if one is available). */
- void
- showModel ();
-
- /** \brief Removes unfit vertices regardless of their age. Unfit vertices are those that have not been observed from enough directions. */
- void
- removeUnfitVertices ();
-
- /** \brief Reset the scanning pipeline. */
- void
- reset ();
-
- /** \brief Saves the model mesh in a file with the given filename and filetype.
- * \note The extension of the filename is ignored!
- */
- void
- saveAs (const std::string& filename, const FileType& filetype);
-
- /** \see http://doc.qt.digia.com/qt/qwidget.html#keyPressEvent */
- void
- keyPressEvent (QKeyEvent* event) override;
-
- private:
-
- using PointXYZRGBA = pcl::PointXYZRGBA;
- using CloudXYZRGBA = pcl::PointCloud<PointXYZRGBA>;
- using CloudXYZRGBAPtr = CloudXYZRGBA::Ptr;
- using CloudXYZRGBAConstPtr = CloudXYZRGBA::ConstPtr;
-
- using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
- using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
- using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
- using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
-
- using PointIHS = pcl::ihs::PointIHS;
- using CloudIHS = pcl::ihs::CloudIHS;
- using CloudIHSPtr = pcl::ihs::CloudIHSPtr;
- using CloudIHSConstPtr = pcl::ihs::CloudIHSConstPtr;
-
- using Mesh = pcl::ihs::Mesh;
- using MeshPtr = pcl::ihs::MeshPtr;
- using MeshConstPtr = pcl::ihs::MeshConstPtr;
-
- using Grabber = pcl::OpenNIGrabber;
- using GrabberPtr = std::shared_ptr<Grabber>;
- using GrabberConstPtr = std::shared_ptr<const Grabber>;
-
- /** \brief Helper object for the computation thread. Please have a look at the documentation of calcFPS. */
- class ComputationFPS : public Base::FPS
- {
- public:
- ComputationFPS () {}
- ~ComputationFPS () {}
- };
-
- /** \brief Helper object for the visualization thread. Please have a look at the documentation of calcFPS. */
- class VisualizationFPS : public Base::FPS
- {
- public:
- VisualizationFPS () {}
- ~VisualizationFPS () {}
- };
+ return (*input_data_processing_);
+ }
- /** \brief Called when new data arries from the grabber. The grabbing - registration - integration pipeline is implemented here. */
- void
- newDataCallback (const CloudXYZRGBAConstPtr& cloud_in);
-
- /** \see http://doc.qt.digia.com/qt/qwidget.html#paintEvent
- * \see http://doc.qt.digia.com/qt/opengl-overpainting.html
- */
- void
- paintEvent (QPaintEvent* event) override;
-
- /** \brief Draw text over the opengl scene.
- * \see http://doc.qt.digia.com/qt/opengl-overpainting.html
- */
- void
- drawText ();
-
- /** \brief Actual implementeation of startGrabber (needed so it can be run in a different thread and doesn't block the application when starting up). */
- void
- startGrabberImpl ();
-
- ////////////////////////////////////////////////////////////////////////
- // Members
- ////////////////////////////////////////////////////////////////////////
-
- /** \brief Synchronization. */
- std::mutex mutex_;
-
- /** \brief Please have a look at the documentation of ComputationFPS. */
- ComputationFPS computation_fps_;
-
- /** \brief Please have a look at the documentation of VisualizationFPS. */
- VisualizationFPS visualization_fps_;
-
- /** \brief Switch between different branches of the scanning pipeline. */
- RunningMode running_mode_;
-
- /** \brief The iteration of the scanning pipeline (grab - register - integrate). */
- unsigned int iteration_;
-
- /** \brief Used to get new data from the sensor. */
- GrabberPtr grabber_;
-
- /** \brief This variable is true if the grabber is starting. */
- bool starting_grabber_;
-
- /** \brief Connection of the grabber signal with the data processing thread. */
- boost::signals2::connection new_data_connection_;
-
- /** \brief Processes the data from the sensor. Output is input to the registration. */
- InputDataProcessingPtr input_data_processing_;
-
- /** \brief Registration (Iterative Closest Point). */
- ICPPtr icp_;
-
- /** \brief Transformation that brings the data cloud into model coordinates. */
- Eigen::Matrix4f transformation_;
-
- /** \brief Integrate the data cloud into a common model. */
- IntegrationPtr integration_;
+ /** \brief Get the registration. */
+ inline ICP&
+ getICP()
+ {
+ return (*icp_);
+ }
- /** \brief Methods called after the integration. */
- MeshProcessingPtr mesh_processing_;
+ /** \brief Get the integration. */
+ inline Integration&
+ getIntegration()
+ {
+ return (*integration_);
+ }
+
+Q_SIGNALS:
+
+ /** \brief Emitted when the running mode changes. */
+ void
+ runningModeChanged(RunningMode new_running_mode) const;
+
+public Q_SLOTS:
+
+ /** \brief Start the grabber (enables the scanning pipeline). */
+ void
+ startGrabber();
+
+ /** \brief Shows the unprocessed input data. */
+ void
+ showUnprocessedData();
+
+ /** \brief Shows the processed input data. */
+ void
+ showProcessedData();
+
+ /** \brief Registers new data to the first acquired data continuously. */
+ void
+ registerContinuously();
+
+ /** \brief Registers new data once and returns to showing the processed data. */
+ void
+ registerOnce();
+
+ /** \brief Show the model shape (if one is available). */
+ void
+ showModel();
+
+ /** \brief Removes unfit vertices regardless of their age. Unfit vertices are those
+ * that have not been observed from enough directions. */
+ void
+ removeUnfitVertices();
+
+ /** \brief Reset the scanning pipeline. */
+ void
+ reset();
+
+ /** \brief Saves the model mesh in a file with the given filename and filetype.
+ *
+ * \note The extension of the filename is ignored!
+ */
+ void
+ saveAs(const std::string& filename, const FileType& filetype);
+
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#keyPressEvent */
+ void
+ keyPressEvent(QKeyEvent* event) override;
+
+private:
+ using PointXYZRGBA = pcl::PointXYZRGBA;
+ using CloudXYZRGBA = pcl::PointCloud<PointXYZRGBA>;
+ using CloudXYZRGBAPtr = CloudXYZRGBA::Ptr;
+ using CloudXYZRGBAConstPtr = CloudXYZRGBA::ConstPtr;
+
+ using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
+ using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
+ using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
+ using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
- /** \brief Model to which new data is registered to (stored as a mesh). */
- MeshPtr mesh_model_;
+ using PointIHS = pcl::ihs::PointIHS;
+ using CloudIHS = pcl::ihs::CloudIHS;
+ using CloudIHSPtr = pcl::ihs::CloudIHSPtr;
+ using CloudIHSConstPtr = pcl::ihs::CloudIHSConstPtr;
+
+ using Mesh = pcl::ihs::Mesh;
+ using MeshPtr = pcl::ihs::MeshPtr;
+ using MeshConstPtr = pcl::ihs::MeshConstPtr;
+
+ using Grabber = pcl::OpenNIGrabber;
+ using GrabberPtr = std::shared_ptr<Grabber>;
+ using GrabberConstPtr = std::shared_ptr<const Grabber>;
+
+ /** \brief Helper object for the computation thread. Please have a look at the
+ * documentation of calcFPS. */
+ class ComputationFPS : public Base::FPS {
+ public:
+ ComputationFPS() = default;
+ ~ComputationFPS() = default;
+ };
+
+ /** \brief Helper object for the visualization thread. Please have a look at the
+ * documentation of calcFPS. */
+ class VisualizationFPS : public Base::FPS {
+ public:
+ VisualizationFPS() = default;
+ ~VisualizationFPS() = default;
+ };
+
+ /** \brief Called when new data arries from the grabber. The grabbing - registration -
+ * integration pipeline is implemented here. */
+ void
+ newDataCallback(const CloudXYZRGBAConstPtr& cloud_in);
+
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#paintEvent
+ * \see http://doc.qt.digia.com/qt/opengl-overpainting.html
+ */
+ void
+ paintEvent(QPaintEvent* event) override;
+
+ /** \brief Draw text over the opengl scene.
+ * \see http://doc.qt.digia.com/qt/opengl-overpainting.html
+ */
+ void
+ drawText();
+
+ /** \brief Actual implementeation of startGrabber (needed so it can be run in a
+ * different thread and doesn't block the application when starting up). */
+ void
+ startGrabberImpl();
+
+ ////////////////////////////////////////////////////////////////////////
+ // Members
+ ////////////////////////////////////////////////////////////////////////
+
+ /** \brief Synchronization. */
+ std::mutex mutex_;
+
+ /** \brief Please have a look at the documentation of ComputationFPS. */
+ ComputationFPS computation_fps_;
+
+ /** \brief Please have a look at the documentation of VisualizationFPS. */
+ VisualizationFPS visualization_fps_;
+
+ /** \brief Switch between different branches of the scanning pipeline. */
+ RunningMode running_mode_;
+
+ /** \brief The iteration of the scanning pipeline (grab - register - integrate). */
+ unsigned int iteration_;
+
+ /** \brief Used to get new data from the sensor. */
+ GrabberPtr grabber_;
+
+ /** \brief This variable is true if the grabber is starting. */
+ bool starting_grabber_;
+
+ /** \brief Connection of the grabber signal with the data processing thread. */
+ boost::signals2::connection new_data_connection_;
+
+ /** \brief Processes the data from the sensor. Output is input to the registration. */
+ InputDataProcessingPtr input_data_processing_;
+
+ /** \brief Registration (Iterative Closest Point). */
+ ICPPtr icp_;
+
+ /** \brief Transformation that brings the data cloud into model coordinates. */
+ Eigen::Matrix4f transformation_;
+
+ /** \brief Integrate the data cloud into a common model. */
+ IntegrationPtr integration_;
+
+ /** \brief Methods called after the integration. */
+ MeshProcessingPtr mesh_processing_;
- /** \brief Prevent the application to crash while closing. */
- bool destructor_called_;
+ /** \brief Model to which new data is registered to (stored as a mesh). */
+ MeshPtr mesh_model_;
+
+ /** \brief Prevent the application to crash while closing. */
+ bool destructor_called_;
- public:
- PCL_MAKE_ALIGNED_OPERATOR_NEW
- };
- } // End namespace ihs
+public:
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+};
+} // End namespace ihs
} // End namespace pcl
// http://doc.qt.digia.com/qt/qmetatype.html#Q_DECLARE_METATYPE
-Q_DECLARE_METATYPE (pcl::ihs::InHandScanner::RunningMode)
+Q_DECLARE_METATYPE(pcl::ihs::InHandScanner::RunningMode)
#pragma once
-#include <pcl/pcl_exports.h>
#include <pcl/apps/in_hand_scanner/common_types.h>
#include <pcl/apps/in_hand_scanner/utils.h>
#include <pcl/features/integral_image_normal.h>
+#include <pcl/pcl_exports.h>
////////////////////////////////////////////////////////////////////////////////
// InputDataProcessing
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- namespace ihs
- {
- /** \brief Bundles methods that are applied to the input data from the sensor.
- * \author Martin Saelzle
- * \ingroup apps
- */
- class PCL_EXPORTS InputDataProcessing
- {
- public:
-
- using PointXYZRGBA = pcl::PointXYZRGBA;
- using CloudXYZRGBA = pcl::PointCloud<PointXYZRGBA>;
- using CloudXYZRGBAPtr = CloudXYZRGBA::Ptr;
- using CloudXYZRGBAConstPtr = CloudXYZRGBA::ConstPtr;
-
- using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
- using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
- using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
- using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
-
- /** \brief Constructor */
- InputDataProcessing ();
-
- /** \brief Apply the segmentation on the input cloud (XYZ and HSV).
- * \param[in] cloud_in The input cloud.
- * \param[out] cloud_out The segmented cloud.
- * \param[out] cloud_discarded Cloud containing all points that were removed during the HSV segmentation. The points in the XYZ segmentation are NOT used!
- * \return true if success.
- * \note Converts from m to cm.
- */
- bool
- segment (const CloudXYZRGBAConstPtr& cloud_in,
- CloudXYZRGBNormalPtr& cloud_out,
- CloudXYZRGBNormalPtr& cloud_discarded) const;
-
- /** \brief Calculate the normals of the input cloud.
- * \param[in] cloud_in The input cloud.
- * \param[out] cloud_out Input cloud with normals appended.
- * \return true if success.
- * \note Converts from m to cm.
- */
- bool
- calculateNormals (const CloudXYZRGBAConstPtr& cloud_in,
- CloudXYZRGBNormalPtr& cloud_out) const;
-
- /** @{ */
- /** \brief Points outside of X - Y - Z - min / max are discarded. The unit is cm. The min values must be smaller than the max values. */
- inline void setXMin (const float x_min) {if (x_min < x_max_) x_min_ = x_min;}
- inline void setXMax (const float x_max) {if (x_max > x_min_) x_max_ = x_max;}
- inline void setYMin (const float y_min) {if (y_min < y_max_) y_min_ = y_min;}
- inline void setYMax (const float y_max) {if (y_max > y_min_) y_max_ = y_max;}
- inline void setZMin (const float z_min) {if (z_min < z_max_) z_min_ = z_min;}
- inline void setZMax (const float z_max) {if (z_max > z_min_) z_max_ = z_max;}
-
- inline float getXMin () const {return (x_min_);}
- inline float getXMax () const {return (x_max_);}
- inline float getYMin () const {return (y_min_);}
- inline float getYMax () const {return (y_max_);}
- inline float getZMin () const {return (z_min_);}
- inline float getZMax () const {return (z_max_);}
- /** @} */
-
- /** @{ */
- /** \brief Simple color segmentation in the HSV color space. Points inside of H - S - V min / max are discarded. H must be in the range 0 and 360, S and V in the range 0 and 1.
- * \note If you set values outside of the allowed range the member variables are clamped to the next best value. E.g. H is set to 0 if you pass -1.
- */
- inline void setHMin (const float h_min) {h_min_ = pcl::ihs::clamp (h_min, 0.f, 360.f);}
- inline void setHMax (const float h_max) {h_max_ = pcl::ihs::clamp (h_max, 0.f, 360.f);}
- inline void setSMin (const float s_min) {s_min_ = pcl::ihs::clamp (s_min, 0.f, 1.f);}
- inline void setSMax (const float s_max) {s_max_ = pcl::ihs::clamp (s_max, 0.f, 1.f);}
- inline void setVMin (const float v_min) {v_min_ = pcl::ihs::clamp (v_min, 0.f, 1.f);}
- inline void setVMax (const float v_max) {v_max_ = pcl::ihs::clamp (v_max, 0.f, 1.f);}
-
- inline float getHMin () const {return (h_min_);}
- inline float getHMax () const {return (h_max_);}
- inline float getSMin () const {return (s_min_);}
- inline float getSMax () const {return (s_max_);}
- inline float getVMin () const {return (v_min_);}
- inline float getVMax () const {return (v_max_);}
- /** @} */
-
- /** @{ */
- /** \brief If true the color values inside of H - S - V min / max are accepted instead of discarded. */
- inline void setColorSegmentationInverted (const bool hsv_inverted) {hsv_inverted_ = hsv_inverted;}
- inline bool getColorSegmentationInverted () const {return (hsv_inverted_);}
- /** @} */
-
- /** @{ */
- /** \brief Enable / disable the color segmentation. */
- inline void setColorSegmentationEnabled (const bool hsv_enabled) {hsv_enabled_ = hsv_enabled;}
- inline bool getColorSegmentationEnabled () const {return (hsv_enabled_);}
- /** @} */
-
- /** @{ */
- /** \brief The XYZ mask is eroded with a kernel of this size. */
- inline void setXYZErodeSize (const unsigned int size) {size_erode_ = size;}
- inline unsigned int getXYZErodeSize () const {return (size_erode_);}
- /** @} */
-
- /** @{ */
- /** \brief The HSV mask is dilated with a kernel of this size. */
- inline void setHSVDilateSize (const unsigned int size) {size_dilate_ = size;}
- inline unsigned int getHSVDilateSize () const {return (size_dilate_);}
- /** @} */
-
- private:
-
- using Normal = pcl::Normal;
- using CloudNormals = pcl::PointCloud<Normal>;
- using CloudNormalsPtr = CloudNormals::Ptr;
- using CloudNormalsConstPtr = CloudNormals::ConstPtr;
-
- using NormalEstimation = pcl::IntegralImageNormalEstimation <PointXYZRGBA, Normal>;
- using NormalEstimationPtr = NormalEstimation::Ptr;
- using NormalEstimationConstPtr = NormalEstimation::ConstPtr;
-
- using MatrixXb = Eigen::Matrix <bool, Eigen::Dynamic, Eigen::Dynamic>;
- using MatrixXi = Eigen::MatrixXi;
-
- /** \brief Erodes the input mask k times with a diamond shaped structuring element.
- * \see http://ostermiller.org/dilate_and_erode.html
- */
- void
- erode (MatrixXb& mask, const int k) const;
-
- /** \brief Dilates the input mask k times with a diamond shaped structuring element.
- * \see http://ostermiller.org/dilate_and_erode.html
- */
- void
- dilate (MatrixXb& mask, const int k) const;
-
- /** \brief Calculates the manhattan distance map for the input matrix.
- * \param[in] mat Input matrix.
- * \param[in] comp Compared value. mat==comp will have zero distance.
- * \return Matrix containing the distances to mat==comp
- * \see http://ostermiller.org/dilate_and_erode.html
- */
- MatrixXi
- manhattan (const MatrixXb& mat, const bool comp) const;
-
- /** \brief Conversion from the RGB to HSV color space. */
- void
- RGBToHSV (const unsigned char r,
- const unsigned char g,
- const unsigned char b,
- float& h,
- float& s,
- float& v) const;
-
- ////////////////////////////////////////////////////////////////////////
- // Members
- ////////////////////////////////////////////////////////////////////////
-
- NormalEstimationPtr normal_estimation_;
-
- float x_min_;
- float x_max_;
- float y_min_;
- float y_max_;
- float z_min_;
- float z_max_;
-
- float h_min_;
- float h_max_;
- float s_min_;
- float s_max_;
- float v_min_;
- float v_max_;
-
- bool hsv_inverted_;
- bool hsv_enabled_;
-
- unsigned int size_dilate_;
- unsigned int size_erode_;
- };
- } // End namespace ihs
+namespace pcl {
+namespace ihs {
+/** \brief Bundles methods that are applied to the input data from the sensor.
+ * \author Martin Saelzle
+ * \ingroup apps
+ */
+class PCL_EXPORTS InputDataProcessing {
+public:
+ using PointXYZRGBA = pcl::PointXYZRGBA;
+ using CloudXYZRGBA = pcl::PointCloud<PointXYZRGBA>;
+ using CloudXYZRGBAPtr = CloudXYZRGBA::Ptr;
+ using CloudXYZRGBAConstPtr = CloudXYZRGBA::ConstPtr;
+
+ using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
+ using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
+ using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
+ using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
+
+ /** \brief Constructor */
+ InputDataProcessing();
+
+ /** \brief Apply the segmentation on the input cloud (XYZ and HSV).
+ *
+ * \param[in] cloud_in The input cloud.
+ * \param[out] cloud_out The segmented cloud.
+ * \param[out] cloud_discarded Cloud containing all points that were removed during
+ * the HSV segmentation. The points in the XYZ segmentation are NOT used!
+ *
+ * \return true if success.
+ *
+ * \note Converts from m to cm.
+ */
+ bool
+ segment(const CloudXYZRGBAConstPtr& cloud_in,
+ CloudXYZRGBNormalPtr& cloud_out,
+ CloudXYZRGBNormalPtr& cloud_discarded) const;
+
+ /** \brief Calculate the normals of the input cloud.
+ *
+ * \param[in] cloud_in The input cloud.
+ * \param[out] cloud_out Input cloud with normals appended.
+ *
+ * \return true if success.
+ *
+ * \note Converts from m to cm.
+ */
+ bool
+ calculateNormals(const CloudXYZRGBAConstPtr& cloud_in,
+ CloudXYZRGBNormalPtr& cloud_out) const;
+
+ /** @{ */
+ /** \brief Points outside of X - Y - Z - min / max are discarded. The unit is cm. The
+ * min values must be smaller than the max values. */
+ inline void
+ setXMin(const float x_min)
+ {
+ if (x_min < x_max_)
+ x_min_ = x_min;
+ }
+ inline void
+ setXMax(const float x_max)
+ {
+ if (x_max > x_min_)
+ x_max_ = x_max;
+ }
+ inline void
+ setYMin(const float y_min)
+ {
+ if (y_min < y_max_)
+ y_min_ = y_min;
+ }
+ inline void
+ setYMax(const float y_max)
+ {
+ if (y_max > y_min_)
+ y_max_ = y_max;
+ }
+ inline void
+ setZMin(const float z_min)
+ {
+ if (z_min < z_max_)
+ z_min_ = z_min;
+ }
+ inline void
+ setZMax(const float z_max)
+ {
+ if (z_max > z_min_)
+ z_max_ = z_max;
+ }
+
+ inline float
+ getXMin() const
+ {
+ return (x_min_);
+ }
+ inline float
+ getXMax() const
+ {
+ return (x_max_);
+ }
+ inline float
+ getYMin() const
+ {
+ return (y_min_);
+ }
+ inline float
+ getYMax() const
+ {
+ return (y_max_);
+ }
+ inline float
+ getZMin() const
+ {
+ return (z_min_);
+ }
+ inline float
+ getZMax() const
+ {
+ return (z_max_);
+ }
+ /** @} */
+
+ /** @{ */
+ /** \brief Simple color segmentation in the HSV color space. Points inside of H - S -
+ * V min / max are discarded. H must be in the range 0 and 360, S and V in the range 0
+ * and 1.
+ *
+ * \note If you set values outside of the allowed range the member variables
+ * are clamped to the next best value. E.g. H is set to 0 if you pass -1.
+ */
+ inline void
+ setHMin(const float h_min)
+ {
+ h_min_ = pcl::ihs::clamp(h_min, 0.f, 360.f);
+ }
+ inline void
+ setHMax(const float h_max)
+ {
+ h_max_ = pcl::ihs::clamp(h_max, 0.f, 360.f);
+ }
+ inline void
+ setSMin(const float s_min)
+ {
+ s_min_ = pcl::ihs::clamp(s_min, 0.f, 1.f);
+ }
+ inline void
+ setSMax(const float s_max)
+ {
+ s_max_ = pcl::ihs::clamp(s_max, 0.f, 1.f);
+ }
+ inline void
+ setVMin(const float v_min)
+ {
+ v_min_ = pcl::ihs::clamp(v_min, 0.f, 1.f);
+ }
+ inline void
+ setVMax(const float v_max)
+ {
+ v_max_ = pcl::ihs::clamp(v_max, 0.f, 1.f);
+ }
+
+ inline float
+ getHMin() const
+ {
+ return (h_min_);
+ }
+ inline float
+ getHMax() const
+ {
+ return (h_max_);
+ }
+ inline float
+ getSMin() const
+ {
+ return (s_min_);
+ }
+ inline float
+ getSMax() const
+ {
+ return (s_max_);
+ }
+ inline float
+ getVMin() const
+ {
+ return (v_min_);
+ }
+ inline float
+ getVMax() const
+ {
+ return (v_max_);
+ }
+ /** @} */
+
+ /** @{ */
+ /** \brief If true the color values inside of H - S - V min / max are accepted instead
+ * of discarded. */
+ inline void
+ setColorSegmentationInverted(const bool hsv_inverted)
+ {
+ hsv_inverted_ = hsv_inverted;
+ }
+ inline bool
+ getColorSegmentationInverted() const
+ {
+ return (hsv_inverted_);
+ }
+ /** @} */
+
+ /** @{ */
+ /** \brief Enable / disable the color segmentation. */
+ inline void
+ setColorSegmentationEnabled(const bool hsv_enabled)
+ {
+ hsv_enabled_ = hsv_enabled;
+ }
+ inline bool
+ getColorSegmentationEnabled() const
+ {
+ return (hsv_enabled_);
+ }
+ /** @} */
+
+ /** @{ */
+ /** \brief The XYZ mask is eroded with a kernel of this size. */
+ inline void
+ setXYZErodeSize(const unsigned int size)
+ {
+ size_erode_ = size;
+ }
+ inline unsigned int
+ getXYZErodeSize() const
+ {
+ return (size_erode_);
+ }
+ /** @} */
+
+ /** @{ */
+ /** \brief The HSV mask is dilated with a kernel of this size. */
+ inline void
+ setHSVDilateSize(const unsigned int size)
+ {
+ size_dilate_ = size;
+ }
+ inline unsigned int
+ getHSVDilateSize() const
+ {
+ return (size_dilate_);
+ }
+ /** @} */
+
+private:
+ using Normal = pcl::Normal;
+ using CloudNormals = pcl::PointCloud<Normal>;
+ using CloudNormalsPtr = CloudNormals::Ptr;
+ using CloudNormalsConstPtr = CloudNormals::ConstPtr;
+
+ using NormalEstimation = pcl::IntegralImageNormalEstimation<PointXYZRGBA, Normal>;
+ using NormalEstimationPtr = NormalEstimation::Ptr;
+ using NormalEstimationConstPtr = NormalEstimation::ConstPtr;
+
+ using MatrixXb = Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic>;
+ using MatrixXi = Eigen::MatrixXi;
+
+ /** \brief Erodes the input mask k times with a diamond shaped structuring element.
+ * \see http://ostermiller.org/dilate_and_erode.html
+ */
+ void
+ erode(MatrixXb& mask, const int k) const;
+
+ /** \brief Dilates the input mask k times with a diamond shaped structuring element.
+ * \see http://ostermiller.org/dilate_and_erode.html
+ */
+ void
+ dilate(MatrixXb& mask, const int k) const;
+
+ /** \brief Calculates the manhattan distance map for the input matrix.
+ *
+ * \param[in] mat Input matrix.
+ * \param[in] comp Compared value. mat==comp will have zero distance.
+ *
+ * \return Matrix containing the distances to mat==comp
+ * \see http://ostermiller.org/dilate_and_erode.html
+ */
+ MatrixXi
+ manhattan(const MatrixXb& mat, const bool comp) const;
+
+ /** \brief Conversion from the RGB to HSV color space. */
+ void
+ RGBToHSV(const unsigned char r,
+ const unsigned char g,
+ const unsigned char b,
+ float& h,
+ float& s,
+ float& v) const;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Members
+ ////////////////////////////////////////////////////////////////////////
+
+ NormalEstimationPtr normal_estimation_;
+
+ float x_min_;
+ float x_max_;
+ float y_min_;
+ float y_max_;
+ float z_min_;
+ float z_max_;
+
+ float h_min_;
+ float h_max_;
+ float s_min_;
+ float s_max_;
+ float v_min_;
+ float v_max_;
+
+ bool hsv_inverted_;
+ bool hsv_enabled_;
+
+ unsigned int size_dilate_;
+ unsigned int size_erode_;
+};
+} // End namespace ihs
} // End namespace pcl
#pragma once
-#include <cstdint>
-
#include <pcl/apps/in_hand_scanner/common_types.h>
-#include <pcl/pcl_exports.h>
#include <pcl/kdtree/kdtree.h>
+#include <pcl/pcl_exports.h>
+
+#include <cstdint>
////////////////////////////////////////////////////////////////////////////////
// Integration
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- namespace ihs
- {
- /** \brief Integrate several clouds into a common mesh.
- * \author Martin Saelzle
- * \ingroup apps
- */
- class PCL_EXPORTS Integration
- {
- public:
-
- using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
- using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
- using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
- using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
-
- using Mesh = pcl::ihs::Mesh;
- using MeshPtr = pcl::ihs::MeshPtr;
- using MeshConstPtr = pcl::ihs::MeshConstPtr;
- using VertexIndex = Mesh::VertexIndex;
- using VertexIndices = Mesh::VertexIndices;
-
- /** \brief Constructor. */
- Integration ();
-
- /** \brief Reconstructs a mesh from an organized cloud.
- * \param[in] cloud_data Input cloud. Must be organized.
- * \param[in] mesh_model Reconstructed mesh.
- * \return true if success.
- */
- bool
- reconstructMesh (const CloudXYZRGBNormalConstPtr& cloud_data,
- MeshPtr& mesh_model) const;
-
- /** \brief Merge the organized cloud into the mesh.
- * \param[in] cloud_data Input cloud. Must be organized.
- * \param[in,out] mesh_model Mesh with new points integrated.
- * \param[in] T Transformation that aligns the data cloud with the model mesh.
- * \return true if success.
- */
- bool
- merge (const CloudXYZRGBNormalConstPtr& cloud_data,
- MeshPtr& mesh_model,
- const Eigen::Matrix4f& T) const;
-
- /** \brief Outlier rejection. In each merge step points that have not been observed again age by one iteration. Points that are observed again get an age of 0. Once a point reaches the maximum age it is decided if the point is removed or kept in the mesh. A point is removed if it has not been observed from a minimum number of directions.
- * \param[in,out] mesh The mesh which should be processed.
- * \param[in] cleanup Calls mesh.cleanup () if true.
- */
- void
- age (const MeshPtr& mesh, const bool cleanup=true) const;
-
- /** \brief Removes unfit vertices regardless of their age. Unfit vertices are those that have not been observed from enough directions.
- * \param[in,out] mesh The which should be processed.
- * \param[in] cleanup Calls mesh.cleanup () if true.
- */
- void
- removeUnfitVertices (const MeshPtr& mesh, const bool cleanup=true) const;
-
- /** @{ */
- /** \brief Corresponding points are averaged out if their distance is below a distance threshold. Else the points are added to the mesh as new vertices (Set in cm^2).
- * \note Must be greater than zero.
- */
- void setMaxSquaredDistance (const float squared_distance);
- float getMaxSquaredDistance () const;
- /** @} */
-
- /** @{ */
- /** \brief Corresponding points are only averaged out if the angle between the normals is smaller than an angle threshold.
- * \note Must be between 0 and 180. Values outside this range are clamped to the nearest valid value.
- */
- void setMaxAngle (const float angle);
- float getMaxAngle () const;
- /** @} */
-
- /** @{ */
- /** \brief Once a point reaches the maximum age it is decided if the point is removed or kept in the mesh.
- * \note Must be greater than zero.
- */
- void setMaxAge (const unsigned int age);
- unsigned int getMaxAge () const;
- /** @} */
-
- /** @{ */
- /** \brief A point is removed if it has not been observed from a minimum number of directions.
- * \note Must be greater than zero.
- */
- void setMinDirections (const unsigned int directions);
- unsigned int getMinDirections () const;
- /** @} */
-
- private:
-
- using PointXYZ = pcl::PointXYZ;
- using CloudXYZ = pcl::PointCloud<PointXYZ>;
- using CloudXYZPtr = CloudXYZ::Ptr;
- using CloudXYZConstPtr = CloudXYZ::ConstPtr;
-
- using PointIHS = pcl::ihs::PointIHS;
- using CloudIHS = pcl::ihs::CloudIHS;
- using CloudIHSPtr = pcl::ihs::CloudIHSPtr;
- using CloudIHSConstPtr = pcl::ihs::CloudIHSConstPtr;
-
- using KdTree = pcl::KdTree<PointXYZ>;
- using KdTreePtr = KdTree::Ptr;
- using KdTreeConstPtr = KdTree::ConstPtr;
-
- std::uint8_t
- trimRGB (const float val) const;
-
- /** \brief Adds two triangles between points 0-1-3 and 1-2-3 to the mesh. */
- void
- addToMesh (const PointIHS& pt_0,
- const PointIHS& pt_1,
- const PointIHS& pt_2,
- const PointIHS& pt_3,
- VertexIndex& vi_0,
- VertexIndex& vi_1,
- VertexIndex& vi_2,
- VertexIndex& vi_3,
- const MeshPtr& mesh) const;
-
- /** \brief Adds a triangle between the points 0-1-2 to the mesh. */
- void
- addToMesh (const PointIHS& pt_0,
- const PointIHS& pt_1,
- const PointIHS& pt_2,
- VertexIndex& vi_0,
- VertexIndex& vi_1,
- VertexIndex& vi_2,
- const MeshPtr& mesh) const;
-
- /** \brief Returns true if the distance between the three points is below a threshold. */
- bool
- distanceThreshold (const PointIHS& pt_0,
- const PointIHS& pt_1,
- const PointIHS& pt_2) const;
-
- /** \brief Returns true if the distance between the four points is below a threshold. */
- bool
- distanceThreshold (const PointIHS& pt_0,
- const PointIHS& pt_1,
- const PointIHS& pt_2,
- const PointIHS& pt_3) const;
-
- ////////////////////////////////////////////////////////////////////////
- // Members
- ////////////////////////////////////////////////////////////////////////
-
- /** \brief Nearest neighbor search. */
- KdTreePtr kd_tree_;
-
- /** \brief Maximum squared distance below which points are averaged out. */
- float max_squared_distance_;
-
- /** \brief Maximum angle between normals below which points are averaged out. In degrees. */
- float max_angle_;
-
- /** \brief Minimum weight above which points are added. */
- float min_weight_;
-
- /** \brief Once a point reaches the maximum age it is decided if the point is removed or kept in the mesh. */
- unsigned int max_age_;
-
- /** \brief A point is removed if it has not been observed from a minimum number of directions. */
- unsigned int min_directions_;
- };
- } // End namespace ihs
+namespace pcl {
+namespace ihs {
+/** \brief Integrate several clouds into a common mesh.
+ * \author Martin Saelzle
+ * \ingroup apps
+ */
+class PCL_EXPORTS Integration {
+public:
+ using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
+ using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
+ using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
+ using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
+
+ using Mesh = pcl::ihs::Mesh;
+ using MeshPtr = pcl::ihs::MeshPtr;
+ using MeshConstPtr = pcl::ihs::MeshConstPtr;
+ using VertexIndex = Mesh::VertexIndex;
+ using VertexIndices = Mesh::VertexIndices;
+
+ /** \brief Constructor. */
+ Integration();
+
+ /** \brief Reconstructs a mesh from an organized cloud.
+ *
+ * \param[in] cloud_data Input cloud. Must be organized.
+ * \param[in] mesh_model Reconstructed mesh.
+ *
+ * \return true if success.
+ */
+ bool
+ reconstructMesh(const CloudXYZRGBNormalConstPtr& cloud_data,
+ MeshPtr& mesh_model) const;
+
+ /** \brief Merge the organized cloud into the mesh.#
+ *
+ * \param[in] cloud_data Input cloud. Must be organized.
+ * \param[in,out] mesh_model Mesh with new points integrated.
+ * \param[in] T Transformation that aligns the data cloud with the model mesh.
+ *
+ * \return true if success.
+ */
+ bool
+ merge(const CloudXYZRGBNormalConstPtr& cloud_data,
+ MeshPtr& mesh_model,
+ const Eigen::Matrix4f& T) const;
+
+ /** \brief Outlier rejection. In each merge step points that have not been observed
+ * again age by one iteration. Points that are observed again get an age of 0. Once a
+ * point reaches the maximum age it is decided if the point is removed or kept in the
+ * mesh. A point is removed if it has not been observed from a minimum number of
+ * directions.
+ *
+ * \param[in,out] mesh The mesh which should be processed.
+ * \param[in] cleanup Calls mesh.cleanup() if true.
+ */
+ void
+ age(const MeshPtr& mesh, const bool cleanup = true) const;
+
+ /** \brief Removes unfit vertices regardless of their age. Unfit vertices are those
+ * that have not been observed from enough directions.
+ *
+ * \param[in,out] mesh The which should be processed.
+ * \param[in] cleanup Calls mesh.cleanup() if true.
+ */
+ void
+ removeUnfitVertices(const MeshPtr& mesh, const bool cleanup = true) const;
+
+ /** @{ */
+ /** \brief Corresponding points are averaged out if their distance is below a distance
+ * threshold. Else the points are added to the mesh as new vertices (Set in cm^2).
+ *
+ * \note Must be greater than zero.
+ */
+ void
+ setMaxSquaredDistance(const float squared_distance);
+ float
+ getMaxSquaredDistance() const;
+ /** @} */
+
+ /** @{ */
+ /** \brief Corresponding points are only averaged out if the angle between the normals
+ * is smaller than an angle threshold.
+ *
+ * \note Must be between 0 and 180. Values outside this range are clamped to the
+ * nearest valid value.
+ */
+ void
+ setMaxAngle(const float angle);
+ float
+ getMaxAngle() const;
+ /** @} */
+
+ /** @{ */
+ /** \brief Once a point reaches the maximum age it is decided if the point is removed
+ * or kept in the mesh.
+ *
+ * \note Must be greater than zero.
+ */
+ void
+ setMaxAge(const unsigned int age);
+ unsigned int
+ getMaxAge() const;
+ /** @} */
+
+ /** @{ */
+ /** \brief A point is removed if it has not been observed from a minimum number of
+ * directions.
+ *
+ * \note Must be greater than zero.
+ */
+ void
+ setMinDirections(const unsigned int directions);
+ unsigned int
+ getMinDirections() const;
+ /** @} */
+
+private:
+ using PointXYZ = pcl::PointXYZ;
+ using CloudXYZ = pcl::PointCloud<PointXYZ>;
+ using CloudXYZPtr = CloudXYZ::Ptr;
+ using CloudXYZConstPtr = CloudXYZ::ConstPtr;
+
+ using PointIHS = pcl::ihs::PointIHS;
+ using CloudIHS = pcl::ihs::CloudIHS;
+ using CloudIHSPtr = pcl::ihs::CloudIHSPtr;
+ using CloudIHSConstPtr = pcl::ihs::CloudIHSConstPtr;
+
+ using KdTree = pcl::KdTree<PointXYZ>;
+ using KdTreePtr = KdTree::Ptr;
+ using KdTreeConstPtr = KdTree::ConstPtr;
+
+ std::uint8_t
+ trimRGB(const float val) const;
+
+ /** \brief Adds two triangles between points 0-1-3 and 1-2-3 to the mesh. */
+ void
+ addToMesh(const PointIHS& pt_0,
+ const PointIHS& pt_1,
+ const PointIHS& pt_2,
+ const PointIHS& pt_3,
+ VertexIndex& vi_0,
+ VertexIndex& vi_1,
+ VertexIndex& vi_2,
+ VertexIndex& vi_3,
+ const MeshPtr& mesh) const;
+
+ /** \brief Adds a triangle between the points 0-1-2 to the mesh. */
+ void
+ addToMesh(const PointIHS& pt_0,
+ const PointIHS& pt_1,
+ const PointIHS& pt_2,
+ VertexIndex& vi_0,
+ VertexIndex& vi_1,
+ VertexIndex& vi_2,
+ const MeshPtr& mesh) const;
+
+ /** \brief Returns true if the distance between the three points is below a threshold.
+ */
+ bool
+ distanceThreshold(const PointIHS& pt_0,
+ const PointIHS& pt_1,
+ const PointIHS& pt_2) const;
+
+ /** \brief Returns true if the distance between the four points is below a threshold.
+ */
+ bool
+ distanceThreshold(const PointIHS& pt_0,
+ const PointIHS& pt_1,
+ const PointIHS& pt_2,
+ const PointIHS& pt_3) const;
+
+ ////////////////////////////////////////////////////////////////////////
+ // Members
+ ////////////////////////////////////////////////////////////////////////
+
+ /** \brief Nearest neighbor search. */
+ KdTreePtr kd_tree_;
+
+ /** \brief Maximum squared distance below which points are averaged out. */
+ float max_squared_distance_;
+
+ /** \brief Maximum angle between normals below which points are averaged out. In
+ * degrees.
+ */
+ float max_angle_;
+
+ /** \brief Minimum weight above which points are added. */
+ float min_weight_;
+
+ /** \brief Once a point reaches the maximum age it is decided if the point is removed
+ * or kept in the mesh.
+ */
+ unsigned int max_age_;
+
+ /** \brief A point is removed if it has not been observed from a minimum number of
+ * directions.
+ */
+ unsigned int min_directions_;
+};
+} // End namespace ihs
} // End namespace pcl
#pragma once
-#include <QMainWindow>
-
#include <pcl/apps/in_hand_scanner/in_hand_scanner.h>
+#include <QMainWindow>
+
////////////////////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////////////////////
-namespace Ui
-{
- class MainWindow;
+namespace Ui {
+class MainWindow;
}
-namespace pcl
-{
- namespace ihs
- {
- class HelpWindow;
- } // End namespace ihs
+namespace pcl {
+namespace ihs {
+class HelpWindow;
+} // End namespace ihs
} // End namespace pcl
////////////////////////////////////////////////////////////////////////////////
// MainWindow
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- namespace ihs
- {
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
-
- public:
-
- using InHandScanner = pcl::ihs::InHandScanner;
- using HelpWindow = pcl::ihs::HelpWindow;
- using RunningMode = InHandScanner::RunningMode;
-
- explicit MainWindow (QWidget* parent = nullptr);
- ~MainWindow ();
-
- public Q_SLOTS:
-
- void showHelp ();
- void saveAs ();
-
- // In hand scanner
- void runningModeChanged (const RunningMode mode);
- void keyPressEvent (QKeyEvent* event) override;
-
- // Input data processing.
- void setXMin (const int x_min);
- void setXMax (const int x_max);
- void setYMin (const int y_min);
- void setYMax (const int y_max);
- void setZMin (const int z_min);
- void setZMax (const int z_max);
-
- void setHMin (const int h_min);
- void setHMax (const int h_max);
- void setSMin (const int s_min);
- void setSMax (const int s_max);
- void setVMin (const int v_min);
- void setVMax (const int v_max);
-
- void setColorSegmentationInverted (const bool is_inverted);
- void setColorSegmentationEnabled (const bool is_enabled);
-
- void setXYZErodeSize (const int size);
- void setHSVDilateSize (const int size);
-
- // Registration
- void setEpsilon ();
- void setMaxIterations (const int iterations);
- void setMinOverlap (const int overlap);
- void setMaxFitness ();
-
- void setCorrespondenceRejectionFactor (const double factor);
- void setCorrespondenceRejectionMaxAngle (const int angle);
-
- // Integration
- void setMaxSquaredDistance ();
- void setAveragingMaxAngle (const int angle);
- void setMaxAge (const int age);
- void setMinDirections (const int directions);
-
- private:
-
- Ui::MainWindow* ui_;
- HelpWindow* help_window_;
- InHandScanner* ihs_;
- };
- } // End namespace ihs
+namespace pcl {
+namespace ihs {
+class MainWindow : public QMainWindow {
+ Q_OBJECT
+
+public:
+ using InHandScanner = pcl::ihs::InHandScanner;
+ using HelpWindow = pcl::ihs::HelpWindow;
+ using RunningMode = InHandScanner::RunningMode;
+
+ explicit MainWindow(QWidget* parent = nullptr);
+ ~MainWindow() override;
+
+public Q_SLOTS:
+
+ void
+ showHelp();
+ void
+ saveAs();
+
+ // In hand scanner
+ void
+ runningModeChanged(const RunningMode mode);
+ void
+ keyPressEvent(QKeyEvent* event) override;
+
+ // Input data processing.
+ void
+ setXMin(const int x_min);
+ void
+ setXMax(const int x_max);
+ void
+ setYMin(const int y_min);
+ void
+ setYMax(const int y_max);
+ void
+ setZMin(const int z_min);
+ void
+ setZMax(const int z_max);
+
+ void
+ setHMin(const int h_min);
+ void
+ setHMax(const int h_max);
+ void
+ setSMin(const int s_min);
+ void
+ setSMax(const int s_max);
+ void
+ setVMin(const int v_min);
+ void
+ setVMax(const int v_max);
+
+ void
+ setColorSegmentationInverted(const bool is_inverted);
+ void
+ setColorSegmentationEnabled(const bool is_enabled);
+
+ void
+ setXYZErodeSize(const int size);
+ void
+ setHSVDilateSize(const int size);
+
+ // Registration
+ void
+ setEpsilon();
+ void
+ setMaxIterations(const int iterations);
+ void
+ setMinOverlap(const int overlap);
+ void
+ setMaxFitness();
+
+ void
+ setCorrespondenceRejectionFactor(const double factor);
+ void
+ setCorrespondenceRejectionMaxAngle(const int angle);
+
+ // Integration
+ void
+ setMaxSquaredDistance();
+ void
+ setAveragingMaxAngle(const int angle);
+ void
+ setMaxAge(const int age);
+ void
+ setMinDirections(const int directions);
+
+private:
+ Ui::MainWindow* ui_;
+ HelpWindow* help_window_;
+ InHandScanner* ihs_;
+};
+} // End namespace ihs
} // End namespace pcl
#include <pcl/apps/in_hand_scanner/common_types.h>
-namespace pcl
-{
- namespace ihs
- {
- /** \brief Contains methods that take advantage of the connectivity information in the mesh.
- * \author Martin Saelzle
- * \ingroup apps
- */
- class MeshProcessing
- {
- public:
-
- using Mesh = pcl::ihs::Mesh;
- using HalfEdgeIndices = Mesh::HalfEdgeIndices;
+namespace pcl {
+namespace ihs {
+/** \brief Contains methods that take advantage of the connectivity information in the
+ * mesh.
+ *
+ * \author Martin Saelzle
+ * \ingroup apps
+ */
+class MeshProcessing {
+public:
+ using Mesh = pcl::ihs::Mesh;
+ using HalfEdgeIndices = Mesh::HalfEdgeIndices;
- static_assert (Mesh::IsManifold::value, "MeshProcessing currently works only on the manifold mesh.");
+ static_assert(Mesh::IsManifold::value,
+ "MeshProcessing currently works only on the manifold mesh.");
- /** \brief Constructor. */
- MeshProcessing ();
+ /** \brief Constructor. */
+ MeshProcessing();
- /** \brief Inserts triangles into jagged boundaries, removes isolated triangles and closes triangular holes.
- * \param[in,out] mesh The mesh which should be processed.
- * \param[in] boundary_collection Collection of boundary half-edges.
- * \param[in] cleanup Calls mesh.cleanup () if true.
- */
- void
- processBoundary (Mesh& mesh, const std::vector <HalfEdgeIndices>& boundary_collection, const bool cleanup=true) const;
- };
- } // End namespace ihs
+ /** \brief Inserts triangles into jagged boundaries, removes isolated triangles and
+ * closes triangular holes.
+ *
+ * \param[in,out] mesh The mesh which should be processed.
+ * \param[in] boundary_collection Collection of boundary half-edges.
+ * \param[in] cleanup Calls mesh.cleanup() if true.
+ */
+ void
+ processBoundary(Mesh& mesh,
+ const std::vector<HalfEdgeIndices>& boundary_collection,
+ const bool cleanup = true) const;
+};
+} // End namespace ihs
} // End namespace pcl
#pragma once
+#include <pcl/apps/in_hand_scanner/common_types.h>
+#include <pcl/apps/in_hand_scanner/opengl_viewer.h>
+#include <pcl/common/time.h>
+#include <pcl/features/integral_image_normal.h>
#include <pcl/memory.h>
#include <pcl/pcl_exports.h>
#include <pcl/pcl_macros.h>
-#include <pcl/common/time.h>
-#include <pcl/features/integral_image_normal.h>
-#include <pcl/apps/in_hand_scanner/common_types.h>
-#include <pcl/apps/in_hand_scanner/opengl_viewer.h>
#include <mutex>
-#include <vector>
#include <string>
+#include <vector>
////////////////////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- namespace ihs
- {
- class Integration;
- } // End namespace ihs
+namespace pcl {
+namespace ihs {
+class Integration;
+} // End namespace ihs
} // End namespace pcl
////////////////////////////////////////////////////////////////////////////////
// OfflineIntegration
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- namespace ihs
- {
- /** \brief Read the clouds and transformations from files and integrate them into one common model.
- * \todo Add Documentation
- */
- class PCL_EXPORTS OfflineIntegration : public pcl::ihs::OpenGLViewer
- {
- Q_OBJECT
-
- public:
-
- using Base = pcl::ihs::OpenGLViewer;
- using Self = pcl::ihs::OfflineIntegration;
-
- /** \brief Constructor. */
- explicit OfflineIntegration (Base* parent=nullptr);
-
- /** \brief Destructor. */
- ~OfflineIntegration ();
-
- public Q_SLOTS:
-
- /** \brief Start the procedure from a path. */
- void
- start ();
-
- private Q_SLOTS:
-
- /** \brief Loads in new data. */
- void
- computationThread ();
-
- private:
-
- using PointXYZRGBA = pcl::PointXYZRGBA;
- using CloudXYZRGBA = pcl::PointCloud<PointXYZRGBA>;
- using CloudXYZRGBAPtr = CloudXYZRGBA::Ptr;
- using CloudXYZRGBAConstPtr = CloudXYZRGBA::ConstPtr;
-
- using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
- using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
- using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
- using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
-
- using Mesh = pcl::ihs::Mesh;
- using MeshPtr = pcl::ihs::MeshPtr;
- using MeshConstPtr = pcl::ihs::MeshConstPtr;
-
- using Integration = pcl::ihs::Integration;
- using IntegrationPtr = std::shared_ptr<Integration>;
- using IntegrationConstPtr = std::shared_ptr<const Integration>;
-
- using NormalEstimation = pcl::IntegralImageNormalEstimation <PointXYZRGBA, PointXYZRGBNormal>;
- using NormalEstimationPtr = NormalEstimation::Ptr;
- using NormalEstimationConstPtr = NormalEstimation::ConstPtr;
-
- /** \brief Helper object for the computation thread. Please have a look at the documentation of calcFPS. */
- class ComputationFPS : public Base::FPS
- {
- public:
- ComputationFPS () {}
- ~ComputationFPS () {}
- };
-
-
- /** \brief Helper object for the visualization thread. Please have a look at the documentation of calcFPS. */
- class VisualizationFPS : public Base::FPS
- {
- public:
- VisualizationFPS () {}
- ~VisualizationFPS () {}
- };
-
- /** \brief Get a list of files with from a given directory.
- * \param[in] path_dir Path to search for the files.
- * \param[in] extension File extension (must start with a dot). E.g. '.pcd'.
- * \param[out] files Paths to the files.
- * \return True if success.
- */
- bool
- getFilesFromDirectory (const std::string& path_dir,
- const std::string& extension,
- std::vector <std::string>& files) const;
-
- /** \brief Load the transformation matrix from the given file.
- * \param[in] filename Path to the file.
- * \param[out] transform The loaded transform.
- * \return True if success.
- */
- bool
- loadTransform (const std::string& filename,
- Eigen::Matrix4f& transform) const;
-
- /** \brief Load the cloud and transformation from the files and compute the normals.
- * \param[in] filename Path to the pcd file.
- * \param[out] cloud Cloud with computed normals.
- * \param[out] T Loaded transformation.
- * \return True if success.
- */
- bool
- load (const std::string& filename,
- CloudXYZRGBNormalPtr& cloud,
- Eigen::Matrix4f& T) const;
-
- /** \see http://doc.qt.digia.com/qt/qwidget.html#paintEvent
- * \see http://doc.qt.digia.com/qt/opengl-overpainting.html
- */
- void
- paintEvent (QPaintEvent* event) override;
-
- /** \see http://doc.qt.digia.com/qt/qwidget.html#keyPressEvent */
- void
- keyPressEvent (QKeyEvent* event) override;
-
- //////////////////////////////////////////////////////////////////////////
- // Members
- //////////////////////////////////////////////////////////////////////////
-
- /** \brief Synchronization. */
- std::mutex mutex_;
-
- /** \brief Wait until the data finished processing. */
- std::mutex mutex_quit_;
-
- /** \brief Please have a look at the documentation of ComputationFPS. */
- ComputationFPS computation_fps_;
-
- /** \brief Please have a look at the documentation of VisualizationFPS. */
- VisualizationFPS visualization_fps_;
-
- /** \brief Path to the pcd and transformation files. */
- std::string path_dir_;
-
- /** \brief Model to which new data is registered to (stored as a mesh). */
- MeshPtr mesh_model_;
-
- /** \brief Compute the normals for the input clouds. */
- NormalEstimationPtr normal_estimation_;
-
- /** \brief Integrate the data cloud into a common model. */
- IntegrationPtr integration_;
-
- /** \brief Prevent the application to crash while closing. */
- bool destructor_called_;
-
- public:
- PCL_MAKE_ALIGNED_OPERATOR_NEW
- };
- } // End namespace ihs
+namespace pcl {
+namespace ihs {
+/** \brief Read the clouds and transformations from files and integrate them into one
+ * common model.
+ *
+ * \todo Add Documentation
+ */
+class PCL_EXPORTS OfflineIntegration : public pcl::ihs::OpenGLViewer {
+ Q_OBJECT
+
+public:
+ using Base = pcl::ihs::OpenGLViewer;
+ using Self = pcl::ihs::OfflineIntegration;
+
+ /** \brief Constructor. */
+ explicit OfflineIntegration(Base* parent = nullptr);
+
+ /** \brief Destructor. */
+ ~OfflineIntegration() override;
+
+public Q_SLOTS:
+
+ /** \brief Start the procedure from a path. */
+ void
+ start();
+
+private Q_SLOTS:
+
+ /** \brief Loads in new data. */
+ void
+ computationThread();
+
+private:
+ using PointXYZRGBA = pcl::PointXYZRGBA;
+ using CloudXYZRGBA = pcl::PointCloud<PointXYZRGBA>;
+ using CloudXYZRGBAPtr = CloudXYZRGBA::Ptr;
+ using CloudXYZRGBAConstPtr = CloudXYZRGBA::ConstPtr;
+
+ using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
+ using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
+ using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
+ using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
+
+ using Mesh = pcl::ihs::Mesh;
+ using MeshPtr = pcl::ihs::MeshPtr;
+ using MeshConstPtr = pcl::ihs::MeshConstPtr;
+
+ using Integration = pcl::ihs::Integration;
+ using IntegrationPtr = std::shared_ptr<Integration>;
+ using IntegrationConstPtr = std::shared_ptr<const Integration>;
+
+ using NormalEstimation =
+ pcl::IntegralImageNormalEstimation<PointXYZRGBA, PointXYZRGBNormal>;
+ using NormalEstimationPtr = NormalEstimation::Ptr;
+ using NormalEstimationConstPtr = NormalEstimation::ConstPtr;
+
+ /** \brief Helper object for the computation thread. Please have a look at the
+ * documentation of calcFPS. */
+ class ComputationFPS : public Base::FPS {
+ public:
+ ComputationFPS() = default;
+ ~ComputationFPS() = default;
+ };
+
+ /** \brief Helper object for the visualization thread. Please have a look at the
+ * documentation of calcFPS. */
+ class VisualizationFPS : public Base::FPS {
+ public:
+ VisualizationFPS() = default;
+ ~VisualizationFPS() = default;
+ };
+
+ /** \brief Get a list of files with from a given directory.
+ *
+ * \param[in] path_dir Path to search for the files.
+ * \param[in] extension File extension (must start with a dot). E.g. '.pcd'.
+ * \param[out] files Paths to the files.
+ *
+ * \return True if success.
+ */
+ bool
+ getFilesFromDirectory(const std::string& path_dir,
+ const std::string& extension,
+ std::vector<std::string>& files) const;
+
+ /** \brief Load the transformation matrix from the given file.
+ *
+ * \param[in] filename Path to the file.
+ * \param[out] transform The loaded transform.
+ *
+ * \return True if success.
+ */
+ bool
+ loadTransform(const std::string& filename, Eigen::Matrix4f& transform) const;
+
+ /** \brief Load the cloud and transformation from the files and compute the normals.
+ *
+ * \param[in] filename Path to the pcd file.
+ * \param[out] cloud Cloud with computed normals.
+ * \param[out] T Loaded transformation.
+ *
+ * \return True if success.
+ */
+ bool
+ load(const std::string& filename,
+ CloudXYZRGBNormalPtr& cloud,
+ Eigen::Matrix4f& T) const;
+
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#paintEvent
+ * \see http://doc.qt.digia.com/qt/opengl-overpainting.html
+ */
+ void
+ paintEvent(QPaintEvent* event) override;
+
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#keyPressEvent */
+ void
+ keyPressEvent(QKeyEvent* event) override;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Members
+ //////////////////////////////////////////////////////////////////////////
+
+ /** \brief Synchronization. */
+ std::mutex mutex_;
+
+ /** \brief Wait until the data finished processing. */
+ std::mutex mutex_quit_;
+
+ /** \brief Please have a look at the documentation of ComputationFPS. */
+ ComputationFPS computation_fps_;
+
+ /** \brief Please have a look at the documentation of VisualizationFPS. */
+ VisualizationFPS visualization_fps_;
+
+ /** \brief Path to the pcd and transformation files. */
+ std::string path_dir_;
+
+ /** \brief Model to which new data is registered to (stored as a mesh). */
+ MeshPtr mesh_model_;
+
+ /** \brief Compute the normals for the input clouds. */
+ NormalEstimationPtr normal_estimation_;
+
+ /** \brief Integrate the data cloud into a common model. */
+ IntegrationPtr integration_;
+
+ /** \brief Prevent the application to crash while closing. */
+ bool destructor_called_;
+
+public:
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+};
+} // End namespace ihs
} // End namespace pcl
#pragma once
+#include <pcl/apps/in_hand_scanner/common_types.h>
+#include <pcl/common/time.h>
#include <pcl/memory.h>
#include <pcl/pcl_exports.h>
#include <pcl/pcl_macros.h>
-#include <pcl/common/time.h>
-#include <pcl/apps/in_hand_scanner/common_types.h>
#include <QGLWidget>
-#include <mutex>
#include <iomanip>
+#include <mutex>
#include <string>
#include <unordered_map>
-namespace pcl
-{
- namespace ihs
- {
- namespace detail
+namespace pcl {
+namespace ihs {
+namespace detail {
+/** \brief Mesh format more efficient for visualization than the half-edge data
+ * structure. \see http://en.wikipedia.org/wiki/Polygon_mesh#Face-vertex_meshes
+ *
+ * \note Only triangles are currently supported.
+ */
+class FaceVertexMesh {
+public:
+ class Triangle {
+ public:
+ Triangle() : first(0), second(0), third(0) {}
+ Triangle(const unsigned int first,
+ const unsigned int second,
+ const unsigned int third)
+ : first(first), second(second), third(third)
+ {}
+
+ unsigned int first;
+ unsigned int second;
+ unsigned int third;
+ };
+
+ /** \brief Constructor */
+ FaceVertexMesh();
+
+ /** \brief Constructor. Converts the input mesh into a face vertex mesh. */
+ FaceVertexMesh(const Mesh& mesh, const Eigen::Isometry3d& T);
+
+ using PointIHS = pcl::ihs::PointIHS;
+ using CloudIHS = pcl::ihs::CloudIHS;
+ using CloudIHSPtr = pcl::ihs::CloudIHSPtr;
+ using CloudIHSConstPtr = pcl::ihs::CloudIHSConstPtr;
+
+ CloudIHS vertices;
+ std::vector<Triangle> triangles;
+ Eigen::Isometry3d transformation;
+
+public:
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+};
+} // End namespace detail
+
+/** \brief Viewer for the in-hand scanner based on Qt and OpenGL.
+ *
+ * \note Currently you have to derive from this class to use it. Implement the
+ * paintEvent: Call the paint event of this class and declare a QPainter.
+ */
+class PCL_EXPORTS OpenGLViewer : public QGLWidget {
+ Q_OBJECT
+
+public:
+ using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
+ using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
+ using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
+ using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
+
+ using Mesh = pcl::ihs::Mesh;
+ using MeshPtr = pcl::ihs::MeshPtr;
+ using MeshConstPtr = pcl::ihs::MeshConstPtr;
+
+ /** \brief How to draw the mesh. */
+ enum MeshRepresentation {
+ MR_POINTS, /**< Draw the points. */
+ MR_EDGES, /**< Wireframe represen of the mesh. */
+ MR_FACES /**< Draw the faces of the mesh without edges. */
+ };
+
+ /** \brief How to color the shapes. */
+ enum Coloring {
+ COL_RGB, /**< Coloring according to the rgb values. */
+ COL_ONE_COLOR, /**< Use one color for all points. */
+ COL_VISCONF /**< Coloring according to the visibility confidence. */
+ };
+
+ /** \brief Coefficients for the wireframe box. */
+ class BoxCoefficients {
+ public:
+ BoxCoefficients()
+ : x_min(0)
+ , x_max(0)
+ , y_min(0)
+ , y_max(0)
+ , z_min(0)
+ , z_max(0)
+ , transformation(Eigen::Isometry3d::Identity())
+ {}
+
+ BoxCoefficients(const float x_min,
+ const float x_max,
+ const float y_min,
+ const float y_max,
+ const float z_min,
+ const float z_max,
+ const Eigen::Isometry3d& T)
+ : x_min(x_min)
+ , x_max(x_max)
+ , y_min(y_min)
+ , y_max(y_max)
+ , z_min(z_min)
+ , z_max(z_max)
+ , transformation(T)
+ {}
+
+ float x_min;
+ float x_max;
+ float y_min;
+ float y_max;
+ float z_min;
+ float z_max;
+ Eigen::Isometry3d transformation;
+
+ public:
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+ };
+
+ /** \brief Constructor. */
+ explicit OpenGLViewer(QWidget* parent = nullptr);
+
+ /** \brief Destructor. */
+ ~OpenGLViewer() override;
+
+ /** \brief Add a mesh to be drawn.
+ *
+ * \param[in] mesh The input mesh.
+ * \param[in] id Unique identifier for the mesh. The internal mesh is replaced by the
+ * input mesh if the id already exists.
+ * \param[in] T Transformation applied to the mesh. Defaults to an identity
+ * transformation.
+ *
+ * \return true if success.
+ *
+ * \note Converts the mesh to the internal representation better suited for
+ * visualization. Therefore this method takes some time.
+ */
+ bool
+ addMesh(const MeshConstPtr& mesh,
+ const std::string& id,
+ const Eigen::Isometry3d& T = Eigen::Isometry3d::Identity());
+
+ /** \brief Convert an organized cloud to a mesh and draw it.
+ *
+ * \param[in] cloud Organized input cloud.
+ * \param[in] id Unique identifier for the mesh. The internal mesh is replaced by the
+ * converted input mesh if the id already exists.
+ * \param[in] T Transformation applied to the mesh. Defaults to an identity
+ * transformation.
+ *
+ * \return true if success.
+ *
+ * \note This method takes some time for the conversion).
+ */
+ bool
+ addMesh(const CloudXYZRGBNormalConstPtr& cloud,
+ const std::string& id,
+ const Eigen::Isometry3d& T = Eigen::Isometry3d::Identity());
+
+ /** \brief Remove the mesh with the given id.
+ *
+ * \param[in] id Identifier of the mesh (results in a failure if the id does not
+ * exist).
+ *
+ * \return true if success.
+ */
+ bool
+ removeMesh(const std::string& id);
+
+ /** \brief Remove all meshes that are currently drawn. */
+ void
+ removeAllMeshes();
+
+ /** \brief Set the coefficients for the box. */
+ void
+ setBoxCoefficients(const BoxCoefficients& coeffs);
+
+ /** \brief Enable / disable drawing the box. */
+ void
+ setDrawBox(const bool enabled);
+
+ /** \brief Check if the box is drawn. */
+ bool
+ getDrawBox() const;
+
+ /** \brief Set the point around which the camera rotates during mouse navigation. */
+ void
+ setPivot(const Eigen::Vector3d& pivot);
+
+ /** \brief Searches the given id in the drawn meshes and calculates the pivot as the
+ * centroid of the found geometry.
+ *
+ * \note Returns immediately and computes the pivot in
+ * another thread.
+ */
+ void
+ setPivot(const std::string& id);
+
+ /** \brief Stop the visualization timer. */
+ void
+ stopTimer();
+
+ /** \brief The visibility confidence is normalized with this value (must be greater
+ * than 1). */
+ void
+ setVisibilityConfidenceNormalization(const float vis_conf_norm);
+
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#minimumSizeHint-prop */
+ QSize
+ minimumSizeHint() const override;
+
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#sizeHint-prop */
+ QSize
+ sizeHint() const override;
+
+ /** \brief Set the scaling factor to convert from meters to the unit of the drawn
+ * files. */
+ void
+ setScalingFactor(const double scale);
+
+public Q_SLOTS:
+
+ /** \brief Requests the scene to be re-drawn (called periodically from a timer). */
+ void
+ timerCallback();
+
+ /** \brief Reset the virtual camera position and orientation. */
+ void
+ resetCamera();
+
+ /** \brief Toggle the mesh representation. */
+ void
+ toggleMeshRepresentation();
+
+ /** \brief Set the mesh representation. */
+ void
+ setMeshRepresentation(const MeshRepresentation& representation);
+
+ /** \brief Toggle the coloring mode. */
+ void
+ toggleColoring();
+
+ /** \brief Set the coloring mode. */
+ void
+ setColoring(const Coloring& coloring);
+
+protected:
+ /** \brief Please have a look at the documentation of calcFPS. */
+ class FPS {
+ public:
+ FPS() : fps_(0.) {}
+
+ inline double&
+ value()
{
- /** \brief Mesh format more efficient for visualization than the half-edge data structure.
- * \see http://en.wikipedia.org/wiki/Polygon_mesh#Face-vertex_meshes
- * \note Only triangles are currently supported.
- */
- class FaceVertexMesh
- {
- public:
-
- class Triangle
- {
- public:
-
- Triangle () : first (0), second (0), third (0) {}
- Triangle (const unsigned int first, const unsigned int second, const unsigned int third)
- : first (first), second (second), third (third)
- {
- }
-
- unsigned int first;
- unsigned int second;
- unsigned int third;
- };
-
- /** \brief Constructor */
- FaceVertexMesh ();
-
- /** \brief Constructor. Converts the input mesh into a face vertex mesh. */
- FaceVertexMesh (const Mesh& mesh, const Eigen::Isometry3d& T);
-
- using PointIHS = pcl::ihs::PointIHS;
- using CloudIHS = pcl::ihs::CloudIHS;
- using CloudIHSPtr = pcl::ihs::CloudIHSPtr;
- using CloudIHSConstPtr = pcl::ihs::CloudIHSConstPtr;
-
- CloudIHS vertices;
- std::vector <Triangle> triangles;
- Eigen::Isometry3d transformation;
-
- public:
- PCL_MAKE_ALIGNED_OPERATOR_NEW
- };
- } // End namespace detail
-
- /** \brief Viewer for the in-hand scanner based on Qt and OpenGL.
- * \note Currently you have to derive from this class to use it. Implement the paintEvent: Call the paint event of this class and declare a QPainter.
- */
- class PCL_EXPORTS OpenGLViewer : public QGLWidget
+ return (fps_);
+ }
+ inline double
+ value() const
{
- Q_OBJECT
-
- public:
-
- using PointXYZRGBNormal = pcl::PointXYZRGBNormal;
- using CloudXYZRGBNormal = pcl::PointCloud<PointXYZRGBNormal>;
- using CloudXYZRGBNormalPtr = CloudXYZRGBNormal::Ptr;
- using CloudXYZRGBNormalConstPtr = CloudXYZRGBNormal::ConstPtr;
-
- using Mesh = pcl::ihs::Mesh;
- using MeshPtr = pcl::ihs::MeshPtr;
- using MeshConstPtr = pcl::ihs::MeshConstPtr;
-
- /** \brief How to draw the mesh. */
- enum MeshRepresentation
- {
- MR_POINTS, /**< Draw the points. */
- MR_EDGES, /**< Wireframe represen of the mesh. */
- MR_FACES /**< Draw the faces of the mesh without edges. */
- };
-
- /** \brief How to color the shapes. */
- enum Coloring
- {
- COL_RGB, /**< Coloring according to the rgb values. */
- COL_ONE_COLOR, /**< Use one color for all points. */
- COL_VISCONF /**< Coloring according to the visibility confidence. */
- };
-
- /** \brief Coefficients for the wireframe box. */
- class BoxCoefficients
- {
- public:
-
- BoxCoefficients ()
- : x_min (0), x_max (0),
- y_min (0), y_max (0),
- z_min (0), z_max (0),
- transformation (Eigen::Isometry3d::Identity ())
- {
- }
-
- BoxCoefficients (const float x_min, const float x_max,
- const float y_min, const float y_max,
- const float z_min, const float z_max,
- const Eigen::Isometry3d& T)
- : x_min (x_min), x_max (x_max),
- y_min (y_min), y_max (y_max),
- z_min (z_min), z_max (z_max),
- transformation (T)
- {
- }
-
- float x_min; float x_max;
- float y_min; float y_max;
- float z_min; float z_max;
- Eigen::Isometry3d transformation;
-
- public:
- PCL_MAKE_ALIGNED_OPERATOR_NEW
- };
-
- /** \brief Constructor. */
- explicit OpenGLViewer (QWidget* parent=nullptr);
-
- /** \brief Destructor. */
- ~OpenGLViewer ();
-
- /** \brief Add a mesh to be drawn.
- * \param[in] mesh The input mesh.
- * \param[in] id Unique identifier for the mesh. The internal mesh is replaced by the input mesh if the id already exists.
- * \param[in] T Transformation applied to the mesh. Defaults to an identity transformation.
- * \return true if success.
- * \note Converts the mesh to the internal representation better suited for visualization. Therefore this method takes some time.
- */
- bool
- addMesh (const MeshConstPtr& mesh, const std::string& id, const Eigen::Isometry3d& T = Eigen::Isometry3d::Identity ());
-
- /** \brief Convert an organized cloud to a mesh and draw it.
- * \param[in] cloud Organized input cloud.
- * \param[in] id Unique identifier for the mesh. The internal mesh is replaced by the converted input mesh if the id already exists.
- * \param[in] T Transformation applied to the mesh. Defaults to an identity transformation.
- * \return true if success.
- * \note This method takes some time for the conversion).
- */
- bool
- addMesh (const CloudXYZRGBNormalConstPtr& cloud, const std::string& id, const Eigen::Isometry3d& T = Eigen::Isometry3d::Identity ());
-
- /** \brief Remove the mesh with the given id.
- * \param[in] id Identifier of the mesh (results in a failure if the id does not exist).
- * \return true if success.
- */
- bool
- removeMesh (const std::string& id);
-
- /** \brief Remove all meshes that are currently drawn. */
- void
- removeAllMeshes ();
-
- /** \brief Set the coefficients for the box. */
- void
- setBoxCoefficients (const BoxCoefficients& coeffs);
-
- /** \brief Enable / disable drawing the box. */
- void
- setDrawBox (const bool enabled);
-
- /** \brief Check if the box is drawn. */
- bool
- getDrawBox () const;
-
- /** \brief Set the point around which the camera rotates during mouse navigation. */
- void
- setPivot (const Eigen::Vector3d& pivot);
-
- /** \brief Searches the given id in the drawn meshes and calculates the pivot as the centroid of the found geometry.
- * \note Returns immediately and computes the pivot in another thread.
- */
- void
- setPivot (const std::string& id);
-
- /** \brief Stop the visualization timer. */
- void
- stopTimer ();
-
- /** \brief The visibility confidence is normalized with this value (must be greater than 1). */
- void
- setVisibilityConfidenceNormalization (const float vis_conf_norm);
-
- /** \see http://doc.qt.digia.com/qt/qwidget.html#minimumSizeHint-prop */
- QSize
- minimumSizeHint () const override;
-
- /** \see http://doc.qt.digia.com/qt/qwidget.html#sizeHint-prop */
- QSize
- sizeHint () const override;
-
- /** \brief Set the scaling factor to convert from meters to the unit of the drawn files. */
- void
- setScalingFactor (const double scale);
-
- public Q_SLOTS:
-
- /** \brief Requests the scene to be re-drawn (called periodically from a timer). */
- void
- timerCallback ();
-
- /** \brief Reset the virtual camera position and orientation. */
- void
- resetCamera ();
-
- /** \brief Toggle the mesh representation. */
- void
- toggleMeshRepresentation ();
-
- /** \brief Set the mesh representation. */
- void
- setMeshRepresentation (const MeshRepresentation& representation);
-
- /** \brief Toggle the coloring mode. */
- void
- toggleColoring ();
-
- /** \brief Set the coloring mode. */
- void
- setColoring (const Coloring& coloring);
-
- protected:
-
- /** \brief Please have a look at the documentation of calcFPS. */
- class FPS
- {
- public:
-
- FPS () : fps_ (0.) {}
-
- inline double& value () {return (fps_);}
- inline double value () const {return (fps_);}
-
- inline std::string
- str () const
- {
- std::stringstream ss;
- ss << std::setprecision (1) << std::fixed << fps_;
- return (ss.str ());
- }
-
- protected:
-
- ~FPS () {}
-
- private:
-
- double fps_;
- };
+ return (fps_);
+ }
- /** Measures the performance of the current thread (selected by passing the corresponding 'fps' helper object). The resulting value is stored in the fps object. */
- template <class FPS> void
- calcFPS (FPS& fps) const
- {
- static pcl::StopWatch sw;
- static unsigned int count = 0;
-
- ++count;
- if (sw.getTimeSeconds () >= .2)
- {
- fps.value () = static_cast <double> (count) / sw.getTimeSeconds ();
- count = 0;
- sw.reset ();
- }
- }
-
- /** \see http://doc.qt.digia.com/qt/qwidget.html#paintEvent
- * \see http://doc.qt.digia.com/qt/opengl-overpainting.html
- */
- void
- paintEvent (QPaintEvent* event) override;
+ inline std::string
+ str() const
+ {
+ std::stringstream ss;
+ ss << std::setprecision(1) << std::fixed << fps_;
+ return (ss.str());
+ }
+
+ protected:
+ ~FPS() = default;
+
+ private:
+ double fps_;
+ };
+
+ /** Measures the performance of the current thread (selected by passing the
+ * corresponding 'fps' helper object). The resulting value is stored in the fps
+ * object. */
+ template <class FPS>
+ void
+ calcFPS(FPS& fps) const
+ {
+ static pcl::StopWatch sw;
+ static unsigned int count = 0;
+
+ ++count;
+ if (sw.getTimeSeconds() >= .2) {
+ fps.value() = static_cast<double>(count) / sw.getTimeSeconds();
+ count = 0;
+ sw.reset();
+ }
+ }
- private:
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#paintEvent
+ * \see http://doc.qt.digia.com/qt/opengl-overpainting.html
+ */
+ void
+ paintEvent(QPaintEvent* event) override;
- using Color = Eigen::Matrix <unsigned char, 3, 1 >;
- using Colors = Eigen::Matrix <unsigned char, 3, Eigen::Dynamic>;
- using Colormap = Eigen::Matrix <unsigned char, 3, 256 >;
+private:
+ using Color = Eigen::Matrix<unsigned char, 3, 1>;
+ using Colors = Eigen::Matrix<unsigned char, 3, Eigen::Dynamic>;
+ using Colormap = Eigen::Matrix<unsigned char, 3, 256>;
- using CloudXYZRGBNormalMap = std::unordered_map <std::string, CloudXYZRGBNormalPtr>;
+ using CloudXYZRGBNormalMap = std::unordered_map<std::string, CloudXYZRGBNormalPtr>;
- using PointIHS = pcl::ihs::PointIHS;
- using CloudIHS = pcl::ihs::CloudIHS;
- using CloudIHSPtr = pcl::ihs::CloudIHSPtr;
- using CloudIHSConstPtr = pcl::ihs::CloudIHSConstPtr;
+ using PointIHS = pcl::ihs::PointIHS;
+ using CloudIHS = pcl::ihs::CloudIHS;
+ using CloudIHSPtr = pcl::ihs::CloudIHSPtr;
+ using CloudIHSConstPtr = pcl::ihs::CloudIHSConstPtr;
- using FaceVertexMesh = pcl::ihs::detail::FaceVertexMesh;
- using FaceVertexMeshPtr = std::shared_ptr<FaceVertexMesh>;
- using FaceVertexMeshConstPtr = std::shared_ptr<const FaceVertexMesh>;
- using FaceVertexMeshMap = std::unordered_map <std::string, FaceVertexMeshPtr>;
+ using FaceVertexMesh = pcl::ihs::detail::FaceVertexMesh;
+ using FaceVertexMeshPtr = std::shared_ptr<FaceVertexMesh>;
+ using FaceVertexMeshConstPtr = std::shared_ptr<const FaceVertexMesh>;
+ using FaceVertexMeshMap = std::unordered_map<std::string, FaceVertexMeshPtr>;
- /** \brief Check if the mesh with the given id is added.
- * \note Must lock the mutex before calling this method.
- */
- bool
- getMeshIsAdded (const std::string& id);
+ /** \brief Check if the mesh with the given id is added.
+ *
+ * \note Must lock the mutex before calling this method.
+ */
+ bool
+ getMeshIsAdded(const std::string& id);
- /** \brief Calculate the pivot for the stored id. */
- void
- calcPivot ();
+ /** \brief Calculate the pivot for the stored id. */
+ void
+ calcPivot();
- /** \brief Draw all meshes.
- * \note Only triangle meshes are currently supported.
- */
- void
- drawMeshes ();
+ /** \brief Draw all meshes.
+ *
+ * \note Only triangle meshes are currently supported.
+ */
+ void
+ drawMeshes();
- /** \brief Draw a wireframe box. */
- void
- drawBox ();
+ /** \brief Draw a wireframe box. */
+ void
+ drawBox();
- /** \see http://doc.qt.digia.com/qt/qglwidget.html#initializeGL */
- void
- initializeGL () override;
+ /** \see http://doc.qt.digia.com/qt/qglwidget.html#initializeGL */
+ void
+ initializeGL() override;
- /** \see http://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml */
- void
- setupViewport (const int w, const int h);
+ /** \see http://www.opengl.org/sdk/docs/man/xhtml/glViewport.xml */
+ void
+ setupViewport(const int w, const int h);
- /** \see http://doc.qt.digia.com/qt/qglwidget.html#resizeGL */
- void
- resizeGL (int w, int h) override;
+ /** \see http://doc.qt.digia.com/qt/qglwidget.html#resizeGL */
+ void
+ resizeGL(int w, int h) override;
- /** \see http://doc.qt.digia.com/qt/qwidget.html#mousePressEvent */
- void
- mousePressEvent (QMouseEvent* event) override;
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#mousePressEvent */
+ void
+ mousePressEvent(QMouseEvent* event) override;
- /** \see http://doc.qt.digia.com/qt/qwidget.html#mouseMoveEvent */
- void
- mouseMoveEvent (QMouseEvent* event) override;
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#mouseMoveEvent */
+ void
+ mouseMoveEvent(QMouseEvent* event) override;
- /** \see http://doc.qt.digia.com/qt/qwidget.html#wheelEvent */
- void
- wheelEvent (QWheelEvent* event) override;
+ /** \see http://doc.qt.digia.com/qt/qwidget.html#wheelEvent */
+ void
+ wheelEvent(QWheelEvent* event) override;
- ////////////////////////////////////////////////////////////////////////
- // Members
- ////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////
+ // Members
+ ////////////////////////////////////////////////////////////////////////
- /** \brief Synchronization. */
- std::mutex mutex_vis_;
+ /** \brief Synchronization. */
+ std::mutex mutex_vis_;
- /** \brief Visualization timer. */
- std::shared_ptr<QTimer> timer_vis_;
+ /** \brief Visualization timer. */
+ std::shared_ptr<QTimer> timer_vis_;
- /** \brief Colormap. */
- Colormap colormap_;
+ /** \brief Colormap. */
+ Colormap colormap_;
- /** \brief The visibility confidence is normalized with this value. */
- float vis_conf_norm_;
+ /** \brief The visibility confidence is normalized with this value. */
+ float vis_conf_norm_;
- /** \brief Meshes stored for visualization. */
- FaceVertexMeshMap drawn_meshes_;
+ /** \brief Meshes stored for visualization. */
+ FaceVertexMeshMap drawn_meshes_;
- /** \brief How to draw the mesh. */
- MeshRepresentation mesh_representation_;
+ /** \brief How to draw the mesh. */
+ MeshRepresentation mesh_representation_;
- /** \brief How to color the shapes. */
- Coloring coloring_;
+ /** \brief How to color the shapes. */
+ Coloring coloring_;
- /** \brief A box is drawn if this value is true. */
- bool draw_box_;
+ /** \brief A box is drawn if this value is true. */
+ bool draw_box_;
- /** \brief Coefficients of the drawn box. */
- BoxCoefficients box_coefficients_;
+ /** \brief Coefficients of the drawn box. */
+ BoxCoefficients box_coefficients_;
- /** \brief Scaling factor to convert from meters to the unit of the drawn files. */
- double scaling_factor_;
+ /** \brief Scaling factor to convert from meters to the unit of the drawn files. */
+ double scaling_factor_;
- /** \brief Rotation of the camera. */
- Eigen::Quaterniond R_cam_;
+ /** \brief Rotation of the camera. */
+ Eigen::Quaterniond R_cam_;
- /** \brief Translation of the camera. */
- Eigen::Vector3d t_cam_;
+ /** \brief Translation of the camera. */
+ Eigen::Vector3d t_cam_;
- /** \brief Center of rotation during mouse navigation. */
- Eigen::Vector3d cam_pivot_;
+ /** \brief Center of rotation during mouse navigation. */
+ Eigen::Vector3d cam_pivot_;
- /** \brief Compute the pivot for the mesh with the given id. */
- std::string cam_pivot_id_;
+ /** \brief Compute the pivot for the mesh with the given id. */
+ std::string cam_pivot_id_;
- /** \brief Set to true right after the mouse got pressed and false if the mouse got moved. */
- bool mouse_pressed_begin_;
+ /** \brief Set to true right after the mouse got pressed and false if the mouse got
+ * moved. */
+ bool mouse_pressed_begin_;
- /** \brief Mouse x-position of the previous mouse move event. */
- int x_prev_;
+ /** \brief Mouse x-position of the previous mouse move event. */
+ int x_prev_;
- /** \brief Mouse y-position of the previous mouse move event. */
- int y_prev_;
+ /** \brief Mouse y-position of the previous mouse move event. */
+ int y_prev_;
- public:
- PCL_MAKE_ALIGNED_OPERATOR_NEW
- };
- } // End namespace ihs
+public:
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+};
+} // End namespace ihs
} // End namespace pcl
// http://doc.qt.digia.com/qt/qmetatype.html#Q_DECLARE_METATYPE
-Q_DECLARE_METATYPE (pcl::ihs::OpenGLViewer::MeshRepresentation)
-Q_DECLARE_METATYPE (pcl::ihs::OpenGLViewer::Coloring)
+Q_DECLARE_METATYPE(pcl::ihs::OpenGLViewer::MeshRepresentation)
+Q_DECLARE_METATYPE(pcl::ihs::OpenGLViewer::Coloring)
#pragma once
-namespace pcl
+namespace pcl {
+namespace ihs {
+/** \brief Clamp the value to the given range. All values smaller than min are set to
+ * min and all values bigger than max are set to max.
+ */
+template <class T>
+inline T
+clamp(const T value, const T min, const T max)
{
- namespace ihs
- {
- /** \brief Clamp the value to the given range. All values smaller than min are set to min and all values bigger than max are set to max. */
- template <class T> inline T
- clamp (const T value, const T min, const T max)
- {
- return (value < min ? min : value > max ? max : value);
- }
- } // End namespace ihs
+ return (value < min ? min : value > max ? max : value);
+}
+} // End namespace ihs
} // End namespace pcl
#pragma once
-#include <cstdint>
-
#include <pcl/memory.h>
#include <pcl/pcl_exports.h>
#include <pcl/pcl_macros.h>
-namespace pcl
-{
- namespace ihs
- {
- // - Frequency 3 Icosahedron where each vertex corresponds to a viewing direction
- // - First vertex aligned to z-axis
- // - Removed vertices with z < 0.3
- // -> 31 directions, fitting nicely into a 32 bit integer
- // -> Very oblique angles are not considered
- class PCL_EXPORTS Dome
- {
- public:
-
- static const int num_directions = 31;
- using Vertices = Eigen::Matrix <float, 4, num_directions>;
+#include <cstdint>
- Dome ();
+namespace pcl {
+namespace ihs {
+// - Frequency 3 Icosahedron where each vertex corresponds to a viewing direction
+// - First vertex aligned to z-axis
+// - Removed vertices with z < 0.3
+// -> 31 directions, fitting nicely into a 32 bit integer
+// -> Very oblique angles are not considered
+class PCL_EXPORTS Dome {
+public:
+ static const int num_directions = 31;
+ using Vertices = Eigen::Matrix<float, 4, num_directions>;
- Vertices
- getVertices () const;
+ Dome();
- private:
+ Vertices
+ getVertices() const;
- Vertices vertices_;
+private:
+ Vertices vertices_;
- public:
- PCL_MAKE_ALIGNED_OPERATOR_NEW
- };
+public:
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+};
- PCL_EXPORTS void
- addDirection (const Eigen::Vector4f& normal,
- const Eigen::Vector4f& direction,
- std::uint32_t& directions);
+PCL_EXPORTS void
+addDirection(const Eigen::Vector4f& normal,
+ const Eigen::Vector4f& direction,
+ std::uint32_t& directions);
- PCL_EXPORTS unsigned int
- countDirections (const std::uint32_t directions);
+PCL_EXPORTS unsigned int
+countDirections(const std::uint32_t directions);
- } // End namespace ihs
+} // End namespace ihs
} // End namespace pcl
*
*/
-
#include <pcl/apps/in_hand_scanner/help_window.h>
+
#include "ui_help_window.h"
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::HelpWindow::HelpWindow (QWidget *parent)
- : QDialog (parent),
- ui (new Ui::HelpWindow)
+pcl::ihs::HelpWindow::HelpWindow(QWidget* parent)
+: QDialog(parent), ui(new Ui::HelpWindow)
{
ui->setupUi(this);
}
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::HelpWindow::~HelpWindow()
-{
- delete ui;
-}
+pcl::ihs::HelpWindow::~HelpWindow() { delete ui; }
////////////////////////////////////////////////////////////////////////////////
*/
#include <pcl/apps/in_hand_scanner/icp.h>
-
-#include <limits>
-#include <cstdlib>
-#include <iomanip>
-#include <cmath>
-
-#include <pcl/kdtree/kdtree_flann.h>
+#include <pcl/apps/in_hand_scanner/utils.h>
#include <pcl/common/centroid.h>
#include <pcl/common/time.h>
+#include <pcl/kdtree/kdtree_flann.h>
-#include <pcl/apps/in_hand_scanner/utils.h>
+#include <cmath>
+#include <cstdlib>
+#include <iomanip>
+#include <limits>
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::ICP::ICP ()
- : kd_tree_ (new pcl::KdTreeFLANN <PointNormal> ()),
+pcl::ihs::ICP::ICP()
+: kd_tree_(new pcl::KdTreeFLANN<PointNormal>())
+,
- epsilon_ (10e-6f),
- max_iterations_ (50),
- min_overlap_ (.75f),
- max_fitness_ (.1f),
+epsilon_(10e-6f)
+, max_iterations_(50)
+, min_overlap_(.75f)
+, max_fitness_(.1f)
+,
- factor_ (9.f),
- max_angle_ (45.f)
-{
-}
+factor_(9.f)
+, max_angle_(45.f)
+{}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::ICP::setEpsilon (const float epsilon)
+pcl::ihs::ICP::setEpsilon(const float epsilon)
{
- if (epsilon > 0) epsilon_ = epsilon;
+ if (epsilon > 0)
+ epsilon_ = epsilon;
}
float
-pcl::ihs::ICP::getEpsilon () const
+pcl::ihs::ICP::getEpsilon() const
{
return (epsilon_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::ICP::setMaxIterations (const unsigned int max_iter)
+pcl::ihs::ICP::setMaxIterations(const unsigned int max_iter)
{
max_iterations_ = max_iter < 1 ? 1 : max_iter;
}
unsigned int
-pcl::ihs::ICP::getMaxIterations () const
+pcl::ihs::ICP::getMaxIterations() const
{
return (max_iterations_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::ICP::setMinOverlap (const float overlap)
+pcl::ihs::ICP::setMinOverlap(const float overlap)
{
- min_overlap_ = pcl::ihs::clamp (overlap, 0.f, 1.f);
+ min_overlap_ = pcl::ihs::clamp(overlap, 0.f, 1.f);
}
float
-pcl::ihs::ICP::getMinOverlap () const
+pcl::ihs::ICP::getMinOverlap() const
{
return (min_overlap_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::ICP::setMaxFitness (const float fitness)
+pcl::ihs::ICP::setMaxFitness(const float fitness)
{
- if (fitness > 0) max_fitness_ = fitness;
+ if (fitness > 0)
+ max_fitness_ = fitness;
}
float
-pcl::ihs::ICP::getMaxFitness () const
+pcl::ihs::ICP::getMaxFitness() const
{
return (max_fitness_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::ICP::setCorrespondenceRejectionFactor (const float factor)
+pcl::ihs::ICP::setCorrespondenceRejectionFactor(const float factor)
{
factor_ = factor < 1.f ? 1.f : factor;
}
float
-pcl::ihs::ICP::getCorrespondenceRejectionFactor () const
+pcl::ihs::ICP::getCorrespondenceRejectionFactor() const
{
return (factor_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::ICP::setMaxAngle (const float angle)
+pcl::ihs::ICP::setMaxAngle(const float angle)
{
- max_angle_ = pcl::ihs::clamp (angle, 0.f, 180.f);
+ max_angle_ = pcl::ihs::clamp(angle, 0.f, 180.f);
}
float
-pcl::ihs::ICP::getMaxAngle () const
+pcl::ihs::ICP::getMaxAngle() const
{
return (max_angle_);
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::ICP::findTransformation (const MeshConstPtr& mesh_model,
- const CloudXYZRGBNormalConstPtr& cloud_data,
- const Eigen::Matrix4f& T_init,
- Eigen::Matrix4f& T_final)
+pcl::ihs::ICP::findTransformation(const MeshConstPtr& mesh_model,
+ const CloudXYZRGBNormalConstPtr& cloud_data,
+ const Eigen::Matrix4f& T_init,
+ Eigen::Matrix4f& T_final)
{
// Check the input
// TODO: Double check the minimum number of points necessary for icp
const std::size_t n_min = 4;
- if(mesh_model->sizeVertices () < n_min || cloud_data->size () < n_min)
- {
+ if (mesh_model->sizeVertices() < n_min || cloud_data->size() < n_min) {
std::cerr << "ERROR in icp.cpp: Not enough input points!\n";
return (false);
}
// Time measurements
pcl::StopWatch sw;
pcl::StopWatch sw_total;
- double t_select = 0.;
- double t_build = 0.;
- double t_nn_search = 0.;
+ double t_select = 0.;
+ double t_build = 0.;
+ double t_nn_search = 0.;
double t_calc_trafo = 0.;
// Convergence and registration failure
- float current_fitness = 0.f;
- float delta_fitness = std::numeric_limits <float>::max ();
- float overlap = std::numeric_limits <float>::quiet_NaN ();
+ float current_fitness = 0.f;
+ float delta_fitness = std::numeric_limits<float>::max();
+ float overlap = std::numeric_limits<float>::quiet_NaN();
// Outlier rejection
float squared_distance_threshold = std::numeric_limits<float>::max();
Eigen::Matrix4f T_cur = T_init;
// Point selection
- sw.reset ();
- const CloudNormalConstPtr cloud_model_selected = this->selectModelPoints (mesh_model, T_init.inverse ());
- const CloudNormalConstPtr cloud_data_selected = this->selectDataPoints (cloud_data);
- t_select = sw.getTime ();
-
- const std::size_t n_model = cloud_model_selected->size ();
- const std::size_t n_data = cloud_data_selected->size ();
- if(n_model < n_min) {std::cerr << "ERROR in icp.cpp: Not enough model points after selection!\n"; return (false);}
- if(n_data < n_min) {std::cerr << "ERROR in icp.cpp: Not enough data points after selection!\n"; return (false);}
+ sw.reset();
+ const CloudNormalConstPtr cloud_model_selected =
+ this->selectModelPoints(mesh_model, T_init.inverse());
+ const CloudNormalConstPtr cloud_data_selected = this->selectDataPoints(cloud_data);
+ t_select = sw.getTime();
+
+ const std::size_t n_model = cloud_model_selected->size();
+ const std::size_t n_data = cloud_data_selected->size();
+ if (n_model < n_min) {
+ std::cerr << "ERROR in icp.cpp: Not enough model points after selection!\n";
+ return (false);
+ }
+ if (n_data < n_min) {
+ std::cerr << "ERROR in icp.cpp: Not enough data points after selection!\n";
+ return (false);
+ }
// Build a kd-tree
- sw.reset ();
- kd_tree_->setInputCloud (cloud_model_selected);
- t_build = sw.getTime ();
+ sw.reset();
+ kd_tree_->setInputCloud(cloud_model_selected);
+ t_build = sw.getTime();
- pcl::Indices index (1);
- std::vector <float> squared_distance (1);
+ pcl::Indices index(1);
+ std::vector<float> squared_distance(1);
// Clouds with one to one correspondences
CloudNormal cloud_model_corr;
CloudNormal cloud_data_corr;
- cloud_model_corr.reserve (n_data);
- cloud_data_corr.reserve (n_data);
+ cloud_model_corr.reserve(n_data);
+ cloud_data_corr.reserve(n_data);
// ICP main loop
unsigned int iter = 1;
PointNormal pt_d;
- const float dot_min = std::cos (max_angle_ * 17.45329252e-3); // deg to rad
- while (true)
- {
+ const float dot_min = std::cos(max_angle_ * 17.45329252e-3); // deg to rad
+ while (true) {
// Accumulated error
float squared_distance_sum = 0.f;
// NN search
- cloud_model_corr.clear ();
- cloud_data_corr.clear ();
- sw.reset ();
- for (CloudNormal::const_iterator it_d = cloud_data_selected->begin (); it_d!=cloud_data_selected->end (); ++it_d)
- {
+ cloud_model_corr.clear();
+ cloud_data_corr.clear();
+ sw.reset();
+ for (CloudNormal::const_iterator it_d = cloud_data_selected->begin();
+ it_d != cloud_data_selected->end();
+ ++it_d) {
// Transform the data point
pt_d = *it_d;
- pt_d.getVector4fMap () = T_cur * pt_d.getVector4fMap ();
- pt_d.getNormalVector4fMap () = T_cur * pt_d.getNormalVector4fMap ();
+ pt_d.getVector4fMap() = T_cur * pt_d.getVector4fMap();
+ pt_d.getNormalVector4fMap() = T_cur * pt_d.getNormalVector4fMap();
// Find the correspondence to the model points
- if (!kd_tree_->nearestKSearch (pt_d, 1, index, squared_distance))
- {
+ if (!kd_tree_->nearestKSearch(pt_d, 1, index, squared_distance)) {
std::cerr << "ERROR in icp.cpp: nearestKSearch failed!\n";
return (false);
}
// Check the distance threshold
- if (squared_distance [0] < squared_distance_threshold)
- {
- if ((std::size_t) index [0] >= cloud_model_selected->size ())
- {
+ if (squared_distance[0] < squared_distance_threshold) {
+ if ((std::size_t)index[0] >= cloud_model_selected->size()) {
std::cerr << "ERROR in icp.cpp: Segfault!\n";
- std::cerr << " Trying to access index " << index [0] << " >= " << cloud_model_selected->size () << std::endl;
- exit (EXIT_FAILURE);
+ std::cerr << " Trying to access index " << index[0]
+ << " >= " << cloud_model_selected->size() << std::endl;
+ exit(EXIT_FAILURE);
}
- const PointNormal& pt_m = cloud_model_selected->operator [] (index [0]);
+ const PointNormal& pt_m = cloud_model_selected->operator[](index[0]);
// Check the normals threshold
- if (pt_m.getNormalVector4fMap ().dot (pt_d.getNormalVector4fMap ()) > dot_min)
- {
- squared_distance_sum += squared_distance [0];
+ if (pt_m.getNormalVector4fMap().dot(pt_d.getNormalVector4fMap()) > dot_min) {
+ squared_distance_sum += squared_distance[0];
- cloud_model_corr.push_back (pt_m);
- cloud_data_corr.push_back (pt_d);
+ cloud_model_corr.push_back(pt_m);
+ cloud_data_corr.push_back(pt_d);
}
}
}
- t_nn_search += sw.getTime ();
+ t_nn_search += sw.getTime();
- const std::size_t n_corr = cloud_data_corr.size ();
- if (n_corr < n_min)
- {
- std::cerr << "ERROR in icp.cpp: Not enough correspondences: " << n_corr << " < " << n_min << std::endl;
+ const std::size_t n_corr = cloud_data_corr.size();
+ if (n_corr < n_min) {
+ std::cerr << "ERROR in icp.cpp: Not enough correspondences: " << n_corr << " < "
+ << n_min << std::endl;
return (false);
}
- // NOTE: The fitness is calculated with the transformation from the previous iteration (I don't re-calculate it after the transformation estimation). This means that the actual fitness will be one iteration "better" than the calculated fitness suggests. This should be no problem because the difference is small at the state of convergence.
+ // NOTE: The fitness is calculated with the transformation from the previous
+ // iteration (I don't re-calculate it after the transformation estimation). This
+ // means that the actual fitness will be one iteration "better" than the calculated
+ // fitness suggests. This should be no problem because the difference is small at
+ // the state of convergence.
float previous_fitness = current_fitness;
- current_fitness = squared_distance_sum / static_cast <float> (n_corr);
- delta_fitness = std::abs (previous_fitness - current_fitness);
+ current_fitness = squared_distance_sum / static_cast<float>(n_corr);
+ delta_fitness = std::abs(previous_fitness - current_fitness);
squared_distance_threshold = factor_ * current_fitness;
- overlap = static_cast <float> (n_corr) / static_cast <float> (n_data);
+ overlap = static_cast<float>(n_corr) / static_cast<float>(n_data);
// std::cerr << "Iter: " << std::left << std::setw(3) << iter
// << " | Overlap: " << std::setprecision(2) << std::setw(4) << overlap
- // << " | current fitness: " << std::setprecision(5) << std::setw(10) << current_fitness
- // << " | delta fitness: " << std::setprecision(5) << std::setw(10) << delta_fitness << std::endl;
+ // << " | current fitness: " << std::setprecision(5) << std::setw(10)
+ // << current_fitness
+ // << " | delta fitness: " << std::setprecision(5) << std::setw(10) <<
+ // delta_fitness << std::endl;
// Minimize the point to plane distance
- sw.reset ();
- Eigen::Matrix4f T_delta = Eigen::Matrix4f::Identity ();
- if (!this->minimizePointPlane (cloud_data_corr, cloud_model_corr, T_delta))
- {
+ sw.reset();
+ Eigen::Matrix4f T_delta = Eigen::Matrix4f::Identity();
+ if (!this->minimizePointPlane(cloud_data_corr, cloud_model_corr, T_delta)) {
std::cerr << "ERROR in icp.cpp: minimizePointPlane failed!\n";
return (false);
}
- t_calc_trafo += sw.getTime ();
+ t_calc_trafo += sw.getTime();
T_cur = T_delta * T_cur;
// Convergence
- if (delta_fitness < epsilon_) break;
+ if (delta_fitness < epsilon_)
+ break;
++iter;
- if (iter > max_iterations_) break;
+ if (iter > max_iterations_)
+ break;
} // End ICP main loop
// Some output
std::cerr << "Registration:\n"
- << " - num model / num data : "
- << std::setw (8) << std::right << n_model << " / "
- << std::setw (8) << std::left << n_data << "\n"
+ << " - num model / num data : " << std::setw(8) << std::right
+ << n_model << " / " << std::setw(8) << std::left << n_data << "\n"
- << std::scientific << std::setprecision (1)
+ << std::scientific << std::setprecision(1)
- << " - delta fitness / epsilon : "
- << std::setw (8) << std::right << delta_fitness << " / "
- << std::setw (8) << std::left << epsilon_
+ << " - delta fitness / epsilon : " << std::setw(8) << std::right
+ << delta_fitness << " / " << std::setw(8) << std::left << epsilon_
<< (delta_fitness < epsilon_ ? " <-- :-)\n" : "\n")
- << " - fitness / max fitness : "
- << std::setw (8) << std::right << current_fitness << " / "
- << std::setw (8) << std::left << max_fitness_
+ << " - fitness / max fitness : " << std::setw(8) << std::right
+ << current_fitness << " / " << std::setw(8) << std::left << max_fitness_
<< (current_fitness > max_fitness_ ? " <-- :-(\n" : "\n")
- << std::fixed << std::setprecision (2)
+ << std::fixed << std::setprecision(2)
- << " - iter / max iter : "
- << std::setw (8) << std::right << iter << " / "
- << std::setw (8) << std::left << max_iterations_
+ << " - iter / max iter : " << std::setw(8) << std::right
+ << iter << " / " << std::setw(8) << std::left << max_iterations_
<< (iter > max_iterations_ ? " <-- :-(\n" : "\n")
- << " - overlap / min overlap : "
- << std::setw (8) << std::right << overlap << " / "
- << std::setw (8) << std::left << min_overlap_
+ << " - overlap / min overlap : " << std::setw(8) << std::right
+ << overlap << " / " << std::setw(8) << std::left << min_overlap_
<< (overlap < min_overlap_ ? " <-- :-(\n" : "\n")
- << std::fixed << std::setprecision (0)
+ << std::fixed << std::setprecision(0)
- << " - time select : "
- << std::setw (8) << std::right << t_select << " ms\n"
+ << " - time select : " << std::setw(8) << std::right
+ << t_select << " ms\n"
- << " - time build kd-tree : "
- << std::setw (8) << std::right << t_build << " ms\n"
+ << " - time build kd-tree : " << std::setw(8) << std::right
+ << t_build << " ms\n"
- << " - time nn-search / trafo / reject: "
- << std::setw (8) << std::right << t_nn_search << " ms\n"
+ << " - time nn-search / trafo / reject: " << std::setw(8) << std::right
+ << t_nn_search << " ms\n"
- << " - time minimize : "
- << std::setw (8) << std::right << t_calc_trafo << " ms\n"
+ << " - time minimize : " << std::setw(8) << std::right
+ << t_calc_trafo << " ms\n"
- << " - total time : "
- << std::setw (8) << std::right << sw_total.getTime () << " ms\n";
+ << " - total time : " << std::setw(8) << std::right
+ << sw_total.getTime() << " ms\n";
- if (iter > max_iterations_ || overlap < min_overlap_ || current_fitness > max_fitness_)
- {
+ if (iter > max_iterations_ || overlap < min_overlap_ ||
+ current_fitness > max_fitness_) {
return (false);
}
- if (delta_fitness <= epsilon_)
- {
+ if (delta_fitness <= epsilon_) {
T_final = T_cur;
return (true);
}
std::cerr << "ERROR in icp.cpp: Congratulations! you found a bug.\n";
- exit (EXIT_FAILURE);
+ exit(EXIT_FAILURE);
}
////////////////////////////////////////////////////////////////////////////////
pcl::ihs::ICP::CloudNormalConstPtr
-pcl::ihs::ICP::selectModelPoints (const MeshConstPtr& mesh_model,
- const Eigen::Matrix4f& T_inv) const
+pcl::ihs::ICP::selectModelPoints(const MeshConstPtr& mesh_model,
+ const Eigen::Matrix4f& T_inv) const
{
- const CloudNormalPtr cloud_model_out (new CloudNormal ());
- cloud_model_out->reserve (mesh_model->sizeVertices ());
+ const CloudNormalPtr cloud_model_out(new CloudNormal());
+ cloud_model_out->reserve(mesh_model->sizeVertices());
- const Mesh::VertexDataCloud& cloud = mesh_model->getVertexDataCloud ();
+ const Mesh::VertexDataCloud& cloud = mesh_model->getVertexDataCloud();
- for (const auto &vertex_data : cloud)
- {
+ for (const auto& vertex_data : cloud) {
// Don't consider points that are facing away from the camera.
- if ((T_inv.lazyProduct (vertex_data.getNormalVector4fMap ())).z () < 0.f)
- {
+ if ((T_inv.lazyProduct(vertex_data.getNormalVector4fMap())).z() < 0.f) {
PointNormal pt;
- pt.getVector4fMap () = vertex_data.getVector4fMap ();
- pt.getNormalVector4fMap () = vertex_data.getNormalVector4fMap ();
+ pt.getVector4fMap() = vertex_data.getVector4fMap();
+ pt.getNormalVector4fMap() = vertex_data.getNormalVector4fMap();
// NOTE: Not the transformed points!!
- cloud_model_out->push_back (pt);
+ cloud_model_out->push_back(pt);
}
}
////////////////////////////////////////////////////////////////////////////////
pcl::ihs::ICP::CloudNormalConstPtr
-pcl::ihs::ICP::selectDataPoints (const CloudXYZRGBNormalConstPtr& cloud_data) const
+pcl::ihs::ICP::selectDataPoints(const CloudXYZRGBNormalConstPtr& cloud_data) const
{
- const CloudNormalPtr cloud_data_out (new CloudNormal ());
- cloud_data_out->reserve (cloud_data->size ());
+ const CloudNormalPtr cloud_data_out(new CloudNormal());
+ cloud_data_out->reserve(cloud_data->size());
- for (const auto &vertex_data : *cloud_data)
- {
- if (!std::isnan (vertex_data.x))
- {
+ for (const auto& vertex_data : *cloud_data) {
+ if (!std::isnan(vertex_data.x)) {
PointNormal pt;
- pt.getVector4fMap () = vertex_data.getVector4fMap ();
- pt.getNormalVector4fMap () = vertex_data.getNormalVector4fMap ();
+ pt.getVector4fMap() = vertex_data.getVector4fMap();
+ pt.getNormalVector4fMap() = vertex_data.getNormalVector4fMap();
- cloud_data_out->push_back (pt);
+ cloud_data_out->push_back(pt);
}
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::ICP::minimizePointPlane (const CloudNormal& cloud_source,
- const CloudNormal& cloud_target,
- Eigen::Matrix4f& T) const
+pcl::ihs::ICP::minimizePointPlane(const CloudNormal& cloud_source,
+ const CloudNormal& cloud_target,
+ Eigen::Matrix4f& T) const
{
// Check the input
// n < n_min already checked in the icp main loop
- const std::size_t n = cloud_source.size ();
- if (cloud_target.size () != n)
- {
+ const std::size_t n = cloud_source.size();
+ if (cloud_target.size() != n) {
std::cerr << "ERROR in icp.cpp: Input must have the same size!\n";
return (false);
}
// For numerical stability
- // - Low: Linear Least-Squares Optimization for Point-to-Plane ICP Surface Registration (2004), in the discussion: "To improve the numerical stability of the computation, it is important to use a unit of distance that is comparable in magnitude with the rotation angles. The simplest way is to rescale and move the two input surfaces so that they are bounded within a unit sphere or cube centered at the origin."
- // - Gelfand et al.: Geometrically Stable Sampling for the ICP Algorithm (2003), in sec 3.1: "As is common with PCA methods, we will shift the center of mass of the points to the origin." ... "Therefore, af- ter shifting the center of mass, we will scale the point set so that the average distance of points from the origin is 1."
- // - Hartley, Zisserman: - Multiple View Geometry (2004), page 109: They normalize to sqrt(2)
+ // - Low: Linear Least-Squares Optimization for Point-to-Plane ICP Surface
+ // Registration (2004), in the discussion: "To improve the numerical stability of the
+ // computation, it is important to use a unit of distance that is comparable in
+ // magnitude with the rotation angles. The simplest way is to rescale and move the two
+ // input surfaces so that they are bounded within a unit sphere or cube centered at
+ // the origin."
+ // - Gelfand et al.: Geometrically Stable Sampling for the ICP Algorithm (2003), in
+ // sec 3.1: "As is common with PCA methods, we will shift the center of mass of the
+ // points to the origin." ... "Therefore, af- ter shifting the center of mass, we will
+ // scale the point set so that the average distance of points from the origin is 1."
+ // - Hartley, Zisserman: - Multiple View Geometry (2004), page 109: They normalize to
+ // sqrt(2)
// TODO: Check the resulting C matrix for the conditioning.
// Subtract the centroid and calculate the scaling factor
- Eigen::Vector4f c_s (0.f, 0.f, 0.f, 1.f);
- Eigen::Vector4f c_t (0.f, 0.f, 0.f, 1.f);
- pcl::compute3DCentroid (cloud_source, c_s); c_s.w () = 1.f;
- pcl::compute3DCentroid (cloud_target, c_t); c_t.w () = 1.f;
+ Eigen::Vector4f c_s(0.f, 0.f, 0.f, 1.f);
+ Eigen::Vector4f c_t(0.f, 0.f, 0.f, 1.f);
+ pcl::compute3DCentroid(cloud_source, c_s);
+ c_s.w() = 1.f;
+ pcl::compute3DCentroid(cloud_target, c_t);
+ c_t.w() = 1.f;
// The normals are only needed for the target
- using Vec4Xf = std::vector <Eigen::Vector4f, Eigen::aligned_allocator <Eigen::Vector4f> >;
+ using Vec4Xf =
+ std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f>>;
Vec4Xf xyz_s, xyz_t, nor_t;
- xyz_s.reserve (n);
- xyz_t.reserve (n);
- nor_t.reserve (n);
+ xyz_s.reserve(n);
+ xyz_t.reserve(n);
+ nor_t.reserve(n);
- CloudNormal::const_iterator it_s = cloud_source.begin ();
- CloudNormal::const_iterator it_t = cloud_target.begin ();
+ CloudNormal::const_iterator it_s = cloud_source.begin();
+ CloudNormal::const_iterator it_t = cloud_target.begin();
float accum = 0.f;
Eigen::Vector4f pt_s, pt_t;
- for (; it_s!=cloud_source.end (); ++it_s, ++it_t)
- {
+ for (; it_s != cloud_source.end(); ++it_s, ++it_t) {
// Subtract the centroid
- pt_s = it_s->getVector4fMap () - c_s;
- pt_t = it_t->getVector4fMap () - c_t;
+ pt_s = it_s->getVector4fMap() - c_s;
+ pt_t = it_t->getVector4fMap() - c_t;
- xyz_s.push_back (pt_s);
- xyz_t.push_back (pt_t);
- nor_t.push_back (it_t->getNormalVector4fMap ());
+ xyz_s.push_back(pt_s);
+ xyz_t.push_back(pt_t);
+ nor_t.push_back(it_t->getNormalVector4fMap());
- // Calculate the radius (L2 norm) of the bounding sphere through both shapes and accumulate the average
+ // Calculate the radius (L2 norm) of the bounding sphere through both shapes and
+ // accumulate the average
// TODO: Change to squared norm and adapt the rest accordingly
- accum += pt_s.head <3> ().norm () + pt_t.head <3> ().norm ();
+ accum += pt_s.head<3>().norm() + pt_t.head<3>().norm();
}
// Inverse factor (do a multiplication instead of division later)
- const float factor = 2.f * static_cast <float> (n) / accum;
- const float factor_squared = factor*factor;
+ const float factor = 2.f * static_cast<float>(n) / accum;
+ const float factor_squared = factor * factor;
// Covariance matrix C
- Eigen::Matrix <float, 6, 6> C;
+ Eigen::Matrix<float, 6, 6> C;
// Right hand side vector b
- Eigen::Matrix <float, 6, 1> b;
+ Eigen::Matrix<float, 6, 1> b;
// For Eigen vectorization: use 4x4 submatrixes instead of 3x3 submatrixes
// -> top left 3x3 matrix will form the final C
// Same for b
- Eigen::Matrix4f C_tl = Eigen::Matrix4f::Zero(); // top left corner
+ Eigen::Matrix4f C_tl = Eigen::Matrix4f::Zero(); // top left corner
Eigen::Matrix4f C_tr_bl = Eigen::Matrix4f::Zero(); // top right / bottom left
- Eigen::Matrix4f C_br = Eigen::Matrix4f::Zero(); // bottom right
+ Eigen::Matrix4f C_br = Eigen::Matrix4f::Zero(); // bottom right
- Eigen::Vector4f b_t = Eigen::Vector4f::Zero(); // top
- Eigen::Vector4f b_b = Eigen::Vector4f::Zero(); // bottom
+ Eigen::Vector4f b_t = Eigen::Vector4f::Zero(); // top
+ Eigen::Vector4f b_b = Eigen::Vector4f::Zero(); // bottom
- Vec4Xf::const_iterator it_xyz_s = xyz_s.begin ();
- Vec4Xf::const_iterator it_xyz_t = xyz_t.begin ();
- Vec4Xf::const_iterator it_nor_t = nor_t.begin ();
+ Vec4Xf::const_iterator it_xyz_s = xyz_s.begin();
+ Vec4Xf::const_iterator it_xyz_t = xyz_t.begin();
+ Vec4Xf::const_iterator it_nor_t = nor_t.begin();
Eigen::Vector4f cross;
- for (; it_xyz_s!=xyz_s.end (); ++it_xyz_s, ++it_xyz_t, ++it_nor_t)
- {
- cross = it_xyz_s->cross3 (*it_nor_t);
+ for (; it_xyz_s != xyz_s.end(); ++it_xyz_s, ++it_xyz_t, ++it_nor_t) {
+ cross = it_xyz_s->cross3(*it_nor_t);
- C_tl += cross * cross. transpose ();
- C_tr_bl += cross * it_nor_t->transpose ();
- C_br += *it_nor_t * it_nor_t->transpose ();
+ C_tl += cross * cross.transpose();
+ C_tr_bl += cross * it_nor_t->transpose();
+ C_br += *it_nor_t * it_nor_t->transpose();
- float dot = (*it_xyz_t-*it_xyz_s).dot (*it_nor_t);
+ float dot = (*it_xyz_t - *it_xyz_s).dot(*it_nor_t);
- b_t += cross * dot;
- b_b += *it_nor_t * dot;
+ b_t += cross * dot;
+ b_b += *it_nor_t * dot;
}
// Scale with the factor and copy the 3x3 submatrixes into C and b
- C_tl *= factor_squared;
+ C_tl *= factor_squared;
C_tr_bl *= factor;
- C << C_tl. topLeftCorner <3, 3> () , C_tr_bl.topLeftCorner <3, 3> (),
- C_tr_bl.topLeftCorner <3, 3> ().transpose(), C_br. topLeftCorner <3, 3> ();
+ C << C_tl.topLeftCorner<3, 3>(), C_tr_bl.topLeftCorner<3, 3>(),
+ C_tr_bl.topLeftCorner<3, 3>().transpose(), C_br.topLeftCorner<3, 3>();
- b << b_t.head <3> () * factor_squared,
- b_b. head <3> () * factor;
+ b << b_t.head<3>() * factor_squared, b_b.head<3>() * factor;
// Solve C * x = b with a Cholesky factorization with pivoting
// x = [alpha; beta; gamma; trans_x; trans_y; trans_z]
- Eigen::Matrix <float, 6, 1> x = C.selfadjointView <Eigen::Lower> ().ldlt ().solve (b);
+ Eigen::Matrix<float, 6, 1> x = C.selfadjointView<Eigen::Lower>().ldlt().solve(b);
// The calculated transformation in the scaled coordinate system
- const float
- sa = std::sin (x (0)),
- ca = std::cos (x (0)),
- sb = std::sin (x (1)),
- cb = std::cos (x (1)),
- sg = std::sin (x (2)),
- cg = std::cos (x (2)),
- tx = x (3),
- ty = x (4),
- tz = x (5);
+ const float sa = std::sin(x(0)), ca = std::cos(x(0)), sb = std::sin(x(1)),
+ cb = std::cos(x(1)), sg = std::sin(x(2)), cg = std::cos(x(2)), tx = x(3),
+ ty = x(4), tz = x(5);
Eigen::Matrix4f TT;
- TT << cg*cb, -sg*ca+cg*sb*sa, sg*sa+cg*sb*ca, tx,
- sg*cb , cg*ca+sg*sb*sa, -cg*sa+sg*sb*ca, ty,
- -sb , cb*sa , cb*ca , tz,
- 0.f , 0.f , 0.f , 1.f;
+ TT << cg * cb, -sg * ca + cg * sb * sa, sg * sa + cg * sb * ca, tx, sg * cb,
+ cg * ca + sg * sb * sa, -cg * sa + sg * sb * ca, ty, -sb, cb * sa, cb * ca, tz,
+ 0.f, 0.f, 0.f, 1.f;
// Transformation matrixes into the local coordinate systems of model/data
Eigen::Matrix4f T_s, T_t;
- T_s << factor, 0.f , 0.f , -c_s.x () * factor,
- 0.f , factor, 0.f , -c_s.y () * factor,
- 0.f , 0.f , factor, -c_s.z () * factor,
- 0.f , 0.f , 0.f , 1.f;
+ T_s << factor, 0.f, 0.f, -c_s.x() * factor, 0.f, factor, 0.f, -c_s.y() * factor, 0.f,
+ 0.f, factor, -c_s.z() * factor, 0.f, 0.f, 0.f, 1.f;
- T_t << factor, 0.f , 0.f , -c_t.x () * factor,
- 0.f , factor, 0.f , -c_t.y () * factor,
- 0.f , 0.f , factor, -c_t.z () * factor,
- 0.f , 0.f , 0.f , 1.f;
+ T_t << factor, 0.f, 0.f, -c_t.x() * factor, 0.f, factor, 0.f, -c_t.y() * factor, 0.f,
+ 0.f, factor, -c_t.z() * factor, 0.f, 0.f, 0.f, 1.f;
// Output transformation T
- T = T_t.inverse () * TT * T_s;
+ T = T_t.inverse() * TT * T_s;
return (true);
}
*
*/
+#include <pcl/apps/in_hand_scanner/icp.h>
#include <pcl/apps/in_hand_scanner/in_hand_scanner.h>
-
-#include <QApplication>
-#include <QtCore>
-#include <QKeyEvent>
-#include <QPainter>
-#include <QtConcurrent>
-
-#include <pcl/exceptions.h>
+#include <pcl/apps/in_hand_scanner/input_data_processing.h>
+#include <pcl/apps/in_hand_scanner/integration.h>
+#include <pcl/apps/in_hand_scanner/mesh_processing.h>
#include <pcl/common/time.h>
#include <pcl/common/transforms.h>
+#include <pcl/geometry/get_boundary.h>
+#include <pcl/geometry/mesh_conversion.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/vtk_io.h>
-#include <pcl/geometry/get_boundary.h>
-#include <pcl/geometry/mesh_conversion.h>
-#include <pcl/apps/in_hand_scanner/icp.h>
-#include <pcl/apps/in_hand_scanner/input_data_processing.h>
-#include <pcl/apps/in_hand_scanner/integration.h>
-#include <pcl/apps/in_hand_scanner/mesh_processing.h>
+#include <pcl/exceptions.h>
+
+#include <QApplication>
+#include <QKeyEvent>
+#include <QPainter>
+#include <QtConcurrent>
+#include <QtCore>
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::InHandScanner::InHandScanner (Base* parent)
- : Base (parent),
- running_mode_ (RM_UNPROCESSED),
- iteration_ (0),
- starting_grabber_ (false),
- input_data_processing_ (new InputDataProcessing ()),
- icp_ (new ICP ()),
- transformation_ (Eigen::Matrix4f::Identity ()),
- integration_ (new Integration ()),
- mesh_processing_ (new MeshProcessing ()),
- mesh_model_ (new Mesh ()),
- destructor_called_ (false)
+pcl::ihs::InHandScanner::InHandScanner(Base* parent)
+: Base(parent)
+, running_mode_(RM_UNPROCESSED)
+, iteration_(0)
+, starting_grabber_(false)
+, input_data_processing_(new InputDataProcessing())
+, icp_(new ICP())
+, transformation_(Eigen::Matrix4f::Identity())
+, integration_(new Integration())
+, mesh_processing_(new MeshProcessing())
+, mesh_model_(new Mesh())
+, destructor_called_(false)
{
// http://doc.qt.digia.com/qt/qmetatype.html#qRegisterMetaType
- qRegisterMetaType <pcl::ihs::InHandScanner::RunningMode> ("RunningMode");
+ qRegisterMetaType<pcl::ihs::InHandScanner::RunningMode>("RunningMode");
- Base::setScalingFactor (0.01);
+ Base::setScalingFactor(0.01);
// Initialize the pivot
- const float x_min = input_data_processing_->getXMin ();
- const float x_max = input_data_processing_->getXMax ();
- const float y_min = input_data_processing_->getYMin ();
- const float y_max = input_data_processing_->getYMax ();
- const float z_min = input_data_processing_->getZMin ();
- const float z_max = input_data_processing_->getZMax ();
-
- Base::setPivot (Eigen::Vector3d ((x_min + x_max) / 2., (y_min + y_max) / 2., (z_min + z_max) / 2.));
+ const float x_min = input_data_processing_->getXMin();
+ const float x_max = input_data_processing_->getXMax();
+ const float y_min = input_data_processing_->getYMin();
+ const float y_max = input_data_processing_->getYMax();
+ const float z_min = input_data_processing_->getZMin();
+ const float z_max = input_data_processing_->getZMax();
+
+ Base::setPivot(Eigen::Vector3d(
+ (x_min + x_max) / 2., (y_min + y_max) / 2., (z_min + z_max) / 2.));
}
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::InHandScanner::~InHandScanner ()
+pcl::ihs::InHandScanner::~InHandScanner()
{
- std::lock_guard<std::mutex> lock (mutex_);
+ std::lock_guard<std::mutex> lock(mutex_);
destructor_called_ = true;
- if (grabber_ && grabber_->isRunning ()) grabber_->stop ();
- if (new_data_connection_.connected ()) new_data_connection_.disconnect ();
+ if (grabber_ && grabber_->isRunning())
+ grabber_->stop();
+ if (new_data_connection_.connected())
+ new_data_connection_.disconnect();
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::startGrabber ()
+pcl::ihs::InHandScanner::startGrabber()
{
- QtConcurrent::run ([this] { startGrabberImpl (); });
+ QtConcurrent::run([this] { startGrabberImpl(); });
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::showUnprocessedData ()
+pcl::ihs::InHandScanner::showUnprocessedData()
{
- std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
std::cerr << "Showing the unprocessed input data.\n";
- Base::setDrawBox (false);
- Base::setColoring (Base::COL_RGB);
+ Base::setDrawBox(false);
+ Base::setColoring(Base::COL_RGB);
running_mode_ = RM_UNPROCESSED;
- emit runningModeChanged (running_mode_);
+ emit runningModeChanged(running_mode_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::showProcessedData ()
+pcl::ihs::InHandScanner::showProcessedData()
{
- std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
std::cerr << "Showing the processed input data.\n";
- Base::setDrawBox (true);
- Base::setColoring (Base::COL_RGB);
+ Base::setDrawBox(true);
+ Base::setColoring(Base::COL_RGB);
running_mode_ = RM_PROCESSED;
- emit runningModeChanged (running_mode_);
+ emit runningModeChanged(running_mode_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::registerContinuously ()
+pcl::ihs::InHandScanner::registerContinuously()
{
- std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
std::cerr << "Continuous registration.\n";
- Base::setDrawBox (true);
- Base::setColoring (Base::COL_VISCONF);
+ Base::setDrawBox(true);
+ Base::setColoring(Base::COL_VISCONF);
running_mode_ = RM_REGISTRATION_CONT;
- emit runningModeChanged (running_mode_);
+ emit runningModeChanged(running_mode_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::registerOnce ()
+pcl::ihs::InHandScanner::registerOnce()
{
- std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
std::cerr << "Single registration.\n";
- Base::setDrawBox (true);
+ Base::setDrawBox(true);
running_mode_ = RM_REGISTRATION_SINGLE;
- emit runningModeChanged (running_mode_);
+ emit runningModeChanged(running_mode_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::showModel ()
+pcl::ihs::InHandScanner::showModel()
{
- std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
std::cerr << "Show the model\n";
- Base::setDrawBox (false);
+ Base::setDrawBox(false);
running_mode_ = RM_SHOW_MODEL;
- emit runningModeChanged (running_mode_);
+ emit runningModeChanged(running_mode_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::removeUnfitVertices ()
+pcl::ihs::InHandScanner::removeUnfitVertices()
{
- std::unique_lock<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
std::cerr << "Removing unfit vertices ...\n";
- integration_->removeUnfitVertices (mesh_model_);
- if (mesh_model_->emptyVertices ())
- {
+ integration_->removeUnfitVertices(mesh_model_);
+ if (mesh_model_->emptyVertices()) {
std::cerr << "Mesh got empty -> Reset\n";
- lock.unlock ();
- this->reset ();
+ lock.unlock();
+ this->reset();
}
- else
- {
- lock.unlock ();
- this->showModel ();
+ else {
+ lock.unlock();
+ this->showModel();
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::reset ()
+pcl::ihs::InHandScanner::reset()
{
- std::unique_lock<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
std::cerr << "Reset the scanning pipeline.\n";
- mesh_model_->clear ();
- Base::removeAllMeshes ();
+ mesh_model_->clear();
+ Base::removeAllMeshes();
- iteration_ = 0;
- transformation_ = Eigen::Matrix4f::Identity ();
+ iteration_ = 0;
+ transformation_ = Eigen::Matrix4f::Identity();
- lock.unlock ();
- this->showUnprocessedData ();
+ lock.unlock();
+ this->showUnprocessedData();
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::saveAs (const std::string& filename, const FileType& filetype)
+pcl::ihs::InHandScanner::saveAs(const std::string& filename, const FileType& filetype)
{
- std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
pcl::PolygonMesh pm;
- pcl::geometry::toFaceVertexMesh (*mesh_model_, pm);
-
- switch (filetype)
- {
- case FT_PLY: pcl::io::savePLYFile (filename, pm); break;
- case FT_VTK: pcl::io::saveVTKFile (filename, pm); break;
- default: break;
+ pcl::geometry::toFaceVertexMesh(*mesh_model_, pm);
+
+ switch (filetype) {
+ case FT_PLY:
+ pcl::io::savePLYFile(filename, pm);
+ break;
+ case FT_VTK:
+ pcl::io::saveVTKFile(filename, pm);
+ break;
+ default:
+ break;
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::keyPressEvent (QKeyEvent* event)
+pcl::ihs::InHandScanner::keyPressEvent(QKeyEvent* event)
{
// Don't allow keyboard callbacks while the grabber is starting up.
- if (starting_grabber_) return;
- if (destructor_called_) return;
-
- switch (event->key ())
- {
- case Qt::Key_1: this->showUnprocessedData (); break;
- case Qt::Key_2: this->showProcessedData (); break;
- case Qt::Key_3: this->registerContinuously (); break;
- case Qt::Key_4: this->registerOnce (); break;
- case Qt::Key_5: this->showModel (); break;
- case Qt::Key_6: this->removeUnfitVertices (); break;
- case Qt::Key_0: this->reset (); break;
- case Qt::Key_C: Base::resetCamera (); break;
- case Qt::Key_K: Base::toggleColoring (); break;
- case Qt::Key_S: Base::toggleMeshRepresentation (); break;
- default: break;
+ if (starting_grabber_)
+ return;
+ if (destructor_called_)
+ return;
+
+ switch (event->key()) {
+ case Qt::Key_1:
+ this->showUnprocessedData();
+ break;
+ case Qt::Key_2:
+ this->showProcessedData();
+ break;
+ case Qt::Key_3:
+ this->registerContinuously();
+ break;
+ case Qt::Key_4:
+ this->registerOnce();
+ break;
+ case Qt::Key_5:
+ this->showModel();
+ break;
+ case Qt::Key_6:
+ this->removeUnfitVertices();
+ break;
+ case Qt::Key_0:
+ this->reset();
+ break;
+ case Qt::Key_C:
+ Base::resetCamera();
+ break;
+ case Qt::Key_K:
+ Base::toggleColoring();
+ break;
+ case Qt::Key_S:
+ Base::toggleMeshRepresentation();
+ break;
+ default:
+ break;
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::newDataCallback (const CloudXYZRGBAConstPtr& cloud_in)
+pcl::ihs::InHandScanner::newDataCallback(const CloudXYZRGBAConstPtr& cloud_in)
{
- Base::calcFPS (computation_fps_); // Must come before the lock!
+ Base::calcFPS(computation_fps_); // Must come before the lock!
- std::unique_lock<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::unique_lock<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
pcl::StopWatch sw;
// Input data processing
CloudXYZRGBNormalPtr cloud_data;
CloudXYZRGBNormalPtr cloud_discarded;
- if (running_mode_ == RM_SHOW_MODEL)
- {
- cloud_data = CloudXYZRGBNormalPtr (new CloudXYZRGBNormal ());
+ if (running_mode_ == RM_SHOW_MODEL) {
+ cloud_data = CloudXYZRGBNormalPtr(new CloudXYZRGBNormal());
}
- else if (running_mode_ == RM_UNPROCESSED)
- {
- if (!input_data_processing_->calculateNormals (cloud_in, cloud_data))
+ else if (running_mode_ == RM_UNPROCESSED) {
+ if (!input_data_processing_->calculateNormals(cloud_in, cloud_data))
return;
}
- else if (running_mode_ >= RM_PROCESSED)
- {
- if (!input_data_processing_->segment (cloud_in, cloud_data, cloud_discarded))
+ else if (running_mode_ >= RM_PROCESSED) {
+ if (!input_data_processing_->segment(cloud_in, cloud_data, cloud_discarded))
return;
}
- double time_input_data_processing = sw.getTime ();
+ double time_input_data_processing = sw.getTime();
// Registration & integration
- if (running_mode_ >= RM_REGISTRATION_CONT)
- {
+ if (running_mode_ >= RM_REGISTRATION_CONT) {
std::cerr << "\nGlobal iteration " << iteration_ << "\n";
std::cerr << "Input data processing:\n"
- << " - time : "
- << std::setw (8) << std::right << time_input_data_processing << " ms\n";
+ << " - time : " << std::setw(8) << std::right
+ << time_input_data_processing << " ms\n";
- if (iteration_ == 0)
- {
- transformation_ = Eigen::Matrix4f::Identity ();
+ if (iteration_ == 0) {
+ transformation_ = Eigen::Matrix4f::Identity();
- sw.reset ();
- integration_->reconstructMesh (cloud_data, mesh_model_);
+ sw.reset();
+ integration_->reconstructMesh(cloud_data, mesh_model_);
std::cerr << "Integration:\n"
- << " - time reconstruct mesh : "
- << std::setw (8) << std::right << sw.getTime () << " ms\n";
+ << " - time reconstruct mesh : " << std::setw(8) << std::right
+ << sw.getTime() << " ms\n";
- cloud_data = CloudXYZRGBNormalPtr (new CloudXYZRGBNormal ());
+ cloud_data = CloudXYZRGBNormalPtr(new CloudXYZRGBNormal());
++iteration_;
}
- else
- {
- Eigen::Matrix4f T_final = Eigen::Matrix4f::Identity ();
- if (icp_->findTransformation (mesh_model_, cloud_data, transformation_, T_final))
- {
+ else {
+ Eigen::Matrix4f T_final = Eigen::Matrix4f::Identity();
+ if (icp_->findTransformation(mesh_model_, cloud_data, transformation_, T_final)) {
transformation_ = T_final;
- sw.reset ();
- integration_->merge (cloud_data, mesh_model_, transformation_);
+ sw.reset();
+ integration_->merge(cloud_data, mesh_model_, transformation_);
std::cerr << "Integration:\n"
- << " - time merge : "
- << std::setw (8) << std::right << sw.getTime () << " ms\n";
-
- sw.reset ();
- integration_->age (mesh_model_);
- std::cerr << " - time age : "
- << std::setw (8) << std::right << sw.getTime () << " ms\n";
-
- sw.reset ();
- std::vector <Mesh::HalfEdgeIndices> boundary_collection;
- pcl::geometry::getBoundBoundaryHalfEdges (*mesh_model_, boundary_collection, 1000);
- std::cerr << " - time compute boundary : "
- << std::setw (8) << std::right << sw.getTime () << " ms\n";
-
- sw.reset ();
- mesh_processing_->processBoundary (*mesh_model_, boundary_collection);
- std::cerr << " - time mesh processing : "
- << std::setw (8) << std::right << sw.getTime () << " ms\n";
-
- cloud_data = CloudXYZRGBNormalPtr (new CloudXYZRGBNormal ());
+ << " - time merge : " << std::setw(8)
+ << std::right << sw.getTime() << " ms\n";
+
+ sw.reset();
+ integration_->age(mesh_model_);
+ std::cerr << " - time age : " << std::setw(8)
+ << std::right << sw.getTime() << " ms\n";
+
+ sw.reset();
+ std::vector<Mesh::HalfEdgeIndices> boundary_collection;
+ pcl::geometry::getBoundBoundaryHalfEdges(
+ *mesh_model_, boundary_collection, 1000);
+ std::cerr << " - time compute boundary : " << std::setw(8)
+ << std::right << sw.getTime() << " ms\n";
+
+ sw.reset();
+ mesh_processing_->processBoundary(*mesh_model_, boundary_collection);
+ std::cerr << " - time mesh processing : " << std::setw(8)
+ << std::right << sw.getTime() << " ms\n";
+
+ cloud_data = CloudXYZRGBNormalPtr(new CloudXYZRGBNormal());
++iteration_;
}
}
// Visualization & copy back some variables
double time_model = 0;
- double time_data = 0;
+ double time_data = 0;
- if (mesh_model_->empty ()) Base::setPivot ("data");
- else Base::setPivot ("model");
+ if (mesh_model_->empty())
+ Base::setPivot("data");
+ else
+ Base::setPivot("model");
- sw.reset ();
- Base::addMesh (mesh_model_, "model", Eigen::Isometry3d (transformation_.inverse ().cast <double> ()));
- time_model = sw.getTime ();
+ sw.reset();
+ Base::addMesh(mesh_model_,
+ "model",
+ Eigen::Isometry3d(transformation_.inverse().cast<double>()));
+ time_model = sw.getTime();
- sw.reset ();
- Base::addMesh (cloud_data , "data"); // Converts to a mesh for visualization
+ sw.reset();
+ Base::addMesh(cloud_data, "data"); // Converts to a mesh for visualization
- if (running_mode_ < RM_REGISTRATION_CONT && cloud_discarded)
- {
- Base::addMesh (cloud_discarded, "cloud_discarded");
+ if (running_mode_ < RM_REGISTRATION_CONT && cloud_discarded) {
+ Base::addMesh(cloud_discarded, "cloud_discarded");
}
- else
- {
- Base::removeMesh ("cloud_discarded");
+ else {
+ Base::removeMesh("cloud_discarded");
}
- time_data = sw.getTime ();
+ time_data = sw.getTime();
- if (running_mode_ >= RM_REGISTRATION_CONT)
- {
+ if (running_mode_ >= RM_REGISTRATION_CONT) {
std::cerr << "Copy to visualization thread:\n"
- << " - time model : "
- << std::setw (8) << std::right << time_model << " ms\n"
- << " - time data : "
- << std::setw (8) << std::right << time_data << " ms\n";
+ << " - time model : " << std::setw(8) << std::right
+ << time_model << " ms\n"
+ << " - time data : " << std::setw(8) << std::right
+ << time_data << " ms\n";
}
- if (running_mode_ == RM_REGISTRATION_SINGLE)
- {
- lock.unlock ();
- this->showProcessedData ();
+ if (running_mode_ == RM_REGISTRATION_SINGLE) {
+ lock.unlock();
+ this->showProcessedData();
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::paintEvent (QPaintEvent* event)
+pcl::ihs::InHandScanner::paintEvent(QPaintEvent* event)
{
- // std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
-
- Base::calcFPS (visualization_fps_);
- Base::BoxCoefficients coeffs (input_data_processing_->getXMin (),
- input_data_processing_->getXMax (),
- input_data_processing_->getYMin (),
- input_data_processing_->getYMax (),
- input_data_processing_->getZMin (),
- input_data_processing_->getZMax (),
- Eigen::Isometry3d::Identity ());
- Base::setBoxCoefficients (coeffs);
-
- Base::setVisibilityConfidenceNormalization (static_cast <float> (integration_->getMinDirections ()));
- // lock.unlock ();
-
- Base::paintEvent (event);
- this->drawText (); // NOTE: Must come AFTER the opengl calls
+ if (destructor_called_)
+ return;
+
+ Base::calcFPS(visualization_fps_);
+ Base::BoxCoefficients coeffs(input_data_processing_->getXMin(),
+ input_data_processing_->getXMax(),
+ input_data_processing_->getYMin(),
+ input_data_processing_->getYMax(),
+ input_data_processing_->getZMin(),
+ input_data_processing_->getZMax(),
+ Eigen::Isometry3d::Identity());
+ Base::setBoxCoefficients(coeffs);
+
+ Base::setVisibilityConfidenceNormalization(
+ static_cast<float>(integration_->getMinDirections()));
+
+ Base::paintEvent(event);
+ this->drawText(); // NOTE: Must come AFTER the opengl calls
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::drawText ()
+pcl::ihs::InHandScanner::drawText()
{
- QPainter painter (this);
- painter.setPen (Qt::white);
+ QPainter painter(this);
+ painter.setPen(Qt::white);
QFont font;
- if (starting_grabber_)
- {
- font.setPointSize (this->width () / 20);
- painter.setFont (font);
- painter.drawText (0, 0, this->width (), this->height (), Qt::AlignHCenter | Qt::AlignVCenter, "Starting the grabber.\n Please wait.");
+ if (starting_grabber_) {
+ font.setPointSize(this->width() / 20);
+ painter.setFont(font);
+ painter.drawText(0,
+ 0,
+ this->width(),
+ this->height(),
+ Qt::AlignHCenter | Qt::AlignVCenter,
+ "Starting the grabber.\n Please wait.");
}
- else
- {
- std::string vis_fps ("Visualization: "), comp_fps ("Computation: ");
+ else {
+ std::string vis_fps("Visualization: "), comp_fps("Computation: ");
- vis_fps.append (visualization_fps_.str ()).append (" fps");
- comp_fps.append (computation_fps_.str ()).append (" fps");
+ vis_fps.append(visualization_fps_.str()).append(" fps");
+ comp_fps.append(computation_fps_.str()).append(" fps");
- const std::string str = std::string (comp_fps).append ("\n").append (vis_fps);
+ const std::string str = std::string(comp_fps).append("\n").append(vis_fps);
- font.setPointSize (this->width () / 50);
+ font.setPointSize(this->width() / 50);
- painter.setFont (font);
- painter.drawText (0, 0, this->width (), this->height (), Qt::AlignBottom | Qt::AlignLeft, str.c_str ());
+ painter.setFont(font);
+ painter.drawText(0,
+ 0,
+ this->width(),
+ this->height(),
+ Qt::AlignBottom | Qt::AlignLeft,
+ str.c_str());
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InHandScanner::startGrabberImpl ()
+pcl::ihs::InHandScanner::startGrabberImpl()
{
- std::unique_lock<std::mutex> lock (mutex_);
+ std::unique_lock<std::mutex> lock(mutex_);
starting_grabber_ = true;
- lock.unlock ();
+ lock.unlock();
- try
- {
- grabber_ = GrabberPtr (new Grabber ());
- }
- catch (const pcl::PCLException& e)
- {
- std::cerr << "ERROR in in_hand_scanner.cpp: " << e.what () << std::endl;
- exit (EXIT_FAILURE);
+ try {
+ grabber_ = GrabberPtr(new Grabber());
+ } catch (const pcl::PCLException& e) {
+ std::cerr << "ERROR in in_hand_scanner.cpp: " << e.what() << std::endl;
+ exit(EXIT_FAILURE);
}
- lock.lock ();
- if (destructor_called_) return;
+ lock.lock();
+ if (destructor_called_)
+ return;
- std::function <void (const CloudXYZRGBAConstPtr&)> new_data_cb = [this] (const CloudXYZRGBAConstPtr& cloud) { newDataCallback (cloud); };
- new_data_connection_ = grabber_->registerCallback (new_data_cb);
- grabber_->start ();
+ std::function<void(const CloudXYZRGBAConstPtr&)> new_data_cb =
+ [this](const CloudXYZRGBAConstPtr& cloud) { newDataCallback(cloud); };
+ new_data_connection_ = grabber_->registerCallback(new_data_cb);
+ grabber_->start();
starting_grabber_ = false;
}
*/
#include <pcl/apps/in_hand_scanner/input_data_processing.h>
-
#include <pcl/common/point_tests.h>
#include <pcl/features/integral_image_normal.h>
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::InputDataProcessing::InputDataProcessing ()
- : normal_estimation_ (new NormalEstimation ()),
-
- x_min_ (-15.f),
- x_max_ ( 15.f),
- y_min_ (-15.f),
- y_max_ ( 15.f),
- z_min_ ( 48.f),
- z_max_ ( 70.f),
-
- h_min_ (210.f),
- h_max_ (270.f),
- s_min_ ( 0.2f),
- s_max_ ( 1.f),
- v_min_ ( 0.2f),
- v_max_ ( 1.f),
-
- hsv_inverted_ (false),
- hsv_enabled_ (true),
-
- size_dilate_ (3),
- size_erode_ (3)
+pcl::ihs::InputDataProcessing::InputDataProcessing()
+: normal_estimation_(new NormalEstimation())
+, x_min_(-15.f)
+, x_max_(15.f)
+, y_min_(-15.f)
+, y_max_(15.f)
+, z_min_(48.f)
+, z_max_(70.f)
+, h_min_(210.f)
+, h_max_(270.f)
+, s_min_(0.2f)
+, s_max_(1.f)
+, v_min_(0.2f)
+, v_max_(1.f)
+, hsv_inverted_(false)
+, hsv_enabled_(true)
+, size_dilate_(3)
+, size_erode_(3)
{
// Normal estimation
- normal_estimation_->setNormalEstimationMethod (NormalEstimation::AVERAGE_3D_GRADIENT);
- normal_estimation_->setMaxDepthChangeFactor (0.02f); // in meters
- normal_estimation_->setNormalSmoothingSize (10.0f);
+ normal_estimation_->setNormalEstimationMethod(NormalEstimation::AVERAGE_3D_GRADIENT);
+ normal_estimation_->setMaxDepthChangeFactor(0.02f); // in meters
+ normal_estimation_->setNormalSmoothingSize(10.0f);
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::InputDataProcessing::segment (const CloudXYZRGBAConstPtr& cloud_in,
- CloudXYZRGBNormalPtr& cloud_out,
- CloudXYZRGBNormalPtr& cloud_discarded) const
+pcl::ihs::InputDataProcessing::segment(const CloudXYZRGBAConstPtr& cloud_in,
+ CloudXYZRGBNormalPtr& cloud_out,
+ CloudXYZRGBNormalPtr& cloud_discarded) const
{
- if (!cloud_in)
- {
+ if (!cloud_in) {
std::cerr << "ERROR in input_data_processing.cpp: Input cloud is invalid.\n";
return (false);
}
- if (!cloud_in->isOrganized ())
- {
+ if (!cloud_in->isOrganized()) {
std::cerr << "ERROR in input_data_processing.cpp: Input cloud must be organized.\n";
return (false);
}
- if (!cloud_out) cloud_out = CloudXYZRGBNormalPtr (new CloudXYZRGBNormal ());
- if (!cloud_discarded) cloud_discarded = CloudXYZRGBNormalPtr (new CloudXYZRGBNormal ());
+ if (!cloud_out)
+ cloud_out = CloudXYZRGBNormalPtr(new CloudXYZRGBNormal());
+ if (!cloud_discarded)
+ cloud_discarded = CloudXYZRGBNormalPtr(new CloudXYZRGBNormal());
- const unsigned int width = cloud_in->width;
+ const unsigned int width = cloud_in->width;
const unsigned int height = cloud_in->height;
// Calculate the normals
- CloudNormalsPtr cloud_normals (new CloudNormals ());
- normal_estimation_->setInputCloud (cloud_in);
- normal_estimation_->compute (*cloud_normals);
+ CloudNormalsPtr cloud_normals(new CloudNormals());
+ normal_estimation_->setInputCloud(cloud_in);
+ normal_estimation_->compute(*cloud_normals);
// Get the XYZ and HSV masks.
- MatrixXb xyz_mask (height, width);
- MatrixXb hsv_mask (height, width);
+ MatrixXb xyz_mask(height, width);
+ MatrixXb hsv_mask(height, width);
// cm -> m for the comparison
const float x_min = .01f * x_min_;
const float z_max = .01f * z_max_;
float h, s, v;
- for (MatrixXb::Index r=0; r<xyz_mask.rows (); ++r)
- {
- for (MatrixXb::Index c=0; c<xyz_mask.cols (); ++c)
- {
- const PointXYZRGBA& xyzrgb = (*cloud_in) [r*width + c];
- const Normal& normal = (*cloud_normals) [r*width + c];
-
- xyz_mask (r, c) = hsv_mask (r, c) = false;
-
- if (!std::isnan (xyzrgb.x) && !std::isnan (normal.normal_x) &&
- xyzrgb.x >= x_min && xyzrgb.x <= x_max &&
- xyzrgb.y >= y_min && xyzrgb.y <= y_max &&
- xyzrgb.z >= z_min && xyzrgb.z <= z_max)
- {
- xyz_mask (r, c) = true;
-
- this->RGBToHSV (xyzrgb.r, xyzrgb.g, xyzrgb.b, h, s, v);
- if (h >= h_min_ && h <= h_max_ && s >= s_min_ && s <= s_max_ && v >= v_min_ && v <= v_max_)
- {
- if (!hsv_inverted_) hsv_mask (r, c) = true;
+ for (MatrixXb::Index r = 0; r < xyz_mask.rows(); ++r) {
+ for (MatrixXb::Index c = 0; c < xyz_mask.cols(); ++c) {
+ const PointXYZRGBA& xyzrgb = (*cloud_in)[r * width + c];
+ const Normal& normal = (*cloud_normals)[r * width + c];
+
+ xyz_mask(r, c) = hsv_mask(r, c) = false;
+
+ if (!std::isnan(xyzrgb.x) && !std::isnan(normal.normal_x) && xyzrgb.x >= x_min &&
+ xyzrgb.x <= x_max && xyzrgb.y >= y_min && xyzrgb.y <= y_max &&
+ xyzrgb.z >= z_min && xyzrgb.z <= z_max) {
+ xyz_mask(r, c) = true;
+
+ this->RGBToHSV(xyzrgb.r, xyzrgb.g, xyzrgb.b, h, s, v);
+ if (h >= h_min_ && h <= h_max_ && s >= s_min_ && s <= s_max_ && v >= v_min_ &&
+ v <= v_max_) {
+ if (!hsv_inverted_)
+ hsv_mask(r, c) = true;
}
- else
- {
- if (hsv_inverted_) hsv_mask (r, c) = true;
+ else {
+ if (hsv_inverted_)
+ hsv_mask(r, c) = true;
}
}
}
}
- this->erode (xyz_mask, size_erode_);
- if (hsv_enabled_) this->dilate (hsv_mask, size_dilate_);
- else hsv_mask.setZero ();
+ this->erode(xyz_mask, size_erode_);
+ if (hsv_enabled_)
+ this->dilate(hsv_mask, size_dilate_);
+ else
+ hsv_mask.setZero();
// Copy the normals into the clouds.
- cloud_out->reserve (cloud_in->size ());
- cloud_discarded->reserve (cloud_in->size ());
+ cloud_out->reserve(cloud_in->size());
+ cloud_discarded->reserve(cloud_in->size());
pcl::PointXYZRGBNormal pt_out, pt_discarded;
pt_discarded.r = 50;
pt_discarded.b = 230;
PointXYZRGBA xyzrgb;
- Normal normal;
+ Normal normal;
- for (MatrixXb::Index r=0; r<xyz_mask.rows (); ++r)
- {
- for (MatrixXb::Index c=0; c<xyz_mask.cols (); ++c)
- {
- if (xyz_mask (r, c))
- {
- xyzrgb = (*cloud_in) [r*width + c];
- normal = (*cloud_normals) [r*width + c];
+ for (MatrixXb::Index r = 0; r < xyz_mask.rows(); ++r) {
+ for (MatrixXb::Index c = 0; c < xyz_mask.cols(); ++c) {
+ if (xyz_mask(r, c)) {
+ xyzrgb = (*cloud_in)[r * width + c];
+ normal = (*cloud_normals)[r * width + c];
// m -> cm
- xyzrgb.getVector3fMap () = 100.f * xyzrgb.getVector3fMap ();
+ xyzrgb.getVector3fMap() = 100.f * xyzrgb.getVector3fMap();
- if (hsv_mask (r, c))
- {
- pt_discarded.getVector4fMap () = xyzrgb.getVector4fMap ();
- pt_discarded.getNormalVector4fMap () = normal.getNormalVector4fMap ();
+ if (hsv_mask(r, c)) {
+ pt_discarded.getVector4fMap() = xyzrgb.getVector4fMap();
+ pt_discarded.getNormalVector4fMap() = normal.getNormalVector4fMap();
- pt_out.x = std::numeric_limits <float>::quiet_NaN ();
+ pt_out.x = std::numeric_limits<float>::quiet_NaN();
}
- else
- {
- pt_out.getVector4fMap () = xyzrgb.getVector4fMap ();
- pt_out.getNormalVector4fMap () = normal.getNormalVector4fMap ();
- pt_out.rgba = xyzrgb.rgba;
+ else {
+ pt_out.getVector4fMap() = xyzrgb.getVector4fMap();
+ pt_out.getNormalVector4fMap() = normal.getNormalVector4fMap();
+ pt_out.rgba = xyzrgb.rgba;
- pt_discarded.x = std::numeric_limits <float>::quiet_NaN ();
+ pt_discarded.x = std::numeric_limits<float>::quiet_NaN();
}
}
- else
- {
- pt_out.x = std::numeric_limits <float>::quiet_NaN ();
- pt_discarded.x = std::numeric_limits <float>::quiet_NaN ();
+ else {
+ pt_out.x = std::numeric_limits<float>::quiet_NaN();
+ pt_discarded.x = std::numeric_limits<float>::quiet_NaN();
}
- cloud_out->push_back (pt_out);
- cloud_discarded->push_back (pt_discarded);
+ cloud_out->push_back(pt_out);
+ cloud_discarded->push_back(pt_discarded);
}
}
- cloud_out->width = cloud_discarded->width = width;
- cloud_out->height = cloud_discarded->height = height;
+ cloud_out->width = cloud_discarded->width = width;
+ cloud_out->height = cloud_discarded->height = height;
cloud_out->is_dense = cloud_discarded->is_dense = false;
return (true);
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::InputDataProcessing::calculateNormals (const CloudXYZRGBAConstPtr& cloud_in,
- CloudXYZRGBNormalPtr& cloud_out) const
+pcl::ihs::InputDataProcessing::calculateNormals(const CloudXYZRGBAConstPtr& cloud_in,
+ CloudXYZRGBNormalPtr& cloud_out) const
{
- if (!cloud_in)
- {
+ if (!cloud_in) {
std::cerr << "ERROR in input_data_processing.cpp: Input cloud is invalid.\n";
return (false);
}
if (!cloud_out)
- cloud_out = CloudXYZRGBNormalPtr (new CloudXYZRGBNormal ());
+ cloud_out = CloudXYZRGBNormalPtr(new CloudXYZRGBNormal());
// Calculate the normals
- CloudNormalsPtr cloud_normals (new CloudNormals ());
- normal_estimation_->setInputCloud (cloud_in);
- normal_estimation_->compute (*cloud_normals);
+ CloudNormalsPtr cloud_normals(new CloudNormals());
+ normal_estimation_->setInputCloud(cloud_in);
+ normal_estimation_->compute(*cloud_normals);
// Copy the input cloud and normals into the output cloud.
- cloud_out->resize (cloud_in->size ());
- cloud_out->width = cloud_in->width;
- cloud_out->height = cloud_in->height;
+ cloud_out->resize(cloud_in->size());
+ cloud_out->width = cloud_in->width;
+ cloud_out->height = cloud_in->height;
cloud_out->is_dense = false;
- CloudNormals::const_iterator it_n = cloud_normals->begin ();
- CloudXYZRGBNormal::iterator it_out = cloud_out->begin ();
+ CloudNormals::const_iterator it_n = cloud_normals->begin();
+ CloudXYZRGBNormal::iterator it_out = cloud_out->begin();
PointXYZRGBNormal invalid_pt;
- invalid_pt.x = invalid_pt.y = invalid_pt.z = std::numeric_limits <float>::quiet_NaN ();
- invalid_pt.normal_x = invalid_pt.normal_y = invalid_pt.normal_z = std::numeric_limits <float>::quiet_NaN ();
- invalid_pt.data [3] = 1.f;
- invalid_pt.data_n [3] = 0.f;
-
- for (auto it_in = cloud_in->begin (); it_in!=cloud_in->end (); ++it_in, ++it_n, ++it_out)
- {
- if (!it_n->getNormalVector4fMap (). hasNaN ())
- {
+ invalid_pt.x = invalid_pt.y = invalid_pt.z = std::numeric_limits<float>::quiet_NaN();
+ invalid_pt.normal_x = invalid_pt.normal_y = invalid_pt.normal_z =
+ std::numeric_limits<float>::quiet_NaN();
+ invalid_pt.data[3] = 1.f;
+ invalid_pt.data_n[3] = 0.f;
+
+ for (auto it_in = cloud_in->begin(); it_in != cloud_in->end();
+ ++it_in, ++it_n, ++it_out) {
+ if (!it_n->getNormalVector4fMap().hasNaN()) {
// m -> cm
- it_out->getVector4fMap () = 100.f * it_in->getVector4fMap ();
- it_out->data [3] = 1.f;
- it_out->rgba = it_in->rgba;
- it_out->getNormalVector4fMap () = it_n->getNormalVector4fMap ();
+ it_out->getVector4fMap() = 100.f * it_in->getVector4fMap();
+ it_out->data[3] = 1.f;
+ it_out->rgba = it_in->rgba;
+ it_out->getNormalVector4fMap() = it_n->getNormalVector4fMap();
}
- else
- {
+ else {
*it_out = invalid_pt;
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InputDataProcessing::erode (MatrixXb& mask, const int k) const
+pcl::ihs::InputDataProcessing::erode(MatrixXb& mask, const int k) const
{
- mask = manhattan (mask, false).array () > k;
+ mask = manhattan(mask, false).array() > k;
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InputDataProcessing::dilate (MatrixXb& mask, const int k) const
+pcl::ihs::InputDataProcessing::dilate(MatrixXb& mask, const int k) const
{
- mask = manhattan (mask, true).array () <= k;
+ mask = manhattan(mask, true).array() <= k;
}
////////////////////////////////////////////////////////////////////////////////
pcl::ihs::InputDataProcessing::MatrixXi
-pcl::ihs::InputDataProcessing::manhattan (const MatrixXb& mat, const bool comp) const
+pcl::ihs::InputDataProcessing::manhattan(const MatrixXb& mat, const bool comp) const
{
- MatrixXi dist (mat.rows (), mat.cols ());
- const int d_max = dist.rows () + dist.cols ();
+ MatrixXi dist(mat.rows(), mat.cols());
+ const int d_max = dist.rows() + dist.cols();
// Forward
- for (MatrixXi::Index r = 0; r < dist.rows (); ++r)
- {
- for (MatrixXi::Index c = 0; c < dist.cols (); ++c)
- {
- if (mat (r, c) == comp)
- {
- dist (r, c) = 0;
+ for (MatrixXi::Index r = 0; r < dist.rows(); ++r) {
+ for (MatrixXi::Index c = 0; c < dist.cols(); ++c) {
+ if (mat(r, c) == comp) {
+ dist(r, c) = 0;
}
- else
- {
- dist (r, c) = d_max;
- if (r > 0) dist (r, c) = std::min (dist (r, c), dist (r-1, c ) + 1);
- if (c > 0) dist (r, c) = std::min (dist (r, c), dist (r , c-1) + 1);
+ else {
+ dist(r, c) = d_max;
+ if (r > 0)
+ dist(r, c) = std::min(dist(r, c), dist(r - 1, c) + 1);
+ if (c > 0)
+ dist(r, c) = std::min(dist(r, c), dist(r, c - 1) + 1);
}
}
}
// Backward
- for (int r = dist.rows () - 1; r >= 0; --r)
- {
- for (int c = dist.cols () - 1; c >= 0; --c)
- {
- if (r < dist.rows ()-1) dist (r, c) = std::min (dist (r, c), dist (r+1, c ) + 1);
- if (c < dist.cols ()-1) dist (r, c) = std::min (dist (r, c), dist (r , c+1) + 1);
+ for (int r = dist.rows() - 1; r >= 0; --r) {
+ for (int c = dist.cols() - 1; c >= 0; --c) {
+ if (r < dist.rows() - 1)
+ dist(r, c) = std::min(dist(r, c), dist(r + 1, c) + 1);
+ if (c < dist.cols() - 1)
+ dist(r, c) = std::min(dist(r, c), dist(r, c + 1) + 1);
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::InputDataProcessing::RGBToHSV (const unsigned char r,
- const unsigned char g,
- const unsigned char b,
- float& h,
- float& s,
- float& v) const
+pcl::ihs::InputDataProcessing::RGBToHSV(const unsigned char r,
+ const unsigned char g,
+ const unsigned char b,
+ float& h,
+ float& s,
+ float& v) const
{
- const unsigned char max = std::max (r, std::max (g, b));
- const unsigned char min = std::min (r, std::min (g, b));
+ const unsigned char max = std::max(r, std::max(g, b));
+ const unsigned char min = std::min(r, std::min(g, b));
- v = static_cast <float> (max) / 255.f;
+ v = static_cast<float>(max) / 255.f;
if (max == 0) // division by zero
{
return;
}
- const float diff = static_cast <float> (max - min);
- s = diff / static_cast <float> (max);
+ const float diff = static_cast<float>(max - min);
+ s = diff / static_cast<float>(max);
if (min == max) // diff == 0 -> division by zero
{
return;
}
- if (max == r) h = 60.f * ( static_cast <float> (g - b) / diff);
- else if (max == g) h = 60.f * (2.f + static_cast <float> (b - r) / diff);
- else h = 60.f * (4.f + static_cast <float> (r - g) / diff); // max == b
+ if (max == r)
+ h = 60.f * (static_cast<float>(g - b) / diff);
+ else if (max == g)
+ h = 60.f * (2.f + static_cast<float>(b - r) / diff);
+ else
+ h = 60.f * (4.f + static_cast<float>(r - g) / diff); // max == b
- if (h < 0.f) h += 360.f;
+ if (h < 0.f)
+ h += 360.f;
}
////////////////////////////////////////////////////////////////////////////////
*/
#include <pcl/apps/in_hand_scanner/integration.h>
+#include <pcl/apps/in_hand_scanner/utils.h>
+#include <pcl/apps/in_hand_scanner/visibility_confidence.h>
+#include <pcl/kdtree/kdtree_flann.h>
#include <iostream>
-#include <vector>
#include <limits>
-
-#include <pcl/kdtree/kdtree_flann.h>
-#include <pcl/apps/in_hand_scanner/visibility_confidence.h>
-#include <pcl/apps/in_hand_scanner/utils.h>
+#include <vector>
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::Integration::Integration ()
- : kd_tree_ (new pcl::KdTreeFLANN <PointXYZ> ()),
- max_squared_distance_ (0.04f), // 0.2cm
- max_angle_ (45.f),
- min_weight_ (.3f),
- max_age_ (30),
- min_directions_ (5)
-{
-}
+pcl::ihs::Integration::Integration()
+: kd_tree_(new pcl::KdTreeFLANN<PointXYZ>())
+, max_squared_distance_(0.04f)
+, // 0.2cm
+max_angle_(45.f)
+, min_weight_(.3f)
+, max_age_(30)
+, min_directions_(5)
+{}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::Integration::reconstructMesh (const CloudXYZRGBNormalConstPtr& cloud_data,
- MeshPtr& mesh_model) const
+pcl::ihs::Integration::reconstructMesh(const CloudXYZRGBNormalConstPtr& cloud_data,
+ MeshPtr& mesh_model) const
{
- if (!cloud_data)
- {
+ if (!cloud_data) {
std::cerr << "ERROR in integration.cpp: Cloud pointer is invalid\n";
return (false);
}
- if (!cloud_data->isOrganized ())
- {
+ if (!cloud_data->isOrganized()) {
std::cerr << "ERROR in integration.cpp: Cloud is not organized\n";
return (false);
}
- const int width = static_cast <int> (cloud_data->width);
- const int height = static_cast <int> (cloud_data->height);
+ const int width = static_cast<int>(cloud_data->width);
+ const int height = static_cast<int>(cloud_data->height);
- if (!mesh_model) mesh_model = MeshPtr (new Mesh ());
+ if (!mesh_model)
+ mesh_model = MeshPtr(new Mesh());
- mesh_model->clear ();
- mesh_model->reserveVertices (cloud_data->size ());
- mesh_model->reserveEdges ((width-1) * height + width * (height-1) + (width-1) * (height-1));
- mesh_model->reserveFaces (2 * (width-1) * (height-1));
+ mesh_model->clear();
+ mesh_model->reserveVertices(cloud_data->size());
+ mesh_model->reserveEdges((width - 1) * height + width * (height - 1) +
+ (width - 1) * (height - 1));
+ mesh_model->reserveFaces(2 * (width - 1) * (height - 1));
// Store which vertex is set at which position (initialized with invalid indices)
- VertexIndices vertex_indices (cloud_data->size (), VertexIndex ());
+ VertexIndices vertex_indices(cloud_data->size(), VertexIndex());
- // Convert to the model cloud type. This is actually not needed but avoids code duplication (see merge). And reconstructMesh is called only the first reconstruction step anyway.
- // NOTE: The default constructor of PointIHS has to initialize with NaNs!
- CloudIHSPtr cloud_model (new CloudIHS ());
- cloud_model->resize (cloud_data->size ());
+ // Convert to the model cloud type. This is actually not needed but avoids code
+ // duplication (see merge). And reconstructMesh is called only the first
+ // reconstruction step anyway. NOTE: The default constructor of PointIHS has to
+ // initialize with NaNs!
+ CloudIHSPtr cloud_model(new CloudIHS());
+ cloud_model->resize(cloud_data->size());
// Set the model points not reached by the main loop
- for (int c=0; c<width; ++c)
- {
- const PointXYZRGBNormal& pt_d = cloud_data->operator [] (c);
+ for (int c = 0; c < width; ++c) {
+ const PointXYZRGBNormal& pt_d = cloud_data->operator[](c);
const float weight = -pt_d.normal_z; // weight = -dot (normal, [0; 0; 1])
- if (!std::isnan (pt_d.x) && weight > min_weight_)
- {
- cloud_model->operator [] (c) = PointIHS (pt_d, weight);
+ if (!std::isnan(pt_d.x) && weight > min_weight_) {
+ cloud_model->operator[](c) = PointIHS(pt_d, weight);
}
}
- for (int r=1; r<height; ++r)
- {
- for (int c=0; c<2; ++c)
- {
- const PointXYZRGBNormal& pt_d = cloud_data->operator [] (r*width + c);
+ for (int r = 1; r < height; ++r) {
+ for (int c = 0; c < 2; ++c) {
+ const PointXYZRGBNormal& pt_d = cloud_data->operator[](r * width + c);
const float weight = -pt_d.normal_z; // weight = -dot (normal, [0; 0; 1])
- if (!std::isnan (pt_d.x) && weight > min_weight_)
- {
- cloud_model->operator [] (r*width + c) = PointIHS (pt_d, weight);
+ if (!std::isnan(pt_d.x) && weight > min_weight_) {
+ cloud_model->operator[](r * width + c) = PointIHS(pt_d, weight);
}
}
}
// * 3 - 0 //
const int offset_1 = -width;
const int offset_2 = -width - 1;
- const int offset_3 = - 1;
+ const int offset_3 = -1;
const int offset_4 = -width - 2;
- for (int r=1; r<height; ++r)
- {
- for (int c=2; c<width; ++c)
- {
- const int ind_0 = r*width + c;
+ for (int r = 1; r < height; ++r) {
+ for (int c = 2; c < width; ++c) {
+ const int ind_0 = r * width + c;
const int ind_1 = ind_0 + offset_1;
const int ind_2 = ind_0 + offset_2;
const int ind_3 = ind_0 + offset_3;
const int ind_4 = ind_0 + offset_4;
- assert (ind_0 >= 0 && ind_0 < static_cast <int> (cloud_data->size ()));
- assert (ind_1 >= 0 && ind_1 < static_cast <int> (cloud_data->size ()));
- assert (ind_2 >= 0 && ind_2 < static_cast <int> (cloud_data->size ()));
- assert (ind_3 >= 0 && ind_3 < static_cast <int> (cloud_data->size ()));
- assert (ind_4 >= 0 && ind_4 < static_cast <int> (cloud_data->size ()));
-
- const PointXYZRGBNormal& pt_d_0 = cloud_data->operator [] (ind_0);
- PointIHS& pt_m_0 = cloud_model->operator [] (ind_0);
- const PointIHS& pt_m_1 = cloud_model->operator [] (ind_1);
- const PointIHS& pt_m_2 = cloud_model->operator [] (ind_2);
- const PointIHS& pt_m_3 = cloud_model->operator [] (ind_3);
- const PointIHS& pt_m_4 = cloud_model->operator [] (ind_4);
-
- VertexIndex& vi_0 = vertex_indices [ind_0];
- VertexIndex& vi_1 = vertex_indices [ind_1];
- VertexIndex& vi_2 = vertex_indices [ind_2];
- VertexIndex& vi_3 = vertex_indices [ind_3];
- VertexIndex& vi_4 = vertex_indices [ind_4];
+ assert(ind_0 >= 0 && ind_0 < static_cast<int>(cloud_data->size()));
+ assert(ind_1 >= 0 && ind_1 < static_cast<int>(cloud_data->size()));
+ assert(ind_2 >= 0 && ind_2 < static_cast<int>(cloud_data->size()));
+ assert(ind_3 >= 0 && ind_3 < static_cast<int>(cloud_data->size()));
+ assert(ind_4 >= 0 && ind_4 < static_cast<int>(cloud_data->size()));
+
+ const PointXYZRGBNormal& pt_d_0 = cloud_data->operator[](ind_0);
+ PointIHS& pt_m_0 = cloud_model->operator[](ind_0);
+ const PointIHS& pt_m_1 = cloud_model->operator[](ind_1);
+ const PointIHS& pt_m_2 = cloud_model->operator[](ind_2);
+ const PointIHS& pt_m_3 = cloud_model->operator[](ind_3);
+ const PointIHS& pt_m_4 = cloud_model->operator[](ind_4);
+
+ VertexIndex& vi_0 = vertex_indices[ind_0];
+ VertexIndex& vi_1 = vertex_indices[ind_1];
+ VertexIndex& vi_2 = vertex_indices[ind_2];
+ VertexIndex& vi_3 = vertex_indices[ind_3];
+ VertexIndex& vi_4 = vertex_indices[ind_4];
const float weight = -pt_d_0.normal_z; // weight = -dot (normal, [0; 0; 1])
- if (!std::isnan (pt_d_0.x) && weight > min_weight_)
- {
- pt_m_0 = PointIHS (pt_d_0, weight);
+ if (!std::isnan(pt_d_0.x) && weight > min_weight_) {
+ pt_m_0 = PointIHS(pt_d_0, weight);
}
- this->addToMesh (pt_m_0,pt_m_1,pt_m_2,pt_m_3, vi_0,vi_1,vi_2,vi_3, mesh_model);
+ this->addToMesh(
+ pt_m_0, pt_m_1, pt_m_2, pt_m_3, vi_0, vi_1, vi_2, vi_3, mesh_model);
if (Mesh::IsManifold::value) // Only needed for the manifold mesh
{
- this->addToMesh (pt_m_0,pt_m_2,pt_m_4,pt_m_3, vi_0,vi_2,vi_4,vi_3, mesh_model);
+ this->addToMesh(
+ pt_m_0, pt_m_2, pt_m_4, pt_m_3, vi_0, vi_2, vi_4, vi_3, mesh_model);
}
}
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::Integration::merge (const CloudXYZRGBNormalConstPtr& cloud_data,
- MeshPtr& mesh_model,
- const Eigen::Matrix4f& T) const
+pcl::ihs::Integration::merge(const CloudXYZRGBNormalConstPtr& cloud_data,
+ MeshPtr& mesh_model,
+ const Eigen::Matrix4f& T) const
{
- if (!cloud_data)
- {
+ if (!cloud_data) {
std::cerr << "ERROR in integration.cpp: Cloud pointer is invalid\n";
return (false);
}
- if (!cloud_data->isOrganized ())
- {
+ if (!cloud_data->isOrganized()) {
std::cerr << "ERROR in integration.cpp: Data cloud is not organized\n";
return (false);
}
- if (!mesh_model)
- {
+ if (!mesh_model) {
std::cerr << "ERROR in integration.cpp: Mesh pointer is invalid\n";
return (false);
}
- if (!mesh_model->sizeVertices ())
- {
+ if (!mesh_model->sizeVertices()) {
std::cerr << "ERROR in integration.cpp: Model mesh is empty\n";
return (false);
}
- const int width = static_cast <int> (cloud_data->width);
- const int height = static_cast <int> (cloud_data->height);
+ const int width = static_cast<int>(cloud_data->width);
+ const int height = static_cast<int>(cloud_data->height);
// Nearest neighbor search
- CloudXYZPtr xyz_model (new CloudXYZ ());
- xyz_model->reserve (mesh_model->sizeVertices ());
- for (std::size_t i=0; i<mesh_model->sizeVertices (); ++i)
- {
- const PointIHS& pt = mesh_model->getVertexDataCloud () [i];
- xyz_model->push_back (PointXYZ (pt.x, pt.y, pt.z));
+ CloudXYZPtr xyz_model(new CloudXYZ());
+ xyz_model->reserve(mesh_model->sizeVertices());
+ for (std::size_t i = 0; i < mesh_model->sizeVertices(); ++i) {
+ const PointIHS& pt = mesh_model->getVertexDataCloud()[i];
+ xyz_model->push_back(PointXYZ(pt.x, pt.y, pt.z));
}
- kd_tree_->setInputCloud (xyz_model);
- pcl::Indices index (1);
- std::vector <float> squared_distance (1);
+ kd_tree_->setInputCloud(xyz_model);
+ pcl::Indices index(1);
+ std::vector<float> squared_distance(1);
- mesh_model->reserveVertices (mesh_model->sizeVertices () + cloud_data->size ());
- mesh_model->reserveEdges (mesh_model->sizeEdges () + (width-1) * height + width * (height-1) + (width-1) * (height-1));
- mesh_model->reserveFaces (mesh_model->sizeFaces () + 2 * (width-1) * (height-1));
+ mesh_model->reserveVertices(mesh_model->sizeVertices() + cloud_data->size());
+ mesh_model->reserveEdges(mesh_model->sizeEdges() + (width - 1) * height +
+ width * (height - 1) + (width - 1) * (height - 1));
+ mesh_model->reserveFaces(mesh_model->sizeFaces() + 2 * (width - 1) * (height - 1));
- // Data cloud in model coordinates (this does not change the connectivity information) and weights
- CloudIHSPtr cloud_data_transformed (new CloudIHS ());
- cloud_data_transformed->resize (cloud_data->size ());
+ // Data cloud in model coordinates (this does not change the connectivity information)
+ // and weights
+ CloudIHSPtr cloud_data_transformed(new CloudIHS());
+ cloud_data_transformed->resize(cloud_data->size());
// Sensor position in model coordinates
- const Eigen::Vector4f& sensor_eye = T * Eigen::Vector4f (0.f, 0.f, 0.f, 1.f);
+ const Eigen::Vector4f& sensor_eye = T * Eigen::Vector4f(0.f, 0.f, 0.f, 1.f);
// Store which vertex is set at which position (initialized with invalid indices)
- VertexIndices vertex_indices (cloud_data->size (), VertexIndex ());
+ VertexIndices vertex_indices(cloud_data->size(), VertexIndex());
// Set the transformed points not reached by the main loop
- for (int c=0; c<width; ++c)
- {
- const PointXYZRGBNormal& pt_d = cloud_data->operator [] (c);
+ for (int c = 0; c < width; ++c) {
+ const PointXYZRGBNormal& pt_d = cloud_data->operator[](c);
const float weight = -pt_d.normal_z; // weight = -dot (normal, [0; 0; 1])
- if (!std::isnan (pt_d.x) && weight > min_weight_)
- {
- PointIHS& pt_d_t = cloud_data_transformed->operator [] (c);
- pt_d_t = PointIHS (pt_d, weight);
- pt_d_t.getVector4fMap () = T * pt_d_t.getVector4fMap ();
- pt_d_t.getNormalVector4fMap () = T * pt_d_t.getNormalVector4fMap ();
+ if (!std::isnan(pt_d.x) && weight > min_weight_) {
+ PointIHS& pt_d_t = cloud_data_transformed->operator[](c);
+ pt_d_t = PointIHS(pt_d, weight);
+ pt_d_t.getVector4fMap() = T * pt_d_t.getVector4fMap();
+ pt_d_t.getNormalVector4fMap() = T * pt_d_t.getNormalVector4fMap();
}
}
- for (int r=1; r<height; ++r)
- {
- for (int c=0; c<2; ++c)
- {
- const PointXYZRGBNormal& pt_d = cloud_data->operator [] (r*width + c);
+ for (int r = 1; r < height; ++r) {
+ for (int c = 0; c < 2; ++c) {
+ const PointXYZRGBNormal& pt_d = cloud_data->operator[](r * width + c);
const float weight = -pt_d.normal_z; // weight = -dot (normal, [0; 0; 1])
- if (!std::isnan (pt_d.x) && weight > min_weight_)
- {
- PointIHS& pt_d_t = cloud_data_transformed->operator [] (r*width + c);
- pt_d_t = PointIHS (pt_d, weight);
- pt_d_t.getVector4fMap () = T * pt_d_t.getVector4fMap ();
- pt_d_t.getNormalVector4fMap () = T * pt_d_t.getNormalVector4fMap ();
+ if (!std::isnan(pt_d.x) && weight > min_weight_) {
+ PointIHS& pt_d_t = cloud_data_transformed->operator[](r * width + c);
+ pt_d_t = PointIHS(pt_d, weight);
+ pt_d_t.getVector4fMap() = T * pt_d_t.getVector4fMap();
+ pt_d_t.getNormalVector4fMap() = T * pt_d_t.getNormalVector4fMap();
}
}
}
// * 3 - 0 //
const int offset_1 = -width;
const int offset_2 = -width - 1;
- const int offset_3 = - 1;
+ const int offset_3 = -1;
const int offset_4 = -width - 2;
- const float dot_min = std::cos (max_angle_ * 17.45329252e-3); // deg to rad
+ const float dot_min = std::cos(max_angle_ * 17.45329252e-3); // deg to rad
- for (int r=1; r<height; ++r)
- {
- for (int c=2; c<width; ++c)
- {
- const int ind_0 = r*width + c;
+ for (int r = 1; r < height; ++r) {
+ for (int c = 2; c < width; ++c) {
+ const int ind_0 = r * width + c;
const int ind_1 = ind_0 + offset_1;
const int ind_2 = ind_0 + offset_2;
const int ind_3 = ind_0 + offset_3;
const int ind_4 = ind_0 + offset_4;
- assert (ind_0 >= 0 && ind_0 < static_cast <int> (cloud_data->size ()));
- assert (ind_1 >= 0 && ind_1 < static_cast <int> (cloud_data->size ()));
- assert (ind_2 >= 0 && ind_2 < static_cast <int> (cloud_data->size ()));
- assert (ind_3 >= 0 && ind_3 < static_cast <int> (cloud_data->size ()));
- assert (ind_4 >= 0 && ind_4 < static_cast <int> (cloud_data->size ()));
+ assert(ind_0 >= 0 && ind_0 < static_cast<int>(cloud_data->size()));
+ assert(ind_1 >= 0 && ind_1 < static_cast<int>(cloud_data->size()));
+ assert(ind_2 >= 0 && ind_2 < static_cast<int>(cloud_data->size()));
+ assert(ind_3 >= 0 && ind_3 < static_cast<int>(cloud_data->size()));
+ assert(ind_4 >= 0 && ind_4 < static_cast<int>(cloud_data->size()));
- const PointXYZRGBNormal& pt_d_0 = cloud_data->operator [] (ind_0);
- PointIHS& pt_d_t_0 = cloud_data_transformed->operator [] (ind_0);
- const PointIHS& pt_d_t_1 = cloud_data_transformed->operator [] (ind_1);
- const PointIHS& pt_d_t_2 = cloud_data_transformed->operator [] (ind_2);
- const PointIHS& pt_d_t_3 = cloud_data_transformed->operator [] (ind_3);
- const PointIHS& pt_d_t_4 = cloud_data_transformed->operator [] (ind_4);
+ const PointXYZRGBNormal& pt_d_0 = cloud_data->operator[](ind_0);
+ PointIHS& pt_d_t_0 = cloud_data_transformed->operator[](ind_0);
+ const PointIHS& pt_d_t_1 = cloud_data_transformed->operator[](ind_1);
+ const PointIHS& pt_d_t_2 = cloud_data_transformed->operator[](ind_2);
+ const PointIHS& pt_d_t_3 = cloud_data_transformed->operator[](ind_3);
+ const PointIHS& pt_d_t_4 = cloud_data_transformed->operator[](ind_4);
- VertexIndex& vi_0 = vertex_indices [ind_0];
+ VertexIndex& vi_0 = vertex_indices[ind_0];
const float weight = -pt_d_0.normal_z; // weight = -dot (normal, [0; 0; 1])
- if (!std::isnan (pt_d_0.x) && weight > min_weight_)
- {
- pt_d_t_0 = PointIHS (pt_d_0, weight);
- pt_d_t_0.getVector4fMap () = T * pt_d_t_0.getVector4fMap ();
- pt_d_t_0.getNormalVector4fMap () = T * pt_d_t_0.getNormalVector4fMap ();
+ if (!std::isnan(pt_d_0.x) && weight > min_weight_) {
+ pt_d_t_0 = PointIHS(pt_d_0, weight);
+ pt_d_t_0.getVector4fMap() = T * pt_d_t_0.getVector4fMap();
+ pt_d_t_0.getNormalVector4fMap() = T * pt_d_t_0.getNormalVector4fMap();
- pcl::PointXYZ tmp; tmp.getVector4fMap () = pt_d_t_0.getVector4fMap ();
+ pcl::PointXYZ tmp;
+ tmp.getVector4fMap() = pt_d_t_0.getVector4fMap();
// NN search
- if (!kd_tree_->nearestKSearch (tmp, 1, index, squared_distance))
- {
+ if (!kd_tree_->nearestKSearch(tmp, 1, index, squared_distance)) {
std::cerr << "ERROR in integration.cpp: nearestKSearch failed!\n";
return (false);
}
// Average out corresponding points
- if (squared_distance [0] <= max_squared_distance_)
- {
- PointIHS& pt_m = mesh_model->getVertexDataCloud () [index [0]]; // Non-const reference!
-
- if (pt_m.getNormalVector4fMap ().dot (pt_d_t_0.getNormalVector4fMap ()) >= dot_min)
- {
- vi_0 = VertexIndex (index [0]);
-
- const float W = pt_m.weight; // Old accumulated weight
- const float w = pt_d_t_0.weight; // Weight of new point
- const float WW = pt_m.weight = W + w; // New accumulated weight
-
- const float r_m = static_cast <float> (pt_m.r);
- const float g_m = static_cast <float> (pt_m.g);
- const float b_m = static_cast <float> (pt_m.b);
-
- const float r_d = static_cast <float> (pt_d_t_0.r);
- const float g_d = static_cast <float> (pt_d_t_0.g);
- const float b_d = static_cast <float> (pt_d_t_0.b);
-
- pt_m.getVector4fMap () = ( W*pt_m.getVector4fMap () + w*pt_d_t_0.getVector4fMap ()) / WW;
- pt_m.getNormalVector4fMap () = ((W*pt_m.getNormalVector4fMap () + w*pt_d_t_0.getNormalVector4fMap ()) / WW).normalized ();
- pt_m.r = this->trimRGB ((W*r_m + w*r_d) / WW);
- pt_m.g = this->trimRGB ((W*g_m + w*g_d) / WW);
- pt_m.b = this->trimRGB ((W*b_m + w*b_d) / WW);
+ if (squared_distance[0] <= max_squared_distance_) {
+ PointIHS& pt_m =
+ mesh_model->getVertexDataCloud()[index[0]]; // Non-const reference!
+
+ if (pt_m.getNormalVector4fMap().dot(pt_d_t_0.getNormalVector4fMap()) >=
+ dot_min) {
+ vi_0 = VertexIndex(index[0]);
+
+ const float W = pt_m.weight; // Old accumulated weight
+ const float w = pt_d_t_0.weight; // Weight of new point
+ const float WW = pt_m.weight = W + w; // New accumulated weight
+
+ const float r_m = static_cast<float>(pt_m.r);
+ const float g_m = static_cast<float>(pt_m.g);
+ const float b_m = static_cast<float>(pt_m.b);
+
+ const float r_d = static_cast<float>(pt_d_t_0.r);
+ const float g_d = static_cast<float>(pt_d_t_0.g);
+ const float b_d = static_cast<float>(pt_d_t_0.b);
+
+ pt_m.getVector4fMap() =
+ (W * pt_m.getVector4fMap() + w * pt_d_t_0.getVector4fMap()) / WW;
+ pt_m.getNormalVector4fMap() = ((W * pt_m.getNormalVector4fMap() +
+ w * pt_d_t_0.getNormalVector4fMap()) /
+ WW)
+ .normalized();
+ pt_m.r = this->trimRGB((W * r_m + w * r_d) / WW);
+ pt_m.g = this->trimRGB((W * g_m + w * g_d) / WW);
+ pt_m.b = this->trimRGB((W * b_m + w * b_d) / WW);
// Point has been observed again -> give it some extra time to live
pt_m.age = 0;
// Add a direction
- pcl::ihs::addDirection (pt_m.getNormalVector4fMap (), sensor_eye-pt_m.getVector4fMap (), pt_m.directions);
+ pcl::ihs::addDirection(pt_m.getNormalVector4fMap(),
+ sensor_eye - pt_m.getVector4fMap(),
+ pt_m.directions);
} // dot normals
- } // squared distance
- } // !isnan && min weight
+ } // squared distance
+ } // !isnan && min weight
// Connect
// 4 2 - 1 //
// \ \ //
// * 3 - 0 //
- VertexIndex& vi_1 = vertex_indices [ind_1];
- VertexIndex& vi_2 = vertex_indices [ind_2];
- VertexIndex& vi_3 = vertex_indices [ind_3];
- VertexIndex& vi_4 = vertex_indices [ind_4];
+ VertexIndex& vi_1 = vertex_indices[ind_1];
+ VertexIndex& vi_2 = vertex_indices[ind_2];
+ VertexIndex& vi_3 = vertex_indices[ind_3];
+ VertexIndex& vi_4 = vertex_indices[ind_4];
- this->addToMesh (pt_d_t_0,pt_d_t_1,pt_d_t_2,pt_d_t_3, vi_0,vi_1,vi_2,vi_3, mesh_model);
+ this->addToMesh(
+ pt_d_t_0, pt_d_t_1, pt_d_t_2, pt_d_t_3, vi_0, vi_1, vi_2, vi_3, mesh_model);
if (Mesh::IsManifold::value) // Only needed for the manifold mesh
{
- this->addToMesh (pt_d_t_0,pt_d_t_2,pt_d_t_4,pt_d_t_3, vi_0,vi_2,vi_4,vi_3, mesh_model);
+ this->addToMesh(
+ pt_d_t_0, pt_d_t_2, pt_d_t_4, pt_d_t_3, vi_0, vi_2, vi_4, vi_3, mesh_model);
}
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::Integration::age (const MeshPtr& mesh, const bool cleanup) const
+pcl::ihs::Integration::age(const MeshPtr& mesh, const bool cleanup) const
{
- for (std::size_t i=0; i<mesh->sizeVertices (); ++i)
- {
- PointIHS& pt = mesh->getVertexDataCloud () [i];
- if (pt.age < max_age_)
- {
+ for (std::size_t i = 0; i < mesh->sizeVertices(); ++i) {
+ PointIHS& pt = mesh->getVertexDataCloud()[i];
+ if (pt.age < max_age_) {
// Point survives
++(pt.age);
}
else if (pt.age == max_age_) // Judgement Day
{
- if (pcl::ihs::countDirections (pt.directions) < min_directions_)
- {
+ if (pcl::ihs::countDirections(pt.directions) < min_directions_) {
// Point dies (no need to transform it)
- mesh->deleteVertex (VertexIndex (i));
+ mesh->deleteVertex(VertexIndex(i));
}
- else
- {
+ else {
// Point becomes immortal
- pt.age = std::numeric_limits <unsigned int>::max ();
+ pt.age = std::numeric_limits<unsigned int>::max();
}
}
}
- if (cleanup)
- {
- mesh->cleanUp ();
+ if (cleanup) {
+ mesh->cleanUp();
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::Integration::removeUnfitVertices (const MeshPtr& mesh, const bool cleanup) const
+pcl::ihs::Integration::removeUnfitVertices(const MeshPtr& mesh,
+ const bool cleanup) const
{
- for (std::size_t i=0; i<mesh->sizeVertices (); ++i)
- {
- if (pcl::ihs::countDirections (mesh->getVertexDataCloud () [i].directions) < min_directions_)
- {
+ for (std::size_t i = 0; i < mesh->sizeVertices(); ++i) {
+ if (pcl::ihs::countDirections(mesh->getVertexDataCloud()[i].directions) <
+ min_directions_) {
// Point dies (no need to transform it)
- mesh->deleteVertex (VertexIndex (i));
+ mesh->deleteVertex(VertexIndex(i));
}
}
- if (cleanup)
- {
- mesh->cleanUp ();
+ if (cleanup) {
+ mesh->cleanUp();
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::Integration::setMaxSquaredDistance (const float squared_distance)
+pcl::ihs::Integration::setMaxSquaredDistance(const float squared_distance)
{
- if (squared_distance > 0) max_squared_distance_ = squared_distance;
+ if (squared_distance > 0)
+ max_squared_distance_ = squared_distance;
}
float
-pcl::ihs::Integration::getMaxSquaredDistance () const
+pcl::ihs::Integration::getMaxSquaredDistance() const
{
return (max_squared_distance_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::Integration::setMaxAngle (const float angle)
+pcl::ihs::Integration::setMaxAngle(const float angle)
{
- max_angle_ = pcl::ihs::clamp (angle, 0.f, 180.f);
+ max_angle_ = pcl::ihs::clamp(angle, 0.f, 180.f);
}
float
-pcl::ihs::Integration::getMaxAngle () const
+pcl::ihs::Integration::getMaxAngle() const
{
return (max_angle_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::Integration::setMaxAge (const unsigned int age)
+pcl::ihs::Integration::setMaxAge(const unsigned int age)
{
max_age_ = age < 1 ? 1 : age;
}
unsigned int
-pcl::ihs::Integration::getMaxAge () const
+pcl::ihs::Integration::getMaxAge() const
{
return (max_age_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::Integration::setMinDirections (const unsigned int directions)
+pcl::ihs::Integration::setMinDirections(const unsigned int directions)
{
min_directions_ = directions < 1 ? 1 : directions;
}
unsigned int
-pcl::ihs::Integration::getMinDirections () const
+pcl::ihs::Integration::getMinDirections() const
{
return (min_directions_);
}
////////////////////////////////////////////////////////////////////////////////
std::uint8_t
-pcl::ihs::Integration::trimRGB (const float val) const
+pcl::ihs::Integration::trimRGB(const float val) const
{
- return (static_cast <std::uint8_t> (val > 255.f ? 255 : val));
+ return (static_cast<std::uint8_t>(val > 255.f ? 255 : val));
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::Integration::addToMesh (const PointIHS& pt_0,
- const PointIHS& pt_1,
- const PointIHS& pt_2,
- const PointIHS& pt_3,
- VertexIndex& vi_0,
- VertexIndex& vi_1,
- VertexIndex& vi_2,
- VertexIndex& vi_3,
- const MeshPtr& mesh) const
+pcl::ihs::Integration::addToMesh(const PointIHS& pt_0,
+ const PointIHS& pt_1,
+ const PointIHS& pt_2,
+ const PointIHS& pt_3,
+ VertexIndex& vi_0,
+ VertexIndex& vi_1,
+ VertexIndex& vi_2,
+ VertexIndex& vi_3,
+ const MeshPtr& mesh) const
{
// Treated bitwise
// 2 - 1
// | |
// 3 - 0
- const unsigned char is_finite = static_cast <unsigned char> (
- (1 * !std::isnan (pt_0.x)) |
- (2 * !std::isnan (pt_1.x)) |
- (4 * !std::isnan (pt_2.x)) |
- (8 * !std::isnan (pt_3.x)));
-
- switch (is_finite)
+ const unsigned char is_finite =
+ static_cast<unsigned char>((1 * !std::isnan(pt_0.x)) | (2 * !std::isnan(pt_1.x)) |
+ (4 * !std::isnan(pt_2.x)) | (8 * !std::isnan(pt_3.x)));
+
+ switch (is_finite) {
+ case 7:
+ this->addToMesh(pt_0, pt_1, pt_2, vi_0, vi_1, vi_2, mesh);
+ break; // 0-1-2
+ case 11:
+ this->addToMesh(pt_0, pt_1, pt_3, vi_0, vi_1, vi_3, mesh);
+ break; // 0-1-3
+ case 13:
+ this->addToMesh(pt_0, pt_2, pt_3, vi_0, vi_2, vi_3, mesh);
+ break; // 0-2-3
+ case 14:
+ this->addToMesh(pt_1, pt_2, pt_3, vi_1, vi_2, vi_3, mesh);
+ break; // 1-2-3
+ case 15: // 0-1-2-3
{
- case 7: this->addToMesh (pt_0, pt_1, pt_2, vi_0, vi_1, vi_2, mesh); break; // 0-1-2
- case 11: this->addToMesh (pt_0, pt_1, pt_3, vi_0, vi_1, vi_3, mesh); break; // 0-1-3
- case 13: this->addToMesh (pt_0, pt_2, pt_3, vi_0, vi_2, vi_3, mesh); break; // 0-2-3
- case 14: this->addToMesh (pt_1, pt_2, pt_3, vi_1, vi_2, vi_3, mesh); break; // 1-2-3
- case 15: // 0-1-2-3
- {
- if (!distanceThreshold (pt_0, pt_1, pt_2, pt_3)) break;
- if (!vi_0.isValid ()) vi_0 = mesh->addVertex (pt_0);
- if (!vi_1.isValid ()) vi_1 = mesh->addVertex (pt_1);
- if (!vi_2.isValid ()) vi_2 = mesh->addVertex (pt_2);
- if (!vi_3.isValid ()) vi_3 = mesh->addVertex (pt_3);
- if (vi_0==vi_1 || vi_0==vi_2 || vi_0==vi_3 || vi_1==vi_2 || vi_1==vi_3 || vi_2==vi_3)
- {
- return;
- }
- mesh->addTrianglePair (vi_0, vi_1, vi_2, vi_3);
-
+ if (!distanceThreshold(pt_0, pt_1, pt_2, pt_3))
break;
+ if (!vi_0.isValid())
+ vi_0 = mesh->addVertex(pt_0);
+ if (!vi_1.isValid())
+ vi_1 = mesh->addVertex(pt_1);
+ if (!vi_2.isValid())
+ vi_2 = mesh->addVertex(pt_2);
+ if (!vi_3.isValid())
+ vi_3 = mesh->addVertex(pt_3);
+ if (vi_0 == vi_1 || vi_0 == vi_2 || vi_0 == vi_3 || vi_1 == vi_2 || vi_1 == vi_3 ||
+ vi_2 == vi_3) {
+ return;
}
+ mesh->addTrianglePair(vi_0, vi_1, vi_2, vi_3);
+
+ break;
+ }
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::Integration::addToMesh (const PointIHS& pt_0,
- const PointIHS& pt_1,
- const PointIHS& pt_2,
- VertexIndex& vi_0,
- VertexIndex& vi_1,
- VertexIndex& vi_2,
- const MeshPtr& mesh) const
+pcl::ihs::Integration::addToMesh(const PointIHS& pt_0,
+ const PointIHS& pt_1,
+ const PointIHS& pt_2,
+ VertexIndex& vi_0,
+ VertexIndex& vi_1,
+ VertexIndex& vi_2,
+ const MeshPtr& mesh) const
{
- if (!distanceThreshold (pt_0, pt_1, pt_2)) return;
+ if (!distanceThreshold(pt_0, pt_1, pt_2))
+ return;
- if (!vi_0.isValid ()) vi_0 = mesh->addVertex (pt_0);
- if (!vi_1.isValid ()) vi_1 = mesh->addVertex (pt_1);
- if (!vi_2.isValid ()) vi_2 = mesh->addVertex (pt_2);
- if (vi_0==vi_1 || vi_0==vi_2 || vi_1==vi_2)
- {
+ if (!vi_0.isValid())
+ vi_0 = mesh->addVertex(pt_0);
+ if (!vi_1.isValid())
+ vi_1 = mesh->addVertex(pt_1);
+ if (!vi_2.isValid())
+ vi_2 = mesh->addVertex(pt_2);
+ if (vi_0 == vi_1 || vi_0 == vi_2 || vi_1 == vi_2) {
return;
}
- mesh->addFace (vi_0, vi_1, vi_2);
+ mesh->addFace(vi_0, vi_1, vi_2);
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::Integration::distanceThreshold (const PointIHS& pt_0,
- const PointIHS& pt_1,
- const PointIHS& pt_2) const
+pcl::ihs::Integration::distanceThreshold(const PointIHS& pt_0,
+ const PointIHS& pt_1,
+ const PointIHS& pt_2) const
{
- if ((pt_0.getVector3fMap () - pt_1.getVector3fMap ()).squaredNorm () > max_squared_distance_) return (false);
- if ((pt_1.getVector3fMap () - pt_2.getVector3fMap ()).squaredNorm () > max_squared_distance_) return (false);
- if ((pt_2.getVector3fMap () - pt_0.getVector3fMap ()).squaredNorm () > max_squared_distance_) return (false);
+ if ((pt_0.getVector3fMap() - pt_1.getVector3fMap()).squaredNorm() >
+ max_squared_distance_)
+ return (false);
+ if ((pt_1.getVector3fMap() - pt_2.getVector3fMap()).squaredNorm() >
+ max_squared_distance_)
+ return (false);
+ if ((pt_2.getVector3fMap() - pt_0.getVector3fMap()).squaredNorm() >
+ max_squared_distance_)
+ return (false);
return (true);
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::Integration::distanceThreshold (const PointIHS& pt_0,
- const PointIHS& pt_1,
- const PointIHS& pt_2,
- const PointIHS& pt_3) const
+pcl::ihs::Integration::distanceThreshold(const PointIHS& pt_0,
+ const PointIHS& pt_1,
+ const PointIHS& pt_2,
+ const PointIHS& pt_3) const
{
- if ((pt_0.getVector3fMap () - pt_1.getVector3fMap ()).squaredNorm () > max_squared_distance_) return (false);
- if ((pt_1.getVector3fMap () - pt_2.getVector3fMap ()).squaredNorm () > max_squared_distance_) return (false);
- if ((pt_2.getVector3fMap () - pt_3.getVector3fMap ()).squaredNorm () > max_squared_distance_) return (false);
- if ((pt_3.getVector3fMap () - pt_0.getVector3fMap ()).squaredNorm () > max_squared_distance_) return (false);
+ if ((pt_0.getVector3fMap() - pt_1.getVector3fMap()).squaredNorm() >
+ max_squared_distance_)
+ return (false);
+ if ((pt_1.getVector3fMap() - pt_2.getVector3fMap()).squaredNorm() >
+ max_squared_distance_)
+ return (false);
+ if ((pt_2.getVector3fMap() - pt_3.getVector3fMap()).squaredNorm() >
+ max_squared_distance_)
+ return (false);
+ if ((pt_3.getVector3fMap() - pt_0.getVector3fMap()).squaredNorm() >
+ max_squared_distance_)
+ return (false);
return (true);
}
*
*/
-#include <QApplication>
-
#include <pcl/apps/in_hand_scanner/main_window.h>
+#include <QApplication>
+
int
-main (int argc, char** argv)
+main(int argc, char** argv)
{
- QApplication app (argc, argv);
+ QApplication app(argc, argv);
pcl::ihs::MainWindow mw;
- mw.show ();
- return (QApplication::exec ());
+ mw.show();
+ return (QApplication::exec());
}
*
*/
+#include <pcl/apps/in_hand_scanner/offline_integration.h>
+
#include <QApplication>
#include <QTimer>
-#include <pcl/apps/in_hand_scanner/offline_integration.h>
-
int
-main (int argc, char** argv)
+main(int argc, char** argv)
{
- QApplication app (argc, argv);
+ QApplication app(argc, argv);
pcl::ihs::OfflineIntegration oi;
- QTimer::singleShot(0, &oi, SLOT (start ()));
- oi.show ();
- return (QApplication::exec ());
+ QTimer::singleShot(0, &oi, SLOT(start()));
+ oi.show();
+ return (QApplication::exec());
}
*
*/
+#include <pcl/apps/in_hand_scanner/help_window.h>
+#include <pcl/apps/in_hand_scanner/icp.h>
+#include <pcl/apps/in_hand_scanner/in_hand_scanner.h>
+#include <pcl/apps/in_hand_scanner/input_data_processing.h>
+#include <pcl/apps/in_hand_scanner/integration.h>
#include <pcl/apps/in_hand_scanner/main_window.h>
-#include "ui_main_window.h"
-
-#include <limits>
#include <QDoubleValidator>
#include <QFileDialog>
#include <QString>
#include <QTimer>
-#include <pcl/apps/in_hand_scanner/help_window.h>
-#include <pcl/apps/in_hand_scanner/in_hand_scanner.h>
-#include <pcl/apps/in_hand_scanner/input_data_processing.h>
-#include <pcl/apps/in_hand_scanner/icp.h>
-#include <pcl/apps/in_hand_scanner/integration.h>
+#include "ui_main_window.h"
+
+#include <limits>
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::MainWindow::MainWindow (QWidget* parent)
- : QMainWindow (parent),
- ui_ (new Ui::MainWindow ()),
- help_window_ (new HelpWindow (this)),
- ihs_ (new InHandScanner ())
+pcl::ihs::MainWindow::MainWindow(QWidget* parent)
+: QMainWindow(parent)
+, ui_(new Ui::MainWindow())
+, help_window_(new HelpWindow(this))
+, ihs_(new InHandScanner())
{
- ui_->setupUi (this);
+ ui_->setupUi(this);
- QWidget* spacer = new QWidget ();
- spacer->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);
- ui_->toolBar->insertWidget (ui_->actionHelp, spacer);
+ QWidget* spacer = new QWidget();
+ spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ ui_->toolBar->insertWidget(ui_->actionHelp, spacer);
- const double max = std::numeric_limits <double>::max ();
+ const double max = std::numeric_limits<double>::max();
// In hand scanner
- QHBoxLayout* layout = new QHBoxLayout (ui_->placeholder_in_hand_scanner);
- layout->addWidget (ihs_);
+ QHBoxLayout* layout = new QHBoxLayout(ui_->placeholder_in_hand_scanner);
+ layout->addWidget(ihs_);
// ui_->centralWidget->setLayout (layout);
- QTimer::singleShot (0, ihs_, SLOT (startGrabber ()));
+ QTimer::singleShot(0, ihs_, SLOT(startGrabber()));
- connect (ui_->toolButton_1, SIGNAL (clicked ()), ihs_, SLOT (showUnprocessedData ()));
- connect (ui_->toolButton_2, SIGNAL (clicked ()), ihs_, SLOT (showProcessedData ()));
- connect (ui_->toolButton_3, SIGNAL (clicked ()), ihs_, SLOT (registerContinuously ()));
- connect (ui_->toolButton_4, SIGNAL (clicked ()), ihs_, SLOT (registerOnce ()));
- connect (ui_->toolButton_5, SIGNAL (clicked ()), ihs_, SLOT (showModel ()));
- connect (ui_->toolButton_6, SIGNAL (clicked ()), ihs_, SLOT (removeUnfitVertices ()));
- connect (ui_->toolButton_0, SIGNAL (clicked ()), ihs_, SLOT (reset ()));
+ connect(ui_->toolButton_1, SIGNAL(clicked()), ihs_, SLOT(showUnprocessedData()));
+ connect(ui_->toolButton_2, SIGNAL(clicked()), ihs_, SLOT(showProcessedData()));
+ connect(ui_->toolButton_3, SIGNAL(clicked()), ihs_, SLOT(registerContinuously()));
+ connect(ui_->toolButton_4, SIGNAL(clicked()), ihs_, SLOT(registerOnce()));
+ connect(ui_->toolButton_5, SIGNAL(clicked()), ihs_, SLOT(showModel()));
+ connect(ui_->toolButton_6, SIGNAL(clicked()), ihs_, SLOT(removeUnfitVertices()));
+ connect(ui_->toolButton_0, SIGNAL(clicked()), ihs_, SLOT(reset()));
- connect (ui_->actionReset_camera, SIGNAL (triggered ()), ihs_, SLOT (resetCamera ()));
- connect (ui_->actionToggle_coloring, SIGNAL (triggered ()), ihs_, SLOT (toggleColoring ()));
- connect (ui_->actionMesh_representation, SIGNAL (triggered ()), ihs_, SLOT (toggleMeshRepresentation ()));
+ connect(ui_->actionReset_camera, SIGNAL(triggered()), ihs_, SLOT(resetCamera()));
+ connect(
+ ui_->actionToggle_coloring, SIGNAL(triggered()), ihs_, SLOT(toggleColoring()));
+ connect(ui_->actionMesh_representation,
+ SIGNAL(triggered()),
+ ihs_,
+ SLOT(toggleMeshRepresentation()));
- connect (ui_->actionSaveAs, SIGNAL (triggered ()), this, SLOT (saveAs ()));
+ connect(ui_->actionSaveAs, SIGNAL(triggered()), this, SLOT(saveAs()));
- connect (ihs_, SIGNAL (runningModeChanged (RunningMode)), this, SLOT (runningModeChanged (RunningMode)));
+ connect(ihs_,
+ SIGNAL(runningModeChanged(RunningMode)),
+ this,
+ SLOT(runningModeChanged(RunningMode)));
// Input data processing
- const pcl::ihs::InputDataProcessing& idp = ihs_->getInputDataProcessing ();
-
- ui_->spinBox_x_min->setValue (static_cast <int> (idp.getXMin ()));
- ui_->spinBox_x_max->setValue (static_cast <int> (idp.getXMax ()));
- ui_->spinBox_y_min->setValue (static_cast <int> (idp.getYMin ()));
- ui_->spinBox_y_max->setValue (static_cast <int> (idp.getYMax ()));
- ui_->spinBox_z_min->setValue (static_cast <int> (idp.getZMin ()));
- ui_->spinBox_z_max->setValue (static_cast <int> (idp.getZMax ()));
-
- ui_->spinBox_h_min->setValue (static_cast <int> (idp.getHMin ()));
- ui_->spinBox_h_max->setValue (static_cast <int> (idp.getHMax ()));
- ui_->spinBox_s_min->setValue (static_cast <int> (idp.getSMin () * 100.f));
- ui_->spinBox_s_max->setValue (static_cast <int> (idp.getSMax () * 100.f));
- ui_->spinBox_v_min->setValue (static_cast <int> (idp.getVMin () * 100.f));
- ui_->spinBox_v_max->setValue (static_cast <int> (idp.getVMax () * 100.f));
-
- ui_->checkBox_color_segmentation_inverted->setChecked (idp.getColorSegmentationInverted ());
- ui_->checkBox_color_segmentation_enabled->setChecked (idp.getColorSegmentationEnabled ());
-
- ui_->spinBox_xyz_erode_size->setValue (idp.getXYZErodeSize ());
- ui_->spinBox_hsv_dilate_size->setValue (idp.getHSVDilateSize ());
+ const pcl::ihs::InputDataProcessing& idp = ihs_->getInputDataProcessing();
+
+ ui_->spinBox_x_min->setValue(static_cast<int>(idp.getXMin()));
+ ui_->spinBox_x_max->setValue(static_cast<int>(idp.getXMax()));
+ ui_->spinBox_y_min->setValue(static_cast<int>(idp.getYMin()));
+ ui_->spinBox_y_max->setValue(static_cast<int>(idp.getYMax()));
+ ui_->spinBox_z_min->setValue(static_cast<int>(idp.getZMin()));
+ ui_->spinBox_z_max->setValue(static_cast<int>(idp.getZMax()));
+
+ ui_->spinBox_h_min->setValue(static_cast<int>(idp.getHMin()));
+ ui_->spinBox_h_max->setValue(static_cast<int>(idp.getHMax()));
+ ui_->spinBox_s_min->setValue(static_cast<int>(idp.getSMin() * 100.f));
+ ui_->spinBox_s_max->setValue(static_cast<int>(idp.getSMax() * 100.f));
+ ui_->spinBox_v_min->setValue(static_cast<int>(idp.getVMin() * 100.f));
+ ui_->spinBox_v_max->setValue(static_cast<int>(idp.getVMax() * 100.f));
+
+ ui_->checkBox_color_segmentation_inverted->setChecked(
+ idp.getColorSegmentationInverted());
+ ui_->checkBox_color_segmentation_enabled->setChecked(
+ idp.getColorSegmentationEnabled());
+
+ ui_->spinBox_xyz_erode_size->setValue(idp.getXYZErodeSize());
+ ui_->spinBox_hsv_dilate_size->setValue(idp.getHSVDilateSize());
// Registration
- ui_->lineEdit_epsilon->setValidator (new QDoubleValidator (0., max, 2));
- ui_->lineEdit_max_fitness->setValidator (new QDoubleValidator (0., max, 2));
+ ui_->lineEdit_epsilon->setValidator(new QDoubleValidator(0., max, 2));
+ ui_->lineEdit_max_fitness->setValidator(new QDoubleValidator(0., max, 2));
- ui_->lineEdit_epsilon->setText (QString ().setNum (ihs_->getICP ().getEpsilon ()));
- ui_->spinBox_max_iterations->setValue (static_cast <int> (ihs_->getICP ().getMaxIterations ()));
- ui_->spinBox_min_overlap->setValue (static_cast <int> (100.f * ihs_->getICP ().getMinOverlap ()));
- ui_->lineEdit_max_fitness->setText (QString ().setNum (ihs_->getICP ().getMaxFitness ()));
+ ui_->lineEdit_epsilon->setText(QString().setNum(ihs_->getICP().getEpsilon()));
+ ui_->spinBox_max_iterations->setValue(
+ static_cast<int>(ihs_->getICP().getMaxIterations()));
+ ui_->spinBox_min_overlap->setValue(
+ static_cast<int>(100.f * ihs_->getICP().getMinOverlap()));
+ ui_->lineEdit_max_fitness->setText(QString().setNum(ihs_->getICP().getMaxFitness()));
- ui_->doubleSpinBox_correspondence_rejection_factor->setValue (ihs_->getICP ().getCorrespondenceRejectionFactor ());
- ui_->spinBox_correspondence_rejection_max_angle->setValue (static_cast <int> (ihs_->getICP ().getMaxAngle ()));
+ ui_->doubleSpinBox_correspondence_rejection_factor->setValue(
+ ihs_->getICP().getCorrespondenceRejectionFactor());
+ ui_->spinBox_correspondence_rejection_max_angle->setValue(
+ static_cast<int>(ihs_->getICP().getMaxAngle()));
// Integration
- ui_->lineEdit_max_squared_distance->setValidator (new QDoubleValidator (0., max, 2));
+ ui_->lineEdit_max_squared_distance->setValidator(new QDoubleValidator(0., max, 2));
- ui_->lineEdit_max_squared_distance->setText (QString ().setNum (ihs_->getIntegration ().getMaxSquaredDistance ()));
- ui_->spinBox_averaging_max_angle->setValue (static_cast <int> (ihs_->getIntegration ().getMaxAngle ()));
- ui_->spinBox_max_age->setValue (static_cast <int> (ihs_->getIntegration ().getMaxAge ()));
- ui_->spinBox_min_directions->setValue (static_cast <int> (ihs_->getIntegration ().getMinDirections ()));
+ ui_->lineEdit_max_squared_distance->setText(
+ QString().setNum(ihs_->getIntegration().getMaxSquaredDistance()));
+ ui_->spinBox_averaging_max_angle->setValue(
+ static_cast<int>(ihs_->getIntegration().getMaxAngle()));
+ ui_->spinBox_max_age->setValue(static_cast<int>(ihs_->getIntegration().getMaxAge()));
+ ui_->spinBox_min_directions->setValue(
+ static_cast<int>(ihs_->getIntegration().getMinDirections()));
// Help
- connect (ui_->actionHelp, SIGNAL (triggered ()), this, SLOT (showHelp ()));
+ connect(ui_->actionHelp, SIGNAL(triggered()), this, SLOT(showHelp()));
}
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::MainWindow::~MainWindow ()
-{
- delete ui_;
-}
+pcl::ihs::MainWindow::~MainWindow() { delete ui_; }
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MainWindow::showHelp ()
+pcl::ihs::MainWindow::showHelp()
{
- help_window_->show ();
+ help_window_->show();
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MainWindow::saveAs ()
+pcl::ihs::MainWindow::saveAs()
{
- QString filename = QFileDialog::getSaveFileName (this, "Save the model mesh.", "", "Polygon File Format (*.ply);;VTK File Format (*.vtk)");
+ QString filename = QFileDialog::getSaveFileName(
+ this,
+ "Save the model mesh.",
+ "",
+ "Polygon File Format (*.ply);;VTK File Format (*.vtk)");
- if (filename.isEmpty ()) return;
+ if (filename.isEmpty())
+ return;
- if (filename.endsWith ("ply", Qt::CaseInsensitive))
- ihs_->saveAs (filename.toStdString (), pcl::ihs::InHandScanner::FT_PLY);
- else if (filename.endsWith ("vtk", Qt::CaseInsensitive))
- ihs_->saveAs (filename.toStdString (), pcl::ihs::InHandScanner::FT_VTK);
+ if (filename.endsWith("ply", Qt::CaseInsensitive))
+ ihs_->saveAs(filename.toStdString(), pcl::ihs::InHandScanner::FT_PLY);
+ else if (filename.endsWith("vtk", Qt::CaseInsensitive))
+ ihs_->saveAs(filename.toStdString(), pcl::ihs::InHandScanner::FT_VTK);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MainWindow::runningModeChanged (const RunningMode mode)
-{
- switch (mode)
- {
- case InHandScanner::RM_UNPROCESSED: ui_->toolButton_1->setChecked (true); break;
- case InHandScanner::RM_PROCESSED: ui_->toolButton_2->setChecked (true); break;
- case InHandScanner::RM_REGISTRATION_CONT: ui_->toolButton_3->setChecked (true); break;
- case InHandScanner::RM_REGISTRATION_SINGLE: break;
- case InHandScanner::RM_SHOW_MODEL: ui_->toolButton_5->setChecked (true); break;
+pcl::ihs::MainWindow::runningModeChanged(const RunningMode mode)
+{
+ switch (mode) {
+ case InHandScanner::RM_UNPROCESSED:
+ ui_->toolButton_1->setChecked(true);
+ break;
+ case InHandScanner::RM_PROCESSED:
+ ui_->toolButton_2->setChecked(true);
+ break;
+ case InHandScanner::RM_REGISTRATION_CONT:
+ ui_->toolButton_3->setChecked(true);
+ break;
+ case InHandScanner::RM_REGISTRATION_SINGLE:
+ break;
+ case InHandScanner::RM_SHOW_MODEL:
+ ui_->toolButton_5->setChecked(true);
+ break;
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MainWindow::keyPressEvent (QKeyEvent* event)
+pcl::ihs::MainWindow::keyPressEvent(QKeyEvent* event)
{
- ihs_->keyPressEvent (event);
+ ihs_->keyPressEvent(event);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MainWindow::setXMin (const int x_min)
+pcl::ihs::MainWindow::setXMin(const int x_min)
{
- ihs_->getInputDataProcessing ().setXMin (static_cast <float> (x_min));
- ui_->spinBox_x_min->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getXMin ()));
+ ihs_->getInputDataProcessing().setXMin(static_cast<float>(x_min));
+ ui_->spinBox_x_min->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getXMin()));
}
void
-pcl::ihs::MainWindow::setXMax (const int x_max)
+pcl::ihs::MainWindow::setXMax(const int x_max)
{
- ihs_->getInputDataProcessing ().setXMax (static_cast <float> (x_max));
- ui_->spinBox_x_max->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getXMax ()));
+ ihs_->getInputDataProcessing().setXMax(static_cast<float>(x_max));
+ ui_->spinBox_x_max->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getXMax()));
}
void
-pcl::ihs::MainWindow::setYMin (const int y_min)
+pcl::ihs::MainWindow::setYMin(const int y_min)
{
- ihs_->getInputDataProcessing ().setYMin (static_cast <float> (y_min));
- ui_->spinBox_y_min->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getYMin ()));
+ ihs_->getInputDataProcessing().setYMin(static_cast<float>(y_min));
+ ui_->spinBox_y_min->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getYMin()));
}
void
-pcl::ihs::MainWindow::setYMax (const int y_max)
+pcl::ihs::MainWindow::setYMax(const int y_max)
{
- ihs_->getInputDataProcessing ().setYMax (static_cast <float> (y_max));
- ui_->spinBox_y_max->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getYMax ()));
+ ihs_->getInputDataProcessing().setYMax(static_cast<float>(y_max));
+ ui_->spinBox_y_max->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getYMax()));
}
void
-pcl::ihs::MainWindow::setZMin (const int z_min)
+pcl::ihs::MainWindow::setZMin(const int z_min)
{
- ihs_->getInputDataProcessing ().setZMin (static_cast <float> (z_min));
- ui_->spinBox_z_min->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getZMin ()));
+ ihs_->getInputDataProcessing().setZMin(static_cast<float>(z_min));
+ ui_->spinBox_z_min->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getZMin()));
}
void
-pcl::ihs::MainWindow::setZMax (const int z_max)
+pcl::ihs::MainWindow::setZMax(const int z_max)
{
- ihs_->getInputDataProcessing ().setZMax (static_cast <float> (z_max));
- ui_->spinBox_z_max->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getZMax ()));
+ ihs_->getInputDataProcessing().setZMax(static_cast<float>(z_max));
+ ui_->spinBox_z_max->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getZMax()));
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MainWindow::setHMin (const int h_min)
+pcl::ihs::MainWindow::setHMin(const int h_min)
{
- ihs_->getInputDataProcessing ().setHMin (static_cast <float> (h_min));
- ui_->spinBox_h_min->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getHMin ()));
+ ihs_->getInputDataProcessing().setHMin(static_cast<float>(h_min));
+ ui_->spinBox_h_min->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getHMin()));
}
void
-pcl::ihs::MainWindow::setHMax (const int h_max)
+pcl::ihs::MainWindow::setHMax(const int h_max)
{
- ihs_->getInputDataProcessing ().setHMax (static_cast <float> (h_max));
- ui_->spinBox_h_max->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getHMax ()));
+ ihs_->getInputDataProcessing().setHMax(static_cast<float>(h_max));
+ ui_->spinBox_h_max->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getHMax()));
}
void
-pcl::ihs::MainWindow::setSMin (const int s_min)
+pcl::ihs::MainWindow::setSMin(const int s_min)
{
- ihs_->getInputDataProcessing ().setSMin (.01f * static_cast <float> (s_min));
- ui_->spinBox_s_min->setValue (static_cast <int> (100.f * ihs_->getInputDataProcessing ().getSMin () + 0.5f));
+ ihs_->getInputDataProcessing().setSMin(.01f * static_cast<float>(s_min));
+ ui_->spinBox_s_min->setValue(
+ static_cast<int>(100.f * ihs_->getInputDataProcessing().getSMin() + 0.5f));
}
void
-pcl::ihs::MainWindow::setSMax (const int s_max)
+pcl::ihs::MainWindow::setSMax(const int s_max)
{
- ihs_->getInputDataProcessing ().setSMax (.01f * static_cast <float> (s_max));
- ui_->spinBox_s_max->setValue (static_cast <int> (100.f * ihs_->getInputDataProcessing ().getSMax () + 0.5f));
+ ihs_->getInputDataProcessing().setSMax(.01f * static_cast<float>(s_max));
+ ui_->spinBox_s_max->setValue(
+ static_cast<int>(100.f * ihs_->getInputDataProcessing().getSMax() + 0.5f));
}
void
-pcl::ihs::MainWindow::setVMin (const int v_min)
+pcl::ihs::MainWindow::setVMin(const int v_min)
{
- ihs_->getInputDataProcessing ().setVMin (.01f * static_cast <float> (v_min));
- ui_->spinBox_v_min->setValue (static_cast <int> (100.f * ihs_->getInputDataProcessing ().getVMin () + 0.5f));
+ ihs_->getInputDataProcessing().setVMin(.01f * static_cast<float>(v_min));
+ ui_->spinBox_v_min->setValue(
+ static_cast<int>(100.f * ihs_->getInputDataProcessing().getVMin() + 0.5f));
}
void
-pcl::ihs::MainWindow::setVMax (const int v_max)
+pcl::ihs::MainWindow::setVMax(const int v_max)
{
- ihs_->getInputDataProcessing ().setVMax (.01f * static_cast <float> (v_max));
- ui_->spinBox_v_max->setValue (static_cast <int> (100.f * ihs_->getInputDataProcessing ().getVMax () + 0.5f));
+ ihs_->getInputDataProcessing().setVMax(.01f * static_cast<float>(v_max));
+ ui_->spinBox_v_max->setValue(
+ static_cast<int>(100.f * ihs_->getInputDataProcessing().getVMax() + 0.5f));
}
void
-pcl::ihs::MainWindow::setColorSegmentationInverted (const bool is_inverted)
+pcl::ihs::MainWindow::setColorSegmentationInverted(const bool is_inverted)
{
- ihs_->getInputDataProcessing ().setColorSegmentationInverted (is_inverted);
- ui_->checkBox_color_segmentation_inverted->setChecked (ihs_->getInputDataProcessing ().getColorSegmentationInverted ());
+ ihs_->getInputDataProcessing().setColorSegmentationInverted(is_inverted);
+ ui_->checkBox_color_segmentation_inverted->setChecked(
+ ihs_->getInputDataProcessing().getColorSegmentationInverted());
}
void
-pcl::ihs::MainWindow::setColorSegmentationEnabled (const bool is_enabled)
+pcl::ihs::MainWindow::setColorSegmentationEnabled(const bool is_enabled)
{
- ihs_->getInputDataProcessing ().setColorSegmentationEnabled (is_enabled);
- ui_->checkBox_color_segmentation_enabled->setChecked (ihs_->getInputDataProcessing ().getColorSegmentationEnabled ());
+ ihs_->getInputDataProcessing().setColorSegmentationEnabled(is_enabled);
+ ui_->checkBox_color_segmentation_enabled->setChecked(
+ ihs_->getInputDataProcessing().getColorSegmentationEnabled());
}
void
-pcl::ihs::MainWindow::setXYZErodeSize (const int size)
+pcl::ihs::MainWindow::setXYZErodeSize(const int size)
{
- ihs_->getInputDataProcessing ().setXYZErodeSize (static_cast <unsigned int> (size));
- ui_->spinBox_xyz_erode_size->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getXYZErodeSize ()));
+ ihs_->getInputDataProcessing().setXYZErodeSize(static_cast<unsigned int>(size));
+ ui_->spinBox_xyz_erode_size->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getXYZErodeSize()));
}
void
-pcl::ihs::MainWindow::setHSVDilateSize (const int size)
+pcl::ihs::MainWindow::setHSVDilateSize(const int size)
{
- ihs_->getInputDataProcessing ().setHSVDilateSize (static_cast <unsigned int> (size));
- ui_->spinBox_hsv_dilate_size->setValue (static_cast <int> (ihs_->getInputDataProcessing ().getHSVDilateSize ()));
+ ihs_->getInputDataProcessing().setHSVDilateSize(static_cast<unsigned int>(size));
+ ui_->spinBox_hsv_dilate_size->setValue(
+ static_cast<int>(ihs_->getInputDataProcessing().getHSVDilateSize()));
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MainWindow::setEpsilon ()
+pcl::ihs::MainWindow::setEpsilon()
{
- ihs_->getICP ().setEpsilon (ui_->lineEdit_epsilon->text ().toFloat ());
- ui_->lineEdit_epsilon->setText (QString ().setNum (ihs_->getICP ().getEpsilon ()));
+ ihs_->getICP().setEpsilon(ui_->lineEdit_epsilon->text().toFloat());
+ ui_->lineEdit_epsilon->setText(QString().setNum(ihs_->getICP().getEpsilon()));
}
void
-pcl::ihs::MainWindow::setMaxIterations (const int iterations)
+pcl::ihs::MainWindow::setMaxIterations(const int iterations)
{
- ihs_->getICP ().setMaxIterations (static_cast <unsigned int> (iterations));
- ui_->spinBox_max_iterations->setValue (static_cast <int> (ihs_->getICP ().getMaxIterations ()));
+ ihs_->getICP().setMaxIterations(static_cast<unsigned int>(iterations));
+ ui_->spinBox_max_iterations->setValue(
+ static_cast<int>(ihs_->getICP().getMaxIterations()));
}
void
-pcl::ihs::MainWindow::setMinOverlap (const int overlap)
+pcl::ihs::MainWindow::setMinOverlap(const int overlap)
{
- ihs_->getICP ().setMinOverlap (.01f * static_cast <float> (overlap));
- ui_->spinBox_min_overlap->setValue (static_cast <int> (100.f * ihs_->getICP ().getMinOverlap () + 0.5f));
+ ihs_->getICP().setMinOverlap(.01f * static_cast<float>(overlap));
+ ui_->spinBox_min_overlap->setValue(
+ static_cast<int>(100.f * ihs_->getICP().getMinOverlap() + 0.5f));
}
void
-pcl::ihs::MainWindow::setMaxFitness ()
+pcl::ihs::MainWindow::setMaxFitness()
{
- ihs_->getICP ().setMaxFitness (ui_->lineEdit_max_fitness->text ().toFloat ());
- ui_->lineEdit_max_fitness->setText (QString ().setNum (ihs_->getICP ().getMaxFitness ()));
+ ihs_->getICP().setMaxFitness(ui_->lineEdit_max_fitness->text().toFloat());
+ ui_->lineEdit_max_fitness->setText(QString().setNum(ihs_->getICP().getMaxFitness()));
}
void
-pcl::ihs::MainWindow::setCorrespondenceRejectionFactor (const double factor)
+pcl::ihs::MainWindow::setCorrespondenceRejectionFactor(const double factor)
{
- ihs_->getICP ().setCorrespondenceRejectionFactor (static_cast <float> (factor));
- ui_->doubleSpinBox_correspondence_rejection_factor->setValue (static_cast <double> (ihs_->getICP ().getCorrespondenceRejectionFactor ()));
+ ihs_->getICP().setCorrespondenceRejectionFactor(static_cast<float>(factor));
+ ui_->doubleSpinBox_correspondence_rejection_factor->setValue(
+ static_cast<double>(ihs_->getICP().getCorrespondenceRejectionFactor()));
}
void
-pcl::ihs::MainWindow::setCorrespondenceRejectionMaxAngle (const int angle)
+pcl::ihs::MainWindow::setCorrespondenceRejectionMaxAngle(const int angle)
{
- ihs_->getICP ().setMaxAngle (static_cast <float> (angle));
- ui_->spinBox_correspondence_rejection_max_angle->setValue (static_cast <int> (ihs_->getICP ().getMaxAngle ()));
+ ihs_->getICP().setMaxAngle(static_cast<float>(angle));
+ ui_->spinBox_correspondence_rejection_max_angle->setValue(
+ static_cast<int>(ihs_->getICP().getMaxAngle()));
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MainWindow::setMaxSquaredDistance ()
+pcl::ihs::MainWindow::setMaxSquaredDistance()
{
- ihs_->getIntegration ().setMaxSquaredDistance (ui_->lineEdit_max_squared_distance->text ().toFloat ());
- ui_->lineEdit_max_squared_distance->setText (QString ().setNum (ihs_->getIntegration ().getMaxSquaredDistance ()));
+ ihs_->getIntegration().setMaxSquaredDistance(
+ ui_->lineEdit_max_squared_distance->text().toFloat());
+ ui_->lineEdit_max_squared_distance->setText(
+ QString().setNum(ihs_->getIntegration().getMaxSquaredDistance()));
}
void
-pcl::ihs::MainWindow::setAveragingMaxAngle (const int angle)
+pcl::ihs::MainWindow::setAveragingMaxAngle(const int angle)
{
- ihs_->getIntegration ().setMaxAngle (static_cast <float> (angle));
- ui_->spinBox_averaging_max_angle->setValue (static_cast <int> (ihs_->getIntegration ().getMaxAngle ()));
+ ihs_->getIntegration().setMaxAngle(static_cast<float>(angle));
+ ui_->spinBox_averaging_max_angle->setValue(
+ static_cast<int>(ihs_->getIntegration().getMaxAngle()));
}
void
-pcl::ihs::MainWindow::setMaxAge (const int age)
+pcl::ihs::MainWindow::setMaxAge(const int age)
{
- ihs_->getIntegration ().setMaxAge (static_cast <unsigned int> (age));
- ui_->spinBox_max_age->setValue (static_cast <int> (ihs_->getIntegration ().getMaxAge ()));
+ ihs_->getIntegration().setMaxAge(static_cast<unsigned int>(age));
+ ui_->spinBox_max_age->setValue(static_cast<int>(ihs_->getIntegration().getMaxAge()));
}
void
-pcl::ihs::MainWindow::setMinDirections (const int directions)
+pcl::ihs::MainWindow::setMinDirections(const int directions)
{
- ihs_->getIntegration ().setMinDirections (static_cast <unsigned int> (directions));
- ui_->spinBox_min_directions->setValue (static_cast <int> (ihs_->getIntegration ().getMinDirections ()));
+ ihs_->getIntegration().setMinDirections(static_cast<unsigned int>(directions));
+ ui_->spinBox_min_directions->setValue(
+ static_cast<int>(ihs_->getIntegration().getMinDirections()));
}
////////////////////////////////////////////////////////////////////////////////
*/
#include <pcl/apps/in_hand_scanner/mesh_processing.h>
+#include <pcl/apps/in_hand_scanner/utils.h>
#include <cmath>
-#include <pcl/apps/in_hand_scanner/utils.h>
-
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::MeshProcessing::MeshProcessing ()
-{
-}
+pcl::ihs::MeshProcessing::MeshProcessing() = default;
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::MeshProcessing::processBoundary (Mesh& mesh, const std::vector <HalfEdgeIndices>& boundary_collection, const bool cleanup) const
+pcl::ihs::MeshProcessing::processBoundary(
+ Mesh& mesh,
+ const std::vector<HalfEdgeIndices>& boundary_collection,
+ const bool cleanup) const
{
Mesh::VertexIndex vi_a, vi_b, vi_c, vi_d;
Eigen::Vector3f ab, bc, ac, n_adb, n_plane; // Edges and normals
Mesh::FaceIndex opposite_face;
- for (const auto &boundary : boundary_collection)
- {
- if (boundary.size () == 3)
- {
- opposite_face = mesh.getOppositeFaceIndex (boundary [0]);
+ for (const auto& boundary : boundary_collection) {
+ if (boundary.size() == 3) {
+ opposite_face = mesh.getOppositeFaceIndex(boundary[0]);
- if (mesh.getOppositeFaceIndex (boundary [1]) == opposite_face &&
- mesh.getOppositeFaceIndex (boundary [2]) == opposite_face)
- {
+ if (mesh.getOppositeFaceIndex(boundary[1]) == opposite_face &&
+ mesh.getOppositeFaceIndex(boundary[2]) == opposite_face) {
// Isolated face.
- mesh.deleteFace (opposite_face);
+ mesh.deleteFace(opposite_face);
}
- else
- {
+ else {
// Close triangular hole.
- mesh.addFace (mesh.getTerminatingVertexIndex (boundary [0]),
- mesh.getTerminatingVertexIndex (boundary [1]),
- mesh.getTerminatingVertexIndex (boundary [2]));
+ mesh.addFace(mesh.getTerminatingVertexIndex(boundary[0]),
+ mesh.getTerminatingVertexIndex(boundary[1]),
+ mesh.getTerminatingVertexIndex(boundary[2]));
}
}
else // size != 3
{
- // Add triangles where the angle between the edges is below a threshold. In the example this would leave only triangles 1-2-3 and triangles 4-5-6 (threshold = 60 degrees). Triangle 1-2-3 should not be added because vertex 2 is not convex (as vertex 5).
+ // Add triangles where the angle between the edges is below a threshold. In the
+ // example this would leave only triangles 1-2-3 and triangles 4-5-6 (threshold =
+ // 60 degrees). Triangle 1-2-3 should not be added because vertex 2 is not convex
+ // (as vertex 5).
// Example: The boundary is on the top. Vertex 7 is connected to vertex 0.
// 2 //
// \ / //
// 5 //
- for (std::size_t i=0; i<boundary.size (); ++i)
- {
+ for (std::size_t i = 0; i < boundary.size(); ++i) {
// The vertices on the boundary
- vi_a = mesh.getOriginatingVertexIndex (boundary [i]);
- vi_b = mesh.getTerminatingVertexIndex (boundary [i]);
- vi_c = mesh.getTerminatingVertexIndex (boundary [(i+1) % boundary.size ()]);
+ vi_a = mesh.getOriginatingVertexIndex(boundary[i]);
+ vi_b = mesh.getTerminatingVertexIndex(boundary[i]);
+ vi_c = mesh.getTerminatingVertexIndex(boundary[(i + 1) % boundary.size()]);
- const Eigen::Vector4f& v_a = mesh.getVertexDataCloud () [vi_a.get ()].getVector4fMap ();
- const Eigen::Vector4f& v_b = mesh.getVertexDataCloud () [vi_b.get ()].getVector4fMap ();
- const Eigen::Vector4f& v_c = mesh.getVertexDataCloud () [vi_c.get ()].getVector4fMap ();
+ const Eigen::Vector4f& v_a =
+ mesh.getVertexDataCloud()[vi_a.get()].getVector4fMap();
+ const Eigen::Vector4f& v_b =
+ mesh.getVertexDataCloud()[vi_b.get()].getVector4fMap();
+ const Eigen::Vector4f& v_c =
+ mesh.getVertexDataCloud()[vi_c.get()].getVector4fMap();
- ab = (v_b - v_a).head <3> ();
- bc = (v_c - v_b).head <3> ();
- ac = (v_c - v_a).head <3> ();
+ ab = (v_b - v_a).head<3>();
+ bc = (v_c - v_b).head<3>();
+ ac = (v_c - v_a).head<3>();
- const float angle = std::acos (pcl::ihs::clamp (-ab.dot (bc) / ab.norm () / bc.norm (), -1.f, 1.f));
+ const float angle =
+ std::acos(pcl::ihs::clamp(-ab.dot(bc) / ab.norm() / bc.norm(), -1.f, 1.f));
if (angle < 1.047197551196598f) // 60 * pi / 180
{
// Third vertex belonging to the face of edge ab
- vi_d = mesh.getTerminatingVertexIndex (
- mesh.getNextHalfEdgeIndex (
- mesh.getOppositeHalfEdgeIndex (boundary [i])));
- const Eigen::Vector4f& v_d = mesh.getVertexDataCloud () [vi_d.get ()].getVector4fMap ();
+ vi_d = mesh.getTerminatingVertexIndex(
+ mesh.getNextHalfEdgeIndex(mesh.getOppositeHalfEdgeIndex(boundary[i])));
+ const Eigen::Vector4f& v_d =
+ mesh.getVertexDataCloud()[vi_d.get()].getVector4fMap();
// n_adb is the normal of triangle a-d-b.
- // The plane goes through edge a-b and is perpendicular to the plane through a-d-b.
- n_adb = (v_d - v_a).head <3> ().cross (ab)/*.normalized ()*/;
- n_plane = n_adb.cross (ab/*.nomalized ()*/);
+ // The plane goes through edge a-b and is perpendicular to the plane through
+ // a-d-b.
+ n_adb = (v_d - v_a).head<3>().cross(ab) /*.normalized()*/;
+ n_plane = n_adb.cross(ab /*.nomalized()*/);
- if (n_plane.dot (ac) > 0.f)
- {
- mesh.addFace (vi_a, vi_b, vi_c);
+ if (n_plane.dot(ac) > 0.f) {
+ mesh.addFace(vi_a, vi_b, vi_c);
}
}
}
}
if (cleanup)
- mesh.cleanUp ();
+ mesh.cleanUp();
}
////////////////////////////////////////////////////////////////////////////////
*
*/
+#include <pcl/apps/in_hand_scanner/integration.h>
#include <pcl/apps/in_hand_scanner/offline_integration.h>
+#include <pcl/common/transforms.h>
+#include <pcl/features/integral_image_normal.h>
+#include <pcl/io/pcd_io.h>
-#include <iomanip>
-#include <fstream>
-
-#include <boost/filesystem.hpp>
#include <boost/algorithm/string/case_conv.hpp>
+#include <boost/filesystem.hpp>
#include <QApplication>
#include <QFileDialog>
-#include <QtCore>
#include <QKeyEvent>
#include <QtConcurrent>
+#include <QtCore>
-#include <pcl/io/pcd_io.h>
-#include <pcl/common/transforms.h>
-#include <pcl/features/integral_image_normal.h>
-#include <pcl/apps/in_hand_scanner/integration.h>
+#include <fstream>
+#include <iomanip>
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::OfflineIntegration::OfflineIntegration (Base* parent)
- : Base (parent),
- mesh_model_ (new Mesh ()),
- normal_estimation_ (new NormalEstimation ()),
- integration_ (new Integration ()),
- destructor_called_ (false)
+pcl::ihs::OfflineIntegration::OfflineIntegration(Base* parent)
+: Base(parent)
+, mesh_model_(new Mesh())
+, normal_estimation_(new NormalEstimation())
+, integration_(new Integration())
+, destructor_called_(false)
{
- normal_estimation_->setNormalEstimationMethod (NormalEstimation::AVERAGE_3D_GRADIENT);
- normal_estimation_->setMaxDepthChangeFactor (0.02f); // in meters
- normal_estimation_->setNormalSmoothingSize (10.0f);
-
- integration_->setMaxSquaredDistance (1e-4); // in m^2
- integration_->setMinDirections (2);
+ normal_estimation_->setNormalEstimationMethod(NormalEstimation::AVERAGE_3D_GRADIENT);
+ normal_estimation_->setMaxDepthChangeFactor(0.02f); // in meters
+ normal_estimation_->setNormalSmoothingSize(10.0f);
+ integration_->setMaxSquaredDistance(1e-4); // in m^2
+ integration_->setMinDirections(2);
- Base::setVisibilityConfidenceNormalization (static_cast <float> (integration_->getMinDirections ()));
+ Base::setVisibilityConfidenceNormalization(
+ static_cast<float>(integration_->getMinDirections()));
}
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::OfflineIntegration::~OfflineIntegration ()
+pcl::ihs::OfflineIntegration::~OfflineIntegration()
{
- std::lock_guard<std::mutex> lock (mutex_);
- std::lock_guard<std::mutex> lock_quit (mutex_quit_);
+ std::lock_guard<std::mutex> lock(mutex_);
+ std::lock_guard<std::mutex> lock_quit(mutex_quit_);
destructor_called_ = true;
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OfflineIntegration::start ()
+pcl::ihs::OfflineIntegration::start()
{
- QString dir = QFileDialog::getExistingDirectory (nullptr, "Please select a directory containing .pcd and .transform files.");
+ QString dir = QFileDialog::getExistingDirectory(
+ nullptr, "Please select a directory containing .pcd and .transform files.");
- if (dir.isEmpty ())
- {
- return (QApplication::quit ());
+ if (dir.isEmpty()) {
+ return (QApplication::quit());
}
- path_dir_ = dir.toStdString ();
- QtConcurrent::run ([this]{ computationThread (); });
+ path_dir_ = dir.toStdString();
+ QtConcurrent::run([this] { computationThread(); });
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OfflineIntegration::computationThread ()
+pcl::ihs::OfflineIntegration::computationThread()
{
- std::vector <std::string> filenames;
+ std::vector<std::string> filenames;
- if (!this->getFilesFromDirectory (path_dir_, ".pcd", filenames))
- {
- std::cerr << "ERROR in offline_integration.cpp: Could not get the files from the directory\n";
+ if (!this->getFilesFromDirectory(path_dir_, ".pcd", filenames)) {
+ std::cerr << "ERROR in offline_integration.cpp: Could not get the files from the "
+ "directory\n";
return;
}
// First cloud is reference model
- std::cerr << "Processing file " << std::setw (5) << 1 << " / " << filenames.size () << std::endl;
- CloudXYZRGBNormalPtr cloud_model (new CloudXYZRGBNormal ());
- Eigen::Matrix4f T = Eigen::Matrix4f::Identity ();
- if (!this->load (filenames [0], cloud_model, T))
- {
+ std::cerr << "Processing file " << std::setw(5) << 1 << " / " << filenames.size()
+ << std::endl;
+ CloudXYZRGBNormalPtr cloud_model(new CloudXYZRGBNormal());
+ Eigen::Matrix4f T = Eigen::Matrix4f::Identity();
+ if (!this->load(filenames[0], cloud_model, T)) {
std::cerr << "ERROR in offline_integration.cpp: Could not load the model cloud.\n";
return;
}
- pcl::transformPointCloudWithNormals (*cloud_model, *cloud_model, T);
+ pcl::transformPointCloudWithNormals(*cloud_model, *cloud_model, T);
- if (!integration_->reconstructMesh (cloud_model, mesh_model_))
- {
- std::cerr << "ERROR in offline_integration.cpp: Could not reconstruct the model mesh.\n";
+ if (!integration_->reconstructMesh(cloud_model, mesh_model_)) {
+ std::cerr
+ << "ERROR in offline_integration.cpp: Could not reconstruct the model mesh.\n";
return;
}
- Base::setPivot ("model");
- Base::addMesh (mesh_model_, "model");
+ Base::setPivot("model");
+ Base::addMesh(mesh_model_, "model");
- if (filenames.empty ())
- {
+ if (filenames.empty()) {
return;
}
- for (std::size_t i=1; i<filenames.size (); ++i)
- {
- std::cerr << "Processing file " << std::setw (5) << i+1 << " / " << filenames.size () << std::endl;
+ for (std::size_t i = 1; i < filenames.size(); ++i) {
+ std::cerr << "Processing file " << std::setw(5) << i + 1 << " / "
+ << filenames.size() << std::endl;
{
- std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
}
- std::unique_lock<std::mutex> lock_quit (mutex_quit_);
+ std::unique_lock<std::mutex> lock_quit(mutex_quit_);
- CloudXYZRGBNormalPtr cloud_data (new CloudXYZRGBNormal ());
- if (!this->load (filenames [i], cloud_data, T))
- {
+ CloudXYZRGBNormalPtr cloud_data(new CloudXYZRGBNormal());
+ if (!this->load(filenames[i], cloud_data, T)) {
std::cerr << "ERROR in offline_integration.cpp: Could not load the data cloud.\n";
return;
}
- if (!integration_->merge (cloud_data, mesh_model_, T))
- {
+ if (!integration_->merge(cloud_data, mesh_model_, T)) {
std::cerr << "ERROR in offline_integration.cpp: merge failed.\n";
return;
}
- integration_->age (mesh_model_);
+ integration_->age(mesh_model_);
{
- lock_quit.unlock ();
- std::lock_guard<std::mutex> lock (mutex_);
- if (destructor_called_) return;
-
- Base::addMesh (mesh_model_, "model", Eigen::Isometry3d (T.inverse ().cast <double> ()));
- Base::calcFPS (computation_fps_);
+ lock_quit.unlock();
+ std::lock_guard<std::mutex> lock(mutex_);
+ if (destructor_called_)
+ return;
+
+ Base::addMesh(
+ mesh_model_, "model", Eigen::Isometry3d(T.inverse().cast<double>()));
+ Base::calcFPS(computation_fps_);
}
}
- Base::setPivot ("model");
+ Base::setPivot("model");
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::OfflineIntegration::getFilesFromDirectory (const std::string& path_dir,
- const std::string& extension,
- std::vector <std::string>& files) const
+pcl::ihs::OfflineIntegration::getFilesFromDirectory(
+ const std::string& path_dir,
+ const std::string& extension,
+ std::vector<std::string>& files) const
{
- if (path_dir.empty() || !boost::filesystem::exists (path_dir))
- {
- std::cerr << "ERROR in offline_integration.cpp: Invalid path\n '" << path_dir << "'\n";
+ if (path_dir.empty() || !boost::filesystem::exists(path_dir)) {
+ std::cerr << "ERROR in offline_integration.cpp: Invalid path\n '" << path_dir
+ << "'\n";
return (false);
}
boost::filesystem::directory_iterator it_end;
- for (boost::filesystem::directory_iterator it (path_dir); it != it_end; ++it)
- {
- if (!is_directory (it->status ()) &&
- boost::algorithm::to_upper_copy (boost::filesystem::extension (it->path ())) == boost::algorithm::to_upper_copy (extension))
- {
- files.push_back (it->path ().string ());
+ for (boost::filesystem::directory_iterator it(path_dir); it != it_end; ++it) {
+ if (!is_directory(it->status()) &&
+ boost::algorithm::to_upper_copy(boost::filesystem::extension(it->path())) ==
+ boost::algorithm::to_upper_copy(extension)) {
+ files.push_back(it->path().string());
}
}
- if (files.empty ())
- {
- std::cerr << "ERROR in offline_integration.cpp: No '" << extension << "' files found\n";
+ if (files.empty()) {
+ std::cerr << "ERROR in offline_integration.cpp: No '" << extension
+ << "' files found\n";
return (false);
}
- sort (files.begin (), files.end ());
+ sort(files.begin(), files.end());
return (true);
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::OfflineIntegration::loadTransform (const std::string& filename,
- Eigen::Matrix4f& transform) const
+pcl::ihs::OfflineIntegration::loadTransform(const std::string& filename,
+ Eigen::Matrix4f& transform) const
{
- Eigen::Matrix4d tr;
- std::ifstream file;
- file.open (filename.c_str (), std::ios::binary);
-
- if (!file.is_open ())
- {
- std::cerr << "Error in offline_integration.cpp: Could not open the file '" << filename << "'\n";
- return (false);
- }
-
- for (int i = 0; i < 4; ++i)
- {
- for (int j = 0; j < 4; ++j)
- {
- file.read (reinterpret_cast<char*>(&tr (i, j)), sizeof (double));
-
- if (!file.good ())
- {
- std::cerr << "Error in offline_integration.cpp: Could not read the transformation from the file.\n";
- return (false);
- }
- }
- }
-
- transform = tr.cast<float> ();
-
- return (true);
+ Eigen::Matrix4d tr;
+ std::ifstream file;
+ file.open(filename.c_str(), std::ios::binary);
+
+ if (!file.is_open()) {
+ std::cerr << "Error in offline_integration.cpp: Could not open the file '"
+ << filename << "'\n";
+ return (false);
+ }
+
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 4; ++j) {
+ file.read(reinterpret_cast<char*>(&tr(i, j)), sizeof(double));
+
+ if (!file.good()) {
+ std::cerr << "Error in offline_integration.cpp: Could not read the "
+ "transformation from the file.\n";
+ return (false);
+ }
+ }
+ }
+
+ transform = tr.cast<float>();
+
+ return (true);
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::OfflineIntegration::load (const std::string& filename,
- CloudXYZRGBNormalPtr& cloud,
- Eigen::Matrix4f& T) const
+pcl::ihs::OfflineIntegration::load(const std::string& filename,
+ CloudXYZRGBNormalPtr& cloud,
+ Eigen::Matrix4f& T) const
{
- if (!cloud)
- {
- cloud = CloudXYZRGBNormalPtr (new CloudXYZRGBNormal ());
+ if (!cloud) {
+ cloud = CloudXYZRGBNormalPtr(new CloudXYZRGBNormal());
}
// Load the cloud.
- CloudXYZRGBAPtr cloud_input (new CloudXYZRGBA ());
+ CloudXYZRGBAPtr cloud_input(new CloudXYZRGBA());
pcl::PCDReader reader;
- if (reader.read (filename, *cloud_input) < 0)
- {
+ if (reader.read(filename, *cloud_input) < 0) {
std::cerr << "ERROR in offline_integration.cpp: Could not read the pcd file.\n";
return (false);
}
// Normal estimation.
- normal_estimation_->setInputCloud (cloud_input);
- normal_estimation_->compute (*cloud);
+ normal_estimation_->setInputCloud(cloud_input);
+ normal_estimation_->compute(*cloud);
- pcl::copyPointCloud (*cloud_input, *cloud);
+ pcl::copyPointCloud(*cloud_input, *cloud);
// Change the file extension of the file.
// Load the transformation.
std::string fn_transform = filename;
- std::size_t pos = fn_transform.find_last_of ('.');
- if (pos == std::string::npos || pos == (fn_transform.size () - 1))
- {
+ std::size_t pos = fn_transform.find_last_of('.');
+ if (pos == std::string::npos || pos == (fn_transform.size() - 1)) {
std::cerr << "ERROR in offline_integration.cpp: No file extension\n";
return (false);
}
- fn_transform.replace (pos, std::string::npos, ".transform");
+ fn_transform.replace(pos, std::string::npos, ".transform");
- if (!this->loadTransform (fn_transform, T))
- {
- std::cerr << "ERROR in offline_integration.cpp: Could not load the transformation.\n";
+ if (!this->loadTransform(fn_transform, T)) {
+ std::cerr
+ << "ERROR in offline_integration.cpp: Could not load the transformation.\n";
return (false);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OfflineIntegration::paintEvent (QPaintEvent* event)
+pcl::ihs::OfflineIntegration::paintEvent(QPaintEvent* event)
{
- Base::paintEvent (event);
+ Base::paintEvent(event);
- QPainter painter (this);
- painter.setPen (Qt::white);
+ QPainter painter(this);
+ painter.setPen(Qt::white);
QFont font;
- font.setPointSize (this->width () / 50);
- painter.setFont (font);
+ font.setPointSize(this->width() / 50);
+ painter.setFont(font);
- std::string vis_fps ("Visualization: "), comp_fps ("Computation: ");
+ std::string vis_fps("Visualization: "), comp_fps("Computation: ");
{
- std::lock_guard<std::mutex> lock (mutex_);
- this->calcFPS (visualization_fps_);
+ std::lock_guard<std::mutex> lock(mutex_);
+ this->calcFPS(visualization_fps_);
- vis_fps.append (visualization_fps_.str ()).append (" fps");
- comp_fps.append (computation_fps_.str ()).append (" fps");
+ vis_fps.append(visualization_fps_.str()).append(" fps");
+ comp_fps.append(computation_fps_.str()).append(" fps");
}
- const std::string str = std::string (comp_fps).append ("\n").append (vis_fps);
+ const std::string str = std::string(comp_fps).append("\n").append(vis_fps);
- painter.drawText (0, 0, this->width (), this->height (), Qt::AlignBottom | Qt::AlignLeft, str.c_str ());
+ painter.drawText(0,
+ 0,
+ this->width(),
+ this->height(),
+ Qt::AlignBottom | Qt::AlignLeft,
+ str.c_str());
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OfflineIntegration::keyPressEvent (QKeyEvent* event)
+pcl::ihs::OfflineIntegration::keyPressEvent(QKeyEvent* event)
{
- if (event->key () == Qt::Key_Escape)
- {
- std::lock_guard<std::mutex> lock (mutex_);
- QApplication::quit ();
+ if (event->key() == Qt::Key_Escape) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ QApplication::quit();
}
- switch (event->key ())
- {
- case Qt::Key_H:
- {
- std::cerr << "======================================================================\n"
- << "Help:\n"
- << "----------------------------------------------------------------------\n"
- << "ESC: Quit the application.\n"
- << "c : Reset the camera.\n"
- << "k : Toggle the coloring (rgb, one color, visibility-confidence).\n"
- << "s : Toggle the mesh representation between points and faces.\n"
- << "======================================================================\n";
- break;
- }
- case Qt::Key_C: Base::resetCamera (); break;
- case Qt::Key_K: Base::toggleColoring (); break;
- case Qt::Key_S: Base::toggleMeshRepresentation (); break;
- default: break;
+ switch (event->key()) {
+ case Qt::Key_H: {
+ std::cerr
+ << "======================================================================\n"
+ << "Help:\n"
+ << "----------------------------------------------------------------------\n"
+ << "ESC: Quit the application.\n"
+ << "c : Reset the camera.\n"
+ << "k : Toggle the coloring (rgb, one color, visibility-confidence).\n"
+ << "s : Toggle the mesh representation between points and faces.\n"
+ << "======================================================================\n";
+ break;
+ }
+ case Qt::Key_C:
+ Base::resetCamera();
+ break;
+ case Qt::Key_K:
+ Base::toggleColoring();
+ break;
+ case Qt::Key_S:
+ Base::toggleMeshRepresentation();
+ break;
+ default:
+ break;
}
}
*/
#include <pcl/apps/in_hand_scanner/opengl_viewer.h>
+#include <pcl/pcl_config.h>
#include <cmath>
-#include <typeinfo>
#include <cstdlib>
-
-#include <pcl/pcl_config.h>
+#include <typeinfo>
#ifdef OPENGL_IS_A_FRAMEWORK
-# include <OpenGL/gl.h>
-# include <OpenGL/glu.h>
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
#else
-# include <GL/gl.h>
-# include <GL/glu.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
#endif
-#include <QtOpenGL>
-
+#include <pcl/apps/in_hand_scanner/visibility_confidence.h>
#include <pcl/common/centroid.h>
#include <pcl/common/impl/centroid.hpp> // TODO: PointIHS is not registered
-#include <pcl/apps/in_hand_scanner/visibility_confidence.h>
+
+#include <QtOpenGL>
////////////////////////////////////////////////////////////////////////////////
// FaceVertexMesh
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::detail::FaceVertexMesh::FaceVertexMesh ()
- : transformation (Eigen::Isometry3d::Identity ())
-{
-}
+pcl::ihs::detail::FaceVertexMesh::FaceVertexMesh()
+: transformation(Eigen::Isometry3d::Identity())
+{}
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::detail::FaceVertexMesh::FaceVertexMesh (const Mesh& mesh, const Eigen::Isometry3d& T)
- : vertices (mesh.getVertexDataCloud ()),
- transformation (T)
+pcl::ihs::detail::FaceVertexMesh::FaceVertexMesh(const Mesh& mesh,
+ const Eigen::Isometry3d& T)
+: vertices(mesh.getVertexDataCloud()), transformation(T)
{
- if (typeid (Mesh::MeshTag) != typeid (pcl::geometry::TriangleMeshTag))
- {
- std::cerr << "In opengl_viewer.cpp: Only triangle meshes are currently supported!\n";
- exit (EXIT_FAILURE);
+ if (typeid(Mesh::MeshTag) != typeid(pcl::geometry::TriangleMeshTag)) {
+ std::cerr
+ << "In opengl_viewer.cpp: Only triangle meshes are currently supported!\n";
+ exit(EXIT_FAILURE);
}
- for (auto &vertex : vertices)
- {
- std::swap (vertex.r, vertex.b);
+ for (auto& vertex : vertices) {
+ std::swap(vertex.r, vertex.b);
}
- triangles.reserve (mesh.sizeFaces ());
+ triangles.reserve(mesh.sizeFaces());
pcl::ihs::detail::FaceVertexMesh::Triangle triangle;
- for (std::size_t i=0; i<mesh.sizeFaces (); ++i)
- {
- Mesh::VertexAroundFaceCirculator circ = mesh.getVertexAroundFaceCirculator (Mesh::FaceIndex (i));
- triangle.first = (circ++).getTargetIndex ().get ();
- triangle.second = (circ++).getTargetIndex ().get ();
- triangle.third = (circ ).getTargetIndex ().get ();
+ for (std::size_t i = 0; i < mesh.sizeFaces(); ++i) {
+ Mesh::VertexAroundFaceCirculator circ =
+ mesh.getVertexAroundFaceCirculator(Mesh::FaceIndex(i));
+ triangle.first = (circ++).getTargetIndex().get();
+ triangle.second = (circ++).getTargetIndex().get();
+ triangle.third = (circ).getTargetIndex().get();
- triangles.push_back (triangle);
+ triangles.push_back(triangle);
}
}
// OpenGLViewer
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::OpenGLViewer::OpenGLViewer (QWidget* parent)
- : QGLWidget (parent),
- timer_vis_ (new QTimer (this)),
- colormap_ (Colormap::Constant (255)),
- vis_conf_norm_ (1),
- mesh_representation_ (MR_POINTS),
- coloring_ (COL_RGB),
- draw_box_ (false),
- scaling_factor_ (1.),
- R_cam_ (1., 0., 0., 0.),
- t_cam_ (0., 0., 0.),
- cam_pivot_ (0., 0., 0.),
- cam_pivot_id_ (""),
- mouse_pressed_begin_ (false),
- x_prev_ (0),
- y_prev_ (0)
+pcl::ihs::OpenGLViewer::OpenGLViewer(QWidget* parent)
+: QGLWidget(parent)
+, timer_vis_(new QTimer(this))
+, colormap_(Colormap::Constant(255))
+, vis_conf_norm_(1)
+, mesh_representation_(MR_POINTS)
+, coloring_(COL_RGB)
+, draw_box_(false)
+, scaling_factor_(1.)
+, R_cam_(1., 0., 0., 0.)
+, t_cam_(0., 0., 0.)
+, cam_pivot_(0., 0., 0.)
+, cam_pivot_id_("")
+, mouse_pressed_begin_(false)
+, x_prev_(0)
+, y_prev_(0)
{
// Timer: Defines the update rate for the visualization
- connect (timer_vis_.get (), SIGNAL (timeout ()), this, SLOT (timerCallback ()));
- timer_vis_->start (33);
+ connect(timer_vis_.get(), SIGNAL(timeout()), this, SLOT(timerCallback()));
+ timer_vis_->start(33);
// http://doc.qt.digia.com/qt/opengl-overpainting.html
- QWidget::setAutoFillBackground (false);
+ QWidget::setAutoFillBackground(false);
// http://doc.qt.digia.com/qt/qwidget.html#keyPressEvent
- this->setFocusPolicy (Qt::StrongFocus);
+ this->setFocusPolicy(Qt::StrongFocus);
// http://doc.qt.digia.com/qt/qmetatype.html#qRegisterMetaType
- qRegisterMetaType <pcl::ihs::OpenGLViewer::MeshRepresentation> ("MeshRepresentation");
- qRegisterMetaType <pcl::ihs::OpenGLViewer::Coloring> ("Coloring");
+ qRegisterMetaType<pcl::ihs::OpenGLViewer::MeshRepresentation>("MeshRepresentation");
+ qRegisterMetaType<pcl::ihs::OpenGLViewer::Coloring>("Coloring");
//////////////////////////////////////////////////////////////////////////////
- // Code to generate the colormap (I don't want to link against vtk just for the colormap).
+ // Code to generate the colormap (I don't want to link against vtk just for the
+ // colormap).
//////////////////////////////////////////////////////////////////////////////
//#include <cstdlib>
//#include <vtkColorTransferFunction.h>
//#include <vtkSmartPointer.h>
- //int
- //main ()
- //{
- // static const unsigned int n = 256;
- // // double rgb_1 [] = { 59./255., 76./255., 192./255.};
- // // double rgb_2 [] = {180./255., 4./255., 38./255.};
- // double rgb_1 [] = {180./255., 0./255., 0./255.};
- // double rgb_2 [] = { 0./255., 180./255., 0./255.};
-
- // vtkSmartPointer <vtkColorTransferFunction> ctf = vtkColorTransferFunction::New ();
- // ctf->SetColorSpaceToDiverging ();
- // ctf->AddRGBPoint ( 0., rgb_1 [0], rgb_1 [1], rgb_1 [2]);
- // ctf->AddRGBPoint ( 1., rgb_2 [0], rgb_2 [1], rgb_2 [2]);
- // ctf->Build ();
-
- // const unsigned char* colormap = ctf->GetTable (0., 1., n);
-
- // for (unsigned int i=0; i<n; ++i)
- // {
- // const unsigned int r = static_cast <unsigned int> (colormap [3 * i ]);
- // const unsigned int g = static_cast <unsigned int> (colormap [3 * i + 1]);
- // const unsigned int b = static_cast <unsigned int> (colormap [3 * i + 2]);
-
- // std::cerr << "colormap_.col ("
- // << std::setw (3) << i << ") = Color ("
- // << std::setw (3) << r << ", "
- // << std::setw (3) << g << ", "
- // << std::setw (3) << b << ");\n";
- // }
-
- // return (EXIT_SUCCESS);
- //}
-
- colormap_.col ( 0) = Color (180, 0, 0);
- colormap_.col ( 1) = Color (182, 9, 1);
- colormap_.col ( 2) = Color (184, 17, 1);
- colormap_.col ( 3) = Color (186, 24, 2);
- colormap_.col ( 4) = Color (188, 29, 2);
- colormap_.col ( 5) = Color (190, 33, 3);
- colormap_.col ( 6) = Color (192, 38, 4);
- colormap_.col ( 7) = Color (194, 42, 5);
- colormap_.col ( 8) = Color (196, 46, 6);
- colormap_.col ( 9) = Color (197, 49, 7);
- colormap_.col ( 10) = Color (199, 53, 9);
- colormap_.col ( 11) = Color (201, 56, 10);
- colormap_.col ( 12) = Color (203, 59, 12);
- colormap_.col ( 13) = Color (205, 63, 13);
- colormap_.col ( 14) = Color (207, 66, 15);
- colormap_.col ( 15) = Color (208, 69, 17);
- colormap_.col ( 16) = Color (210, 72, 18);
- colormap_.col ( 17) = Color (212, 75, 20);
- colormap_.col ( 18) = Color (214, 78, 21);
- colormap_.col ( 19) = Color (215, 81, 23);
- colormap_.col ( 20) = Color (217, 84, 25);
- colormap_.col ( 21) = Color (219, 87, 26);
- colormap_.col ( 22) = Color (221, 89, 28);
- colormap_.col ( 23) = Color (222, 92, 30);
- colormap_.col ( 24) = Color (224, 95, 32);
- colormap_.col ( 25) = Color (225, 98, 33);
- colormap_.col ( 26) = Color (227, 101, 35);
- colormap_.col ( 27) = Color (229, 103, 37);
- colormap_.col ( 28) = Color (230, 106, 39);
- colormap_.col ( 29) = Color (232, 109, 40);
- colormap_.col ( 30) = Color (233, 112, 42);
- colormap_.col ( 31) = Color (235, 114, 44);
- colormap_.col ( 32) = Color (236, 117, 46);
- colormap_.col ( 33) = Color (238, 120, 48);
- colormap_.col ( 34) = Color (239, 122, 50);
- colormap_.col ( 35) = Color (241, 125, 52);
- colormap_.col ( 36) = Color (242, 127, 54);
- colormap_.col ( 37) = Color (244, 130, 56);
- colormap_.col ( 38) = Color (245, 133, 58);
- colormap_.col ( 39) = Color (246, 135, 60);
- colormap_.col ( 40) = Color (248, 138, 62);
- colormap_.col ( 41) = Color (249, 140, 64);
- colormap_.col ( 42) = Color (250, 143, 66);
- colormap_.col ( 43) = Color (252, 145, 68);
- colormap_.col ( 44) = Color (253, 148, 70);
- colormap_.col ( 45) = Color (254, 150, 73);
- colormap_.col ( 46) = Color (255, 153, 75);
- colormap_.col ( 47) = Color (255, 154, 76);
- colormap_.col ( 48) = Color (255, 156, 78);
- colormap_.col ( 49) = Color (255, 158, 80);
- colormap_.col ( 50) = Color (255, 159, 82);
- colormap_.col ( 51) = Color (255, 161, 84);
- colormap_.col ( 52) = Color (255, 163, 86);
- colormap_.col ( 53) = Color (255, 164, 88);
- colormap_.col ( 54) = Color (255, 166, 90);
- colormap_.col ( 55) = Color (255, 168, 92);
- colormap_.col ( 56) = Color (255, 169, 93);
- colormap_.col ( 57) = Color (255, 171, 95);
- colormap_.col ( 58) = Color (255, 172, 97);
- colormap_.col ( 59) = Color (255, 174, 99);
- colormap_.col ( 60) = Color (255, 176, 101);
- colormap_.col ( 61) = Color (255, 177, 103);
- colormap_.col ( 62) = Color (255, 179, 105);
- colormap_.col ( 63) = Color (255, 180, 107);
- colormap_.col ( 64) = Color (255, 182, 109);
- colormap_.col ( 65) = Color (255, 183, 111);
- colormap_.col ( 66) = Color (255, 185, 113);
- colormap_.col ( 67) = Color (255, 186, 115);
- colormap_.col ( 68) = Color (255, 188, 117);
- colormap_.col ( 69) = Color (255, 189, 119);
- colormap_.col ( 70) = Color (255, 191, 122);
- colormap_.col ( 71) = Color (255, 192, 124);
- colormap_.col ( 72) = Color (255, 194, 126);
- colormap_.col ( 73) = Color (255, 195, 128);
- colormap_.col ( 74) = Color (255, 196, 130);
- colormap_.col ( 75) = Color (255, 198, 132);
- colormap_.col ( 76) = Color (255, 199, 134);
- colormap_.col ( 77) = Color (255, 201, 136);
- colormap_.col ( 78) = Color (255, 202, 139);
- colormap_.col ( 79) = Color (255, 203, 141);
- colormap_.col ( 80) = Color (255, 205, 143);
- colormap_.col ( 81) = Color (255, 206, 145);
- colormap_.col ( 82) = Color (255, 207, 147);
- colormap_.col ( 83) = Color (255, 209, 149);
- colormap_.col ( 84) = Color (255, 210, 152);
- colormap_.col ( 85) = Color (255, 211, 154);
- colormap_.col ( 86) = Color (255, 213, 156);
- colormap_.col ( 87) = Color (255, 214, 158);
- colormap_.col ( 88) = Color (255, 215, 161);
- colormap_.col ( 89) = Color (255, 216, 163);
- colormap_.col ( 90) = Color (255, 218, 165);
- colormap_.col ( 91) = Color (255, 219, 168);
- colormap_.col ( 92) = Color (255, 220, 170);
- colormap_.col ( 93) = Color (255, 221, 172);
- colormap_.col ( 94) = Color (255, 223, 175);
- colormap_.col ( 95) = Color (255, 224, 177);
- colormap_.col ( 96) = Color (255, 225, 179);
- colormap_.col ( 97) = Color (255, 226, 182);
- colormap_.col ( 98) = Color (255, 227, 184);
- colormap_.col ( 99) = Color (255, 228, 186);
- colormap_.col (100) = Color (255, 230, 189);
- colormap_.col (101) = Color (255, 231, 191);
- colormap_.col (102) = Color (255, 232, 193);
- colormap_.col (103) = Color (255, 233, 196);
- colormap_.col (104) = Color (255, 234, 198);
- colormap_.col (105) = Color (255, 235, 201);
- colormap_.col (106) = Color (255, 236, 203);
- colormap_.col (107) = Color (255, 237, 205);
- colormap_.col (108) = Color (255, 238, 208);
- colormap_.col (109) = Color (255, 239, 210);
- colormap_.col (110) = Color (255, 240, 213);
- colormap_.col (111) = Color (255, 241, 215);
- colormap_.col (112) = Color (255, 242, 218);
- colormap_.col (113) = Color (255, 243, 220);
- colormap_.col (114) = Color (255, 244, 222);
- colormap_.col (115) = Color (255, 245, 225);
- colormap_.col (116) = Color (255, 246, 227);
- colormap_.col (117) = Color (255, 247, 230);
- colormap_.col (118) = Color (255, 248, 232);
- colormap_.col (119) = Color (255, 249, 235);
- colormap_.col (120) = Color (255, 249, 237);
- colormap_.col (121) = Color (255, 250, 239);
- colormap_.col (122) = Color (255, 251, 242);
- colormap_.col (123) = Color (255, 252, 244);
- colormap_.col (124) = Color (255, 253, 247);
- colormap_.col (125) = Color (255, 253, 249);
- colormap_.col (126) = Color (255, 254, 251);
- colormap_.col (127) = Color (255, 255, 254);
- colormap_.col (128) = Color (255, 255, 254);
- colormap_.col (129) = Color (254, 255, 253);
- colormap_.col (130) = Color (253, 255, 252);
- colormap_.col (131) = Color (252, 255, 250);
- colormap_.col (132) = Color (251, 255, 249);
- colormap_.col (133) = Color (250, 255, 248);
- colormap_.col (134) = Color (249, 255, 246);
- colormap_.col (135) = Color (248, 255, 245);
- colormap_.col (136) = Color (247, 255, 244);
- colormap_.col (137) = Color (246, 255, 242);
- colormap_.col (138) = Color (245, 255, 241);
- colormap_.col (139) = Color (244, 255, 240);
- colormap_.col (140) = Color (243, 255, 238);
- colormap_.col (141) = Color (242, 255, 237);
- colormap_.col (142) = Color (241, 255, 236);
- colormap_.col (143) = Color (240, 255, 235);
- colormap_.col (144) = Color (239, 255, 233);
- colormap_.col (145) = Color (238, 255, 232);
- colormap_.col (146) = Color (237, 255, 231);
- colormap_.col (147) = Color (236, 255, 229);
- colormap_.col (148) = Color (235, 255, 228);
- colormap_.col (149) = Color (234, 255, 227);
- colormap_.col (150) = Color (234, 255, 225);
- colormap_.col (151) = Color (233, 255, 224);
- colormap_.col (152) = Color (232, 255, 223);
- colormap_.col (153) = Color (231, 255, 221);
- colormap_.col (154) = Color (230, 255, 220);
- colormap_.col (155) = Color (229, 255, 219);
- colormap_.col (156) = Color (228, 255, 218);
- colormap_.col (157) = Color (227, 255, 216);
- colormap_.col (158) = Color (226, 255, 215);
- colormap_.col (159) = Color (225, 255, 214);
- colormap_.col (160) = Color (224, 255, 212);
- colormap_.col (161) = Color (223, 255, 211);
- colormap_.col (162) = Color (222, 255, 210);
- colormap_.col (163) = Color (221, 255, 208);
- colormap_.col (164) = Color (220, 255, 207);
- colormap_.col (165) = Color (219, 255, 206);
- colormap_.col (166) = Color (218, 255, 204);
- colormap_.col (167) = Color (217, 255, 203);
- colormap_.col (168) = Color (216, 255, 202);
- colormap_.col (169) = Color (215, 255, 201);
- colormap_.col (170) = Color (214, 255, 199);
- colormap_.col (171) = Color (213, 255, 198);
- colormap_.col (172) = Color (211, 255, 197);
- colormap_.col (173) = Color (210, 255, 195);
- colormap_.col (174) = Color (209, 255, 194);
- colormap_.col (175) = Color (208, 255, 193);
- colormap_.col (176) = Color (207, 255, 191);
- colormap_.col (177) = Color (206, 255, 190);
- colormap_.col (178) = Color (205, 255, 188);
- colormap_.col (179) = Color (204, 255, 187);
- colormap_.col (180) = Color (203, 255, 186);
- colormap_.col (181) = Color (202, 255, 184);
- colormap_.col (182) = Color (201, 255, 183);
- colormap_.col (183) = Color (199, 255, 182);
- colormap_.col (184) = Color (198, 255, 180);
- colormap_.col (185) = Color (197, 255, 179);
- colormap_.col (186) = Color (196, 255, 177);
- colormap_.col (187) = Color (195, 255, 176);
- colormap_.col (188) = Color (194, 255, 174);
- colormap_.col (189) = Color (192, 255, 173);
- colormap_.col (190) = Color (191, 255, 172);
- colormap_.col (191) = Color (190, 255, 170);
- colormap_.col (192) = Color (189, 255, 169);
- colormap_.col (193) = Color (188, 255, 167);
- colormap_.col (194) = Color (186, 255, 166);
- colormap_.col (195) = Color (185, 255, 164);
- colormap_.col (196) = Color (184, 255, 163);
- colormap_.col (197) = Color (183, 255, 161);
- colormap_.col (198) = Color (181, 255, 160);
- colormap_.col (199) = Color (180, 255, 158);
- colormap_.col (200) = Color (179, 255, 157);
- colormap_.col (201) = Color (177, 255, 155);
- colormap_.col (202) = Color (176, 255, 154);
- colormap_.col (203) = Color (175, 255, 152);
- colormap_.col (204) = Color (173, 255, 150);
- colormap_.col (205) = Color (172, 255, 149);
- colormap_.col (206) = Color (170, 255, 147);
- colormap_.col (207) = Color (169, 255, 145);
- colormap_.col (208) = Color (166, 253, 143);
- colormap_.col (209) = Color (164, 252, 141);
- colormap_.col (210) = Color (162, 251, 138);
- colormap_.col (211) = Color (159, 250, 136);
- colormap_.col (212) = Color (157, 248, 134);
- colormap_.col (213) = Color (155, 247, 131);
- colormap_.col (214) = Color (152, 246, 129);
- colormap_.col (215) = Color (150, 245, 127);
- colormap_.col (216) = Color (148, 243, 124);
- colormap_.col (217) = Color (145, 242, 122);
- colormap_.col (218) = Color (143, 240, 119);
- colormap_.col (219) = Color (140, 239, 117);
- colormap_.col (220) = Color (138, 238, 114);
- colormap_.col (221) = Color (135, 236, 112);
- colormap_.col (222) = Color (133, 235, 110);
- colormap_.col (223) = Color (130, 233, 107);
- colormap_.col (224) = Color (128, 232, 105);
- colormap_.col (225) = Color (125, 230, 102);
- colormap_.col (226) = Color (122, 229, 100);
- colormap_.col (227) = Color (120, 227, 97);
- colormap_.col (228) = Color (117, 226, 94);
- colormap_.col (229) = Color (114, 224, 92);
- colormap_.col (230) = Color (111, 223, 89);
- colormap_.col (231) = Color (109, 221, 87);
- colormap_.col (232) = Color (106, 220, 84);
- colormap_.col (233) = Color (103, 218, 82);
- colormap_.col (234) = Color (100, 217, 79);
- colormap_.col (235) = Color ( 97, 215, 76);
- colormap_.col (236) = Color ( 94, 213, 73);
- colormap_.col (237) = Color ( 91, 212, 71);
- colormap_.col (238) = Color ( 88, 210, 68);
- colormap_.col (239) = Color ( 85, 208, 65);
- colormap_.col (240) = Color ( 82, 207, 62);
- colormap_.col (241) = Color ( 78, 205, 59);
- colormap_.col (242) = Color ( 75, 203, 57);
- colormap_.col (243) = Color ( 71, 201, 54);
- colormap_.col (244) = Color ( 68, 200, 50);
- colormap_.col (245) = Color ( 64, 198, 47);
- colormap_.col (246) = Color ( 60, 196, 44);
- colormap_.col (247) = Color ( 56, 195, 41);
- colormap_.col (248) = Color ( 52, 193, 37);
- colormap_.col (249) = Color ( 47, 191, 33);
- colormap_.col (250) = Color ( 42, 189, 29);
- colormap_.col (251) = Color ( 37, 187, 25);
- colormap_.col (252) = Color ( 31, 186, 20);
- colormap_.col (253) = Color ( 24, 184, 15);
- colormap_.col (254) = Color ( 14, 182, 7);
- colormap_.col (255) = Color ( 0, 180, 0);
+ // int
+ // main()
+ // {
+ // static const unsigned int n = 256;
+ // // double rgb_1 [] = { 59./255., 76./255., 192./255.};
+ // // double rgb_2 [] = {180./255., 4./255., 38./255.};
+ // double rgb_1 [] = {180./255., 0./255., 0./255.};
+ // double rgb_2 [] = { 0./255., 180./255., 0./255.};
+ //
+ // vtkSmartPointer <vtkColorTransferFunction> ctf = vtkColorTransferFunction::New();
+ // ctf->SetColorSpaceToDiverging();
+ // ctf->AddRGBPoint(0., rgb_1 [0], rgb_1 [1], rgb_1 [2]);
+ // ctf->AddRGBPoint(1., rgb_2 [0], rgb_2 [1], rgb_2 [2]);
+ // ctf->Build();
+ //
+ // const unsigned char* colormap = ctf->GetTable (0., 1., n);
+ //
+ // for (unsigned int i=0; i<n; ++i)
+ // {
+ // const unsigned int r = static_cast <unsigned int> (colormap [3 * i ]);
+ // const unsigned int g = static_cast <unsigned int> (colormap [3 * i + 1]);
+ // const unsigned int b = static_cast <unsigned int> (colormap [3 * i + 2]);
+ //
+ // std::cerr << "colormap_.col ("
+ // << std::setw (3) << i << ") = Color ("
+ // << std::setw (3) << r << ", "
+ // << std::setw (3) << g << ", "
+ // << std::setw (3) << b << ");\n";
+ // }
+ //
+ // return (EXIT_SUCCESS);
+ // }
+
+ colormap_.col(0) = Color(180, 0, 0);
+ colormap_.col(1) = Color(182, 9, 1);
+ colormap_.col(2) = Color(184, 17, 1);
+ colormap_.col(3) = Color(186, 24, 2);
+ colormap_.col(4) = Color(188, 29, 2);
+ colormap_.col(5) = Color(190, 33, 3);
+ colormap_.col(6) = Color(192, 38, 4);
+ colormap_.col(7) = Color(194, 42, 5);
+ colormap_.col(8) = Color(196, 46, 6);
+ colormap_.col(9) = Color(197, 49, 7);
+ colormap_.col(10) = Color(199, 53, 9);
+ colormap_.col(11) = Color(201, 56, 10);
+ colormap_.col(12) = Color(203, 59, 12);
+ colormap_.col(13) = Color(205, 63, 13);
+ colormap_.col(14) = Color(207, 66, 15);
+ colormap_.col(15) = Color(208, 69, 17);
+ colormap_.col(16) = Color(210, 72, 18);
+ colormap_.col(17) = Color(212, 75, 20);
+ colormap_.col(18) = Color(214, 78, 21);
+ colormap_.col(19) = Color(215, 81, 23);
+ colormap_.col(20) = Color(217, 84, 25);
+ colormap_.col(21) = Color(219, 87, 26);
+ colormap_.col(22) = Color(221, 89, 28);
+ colormap_.col(23) = Color(222, 92, 30);
+ colormap_.col(24) = Color(224, 95, 32);
+ colormap_.col(25) = Color(225, 98, 33);
+ colormap_.col(26) = Color(227, 101, 35);
+ colormap_.col(27) = Color(229, 103, 37);
+ colormap_.col(28) = Color(230, 106, 39);
+ colormap_.col(29) = Color(232, 109, 40);
+ colormap_.col(30) = Color(233, 112, 42);
+ colormap_.col(31) = Color(235, 114, 44);
+ colormap_.col(32) = Color(236, 117, 46);
+ colormap_.col(33) = Color(238, 120, 48);
+ colormap_.col(34) = Color(239, 122, 50);
+ colormap_.col(35) = Color(241, 125, 52);
+ colormap_.col(36) = Color(242, 127, 54);
+ colormap_.col(37) = Color(244, 130, 56);
+ colormap_.col(38) = Color(245, 133, 58);
+ colormap_.col(39) = Color(246, 135, 60);
+ colormap_.col(40) = Color(248, 138, 62);
+ colormap_.col(41) = Color(249, 140, 64);
+ colormap_.col(42) = Color(250, 143, 66);
+ colormap_.col(43) = Color(252, 145, 68);
+ colormap_.col(44) = Color(253, 148, 70);
+ colormap_.col(45) = Color(254, 150, 73);
+ colormap_.col(46) = Color(255, 153, 75);
+ colormap_.col(47) = Color(255, 154, 76);
+ colormap_.col(48) = Color(255, 156, 78);
+ colormap_.col(49) = Color(255, 158, 80);
+ colormap_.col(50) = Color(255, 159, 82);
+ colormap_.col(51) = Color(255, 161, 84);
+ colormap_.col(52) = Color(255, 163, 86);
+ colormap_.col(53) = Color(255, 164, 88);
+ colormap_.col(54) = Color(255, 166, 90);
+ colormap_.col(55) = Color(255, 168, 92);
+ colormap_.col(56) = Color(255, 169, 93);
+ colormap_.col(57) = Color(255, 171, 95);
+ colormap_.col(58) = Color(255, 172, 97);
+ colormap_.col(59) = Color(255, 174, 99);
+ colormap_.col(60) = Color(255, 176, 101);
+ colormap_.col(61) = Color(255, 177, 103);
+ colormap_.col(62) = Color(255, 179, 105);
+ colormap_.col(63) = Color(255, 180, 107);
+ colormap_.col(64) = Color(255, 182, 109);
+ colormap_.col(65) = Color(255, 183, 111);
+ colormap_.col(66) = Color(255, 185, 113);
+ colormap_.col(67) = Color(255, 186, 115);
+ colormap_.col(68) = Color(255, 188, 117);
+ colormap_.col(69) = Color(255, 189, 119);
+ colormap_.col(70) = Color(255, 191, 122);
+ colormap_.col(71) = Color(255, 192, 124);
+ colormap_.col(72) = Color(255, 194, 126);
+ colormap_.col(73) = Color(255, 195, 128);
+ colormap_.col(74) = Color(255, 196, 130);
+ colormap_.col(75) = Color(255, 198, 132);
+ colormap_.col(76) = Color(255, 199, 134);
+ colormap_.col(77) = Color(255, 201, 136);
+ colormap_.col(78) = Color(255, 202, 139);
+ colormap_.col(79) = Color(255, 203, 141);
+ colormap_.col(80) = Color(255, 205, 143);
+ colormap_.col(81) = Color(255, 206, 145);
+ colormap_.col(82) = Color(255, 207, 147);
+ colormap_.col(83) = Color(255, 209, 149);
+ colormap_.col(84) = Color(255, 210, 152);
+ colormap_.col(85) = Color(255, 211, 154);
+ colormap_.col(86) = Color(255, 213, 156);
+ colormap_.col(87) = Color(255, 214, 158);
+ colormap_.col(88) = Color(255, 215, 161);
+ colormap_.col(89) = Color(255, 216, 163);
+ colormap_.col(90) = Color(255, 218, 165);
+ colormap_.col(91) = Color(255, 219, 168);
+ colormap_.col(92) = Color(255, 220, 170);
+ colormap_.col(93) = Color(255, 221, 172);
+ colormap_.col(94) = Color(255, 223, 175);
+ colormap_.col(95) = Color(255, 224, 177);
+ colormap_.col(96) = Color(255, 225, 179);
+ colormap_.col(97) = Color(255, 226, 182);
+ colormap_.col(98) = Color(255, 227, 184);
+ colormap_.col(99) = Color(255, 228, 186);
+ colormap_.col(100) = Color(255, 230, 189);
+ colormap_.col(101) = Color(255, 231, 191);
+ colormap_.col(102) = Color(255, 232, 193);
+ colormap_.col(103) = Color(255, 233, 196);
+ colormap_.col(104) = Color(255, 234, 198);
+ colormap_.col(105) = Color(255, 235, 201);
+ colormap_.col(106) = Color(255, 236, 203);
+ colormap_.col(107) = Color(255, 237, 205);
+ colormap_.col(108) = Color(255, 238, 208);
+ colormap_.col(109) = Color(255, 239, 210);
+ colormap_.col(110) = Color(255, 240, 213);
+ colormap_.col(111) = Color(255, 241, 215);
+ colormap_.col(112) = Color(255, 242, 218);
+ colormap_.col(113) = Color(255, 243, 220);
+ colormap_.col(114) = Color(255, 244, 222);
+ colormap_.col(115) = Color(255, 245, 225);
+ colormap_.col(116) = Color(255, 246, 227);
+ colormap_.col(117) = Color(255, 247, 230);
+ colormap_.col(118) = Color(255, 248, 232);
+ colormap_.col(119) = Color(255, 249, 235);
+ colormap_.col(120) = Color(255, 249, 237);
+ colormap_.col(121) = Color(255, 250, 239);
+ colormap_.col(122) = Color(255, 251, 242);
+ colormap_.col(123) = Color(255, 252, 244);
+ colormap_.col(124) = Color(255, 253, 247);
+ colormap_.col(125) = Color(255, 253, 249);
+ colormap_.col(126) = Color(255, 254, 251);
+ colormap_.col(127) = Color(255, 255, 254);
+ colormap_.col(128) = Color(255, 255, 254);
+ colormap_.col(129) = Color(254, 255, 253);
+ colormap_.col(130) = Color(253, 255, 252);
+ colormap_.col(131) = Color(252, 255, 250);
+ colormap_.col(132) = Color(251, 255, 249);
+ colormap_.col(133) = Color(250, 255, 248);
+ colormap_.col(134) = Color(249, 255, 246);
+ colormap_.col(135) = Color(248, 255, 245);
+ colormap_.col(136) = Color(247, 255, 244);
+ colormap_.col(137) = Color(246, 255, 242);
+ colormap_.col(138) = Color(245, 255, 241);
+ colormap_.col(139) = Color(244, 255, 240);
+ colormap_.col(140) = Color(243, 255, 238);
+ colormap_.col(141) = Color(242, 255, 237);
+ colormap_.col(142) = Color(241, 255, 236);
+ colormap_.col(143) = Color(240, 255, 235);
+ colormap_.col(144) = Color(239, 255, 233);
+ colormap_.col(145) = Color(238, 255, 232);
+ colormap_.col(146) = Color(237, 255, 231);
+ colormap_.col(147) = Color(236, 255, 229);
+ colormap_.col(148) = Color(235, 255, 228);
+ colormap_.col(149) = Color(234, 255, 227);
+ colormap_.col(150) = Color(234, 255, 225);
+ colormap_.col(151) = Color(233, 255, 224);
+ colormap_.col(152) = Color(232, 255, 223);
+ colormap_.col(153) = Color(231, 255, 221);
+ colormap_.col(154) = Color(230, 255, 220);
+ colormap_.col(155) = Color(229, 255, 219);
+ colormap_.col(156) = Color(228, 255, 218);
+ colormap_.col(157) = Color(227, 255, 216);
+ colormap_.col(158) = Color(226, 255, 215);
+ colormap_.col(159) = Color(225, 255, 214);
+ colormap_.col(160) = Color(224, 255, 212);
+ colormap_.col(161) = Color(223, 255, 211);
+ colormap_.col(162) = Color(222, 255, 210);
+ colormap_.col(163) = Color(221, 255, 208);
+ colormap_.col(164) = Color(220, 255, 207);
+ colormap_.col(165) = Color(219, 255, 206);
+ colormap_.col(166) = Color(218, 255, 204);
+ colormap_.col(167) = Color(217, 255, 203);
+ colormap_.col(168) = Color(216, 255, 202);
+ colormap_.col(169) = Color(215, 255, 201);
+ colormap_.col(170) = Color(214, 255, 199);
+ colormap_.col(171) = Color(213, 255, 198);
+ colormap_.col(172) = Color(211, 255, 197);
+ colormap_.col(173) = Color(210, 255, 195);
+ colormap_.col(174) = Color(209, 255, 194);
+ colormap_.col(175) = Color(208, 255, 193);
+ colormap_.col(176) = Color(207, 255, 191);
+ colormap_.col(177) = Color(206, 255, 190);
+ colormap_.col(178) = Color(205, 255, 188);
+ colormap_.col(179) = Color(204, 255, 187);
+ colormap_.col(180) = Color(203, 255, 186);
+ colormap_.col(181) = Color(202, 255, 184);
+ colormap_.col(182) = Color(201, 255, 183);
+ colormap_.col(183) = Color(199, 255, 182);
+ colormap_.col(184) = Color(198, 255, 180);
+ colormap_.col(185) = Color(197, 255, 179);
+ colormap_.col(186) = Color(196, 255, 177);
+ colormap_.col(187) = Color(195, 255, 176);
+ colormap_.col(188) = Color(194, 255, 174);
+ colormap_.col(189) = Color(192, 255, 173);
+ colormap_.col(190) = Color(191, 255, 172);
+ colormap_.col(191) = Color(190, 255, 170);
+ colormap_.col(192) = Color(189, 255, 169);
+ colormap_.col(193) = Color(188, 255, 167);
+ colormap_.col(194) = Color(186, 255, 166);
+ colormap_.col(195) = Color(185, 255, 164);
+ colormap_.col(196) = Color(184, 255, 163);
+ colormap_.col(197) = Color(183, 255, 161);
+ colormap_.col(198) = Color(181, 255, 160);
+ colormap_.col(199) = Color(180, 255, 158);
+ colormap_.col(200) = Color(179, 255, 157);
+ colormap_.col(201) = Color(177, 255, 155);
+ colormap_.col(202) = Color(176, 255, 154);
+ colormap_.col(203) = Color(175, 255, 152);
+ colormap_.col(204) = Color(173, 255, 150);
+ colormap_.col(205) = Color(172, 255, 149);
+ colormap_.col(206) = Color(170, 255, 147);
+ colormap_.col(207) = Color(169, 255, 145);
+ colormap_.col(208) = Color(166, 253, 143);
+ colormap_.col(209) = Color(164, 252, 141);
+ colormap_.col(210) = Color(162, 251, 138);
+ colormap_.col(211) = Color(159, 250, 136);
+ colormap_.col(212) = Color(157, 248, 134);
+ colormap_.col(213) = Color(155, 247, 131);
+ colormap_.col(214) = Color(152, 246, 129);
+ colormap_.col(215) = Color(150, 245, 127);
+ colormap_.col(216) = Color(148, 243, 124);
+ colormap_.col(217) = Color(145, 242, 122);
+ colormap_.col(218) = Color(143, 240, 119);
+ colormap_.col(219) = Color(140, 239, 117);
+ colormap_.col(220) = Color(138, 238, 114);
+ colormap_.col(221) = Color(135, 236, 112);
+ colormap_.col(222) = Color(133, 235, 110);
+ colormap_.col(223) = Color(130, 233, 107);
+ colormap_.col(224) = Color(128, 232, 105);
+ colormap_.col(225) = Color(125, 230, 102);
+ colormap_.col(226) = Color(122, 229, 100);
+ colormap_.col(227) = Color(120, 227, 97);
+ colormap_.col(228) = Color(117, 226, 94);
+ colormap_.col(229) = Color(114, 224, 92);
+ colormap_.col(230) = Color(111, 223, 89);
+ colormap_.col(231) = Color(109, 221, 87);
+ colormap_.col(232) = Color(106, 220, 84);
+ colormap_.col(233) = Color(103, 218, 82);
+ colormap_.col(234) = Color(100, 217, 79);
+ colormap_.col(235) = Color(97, 215, 76);
+ colormap_.col(236) = Color(94, 213, 73);
+ colormap_.col(237) = Color(91, 212, 71);
+ colormap_.col(238) = Color(88, 210, 68);
+ colormap_.col(239) = Color(85, 208, 65);
+ colormap_.col(240) = Color(82, 207, 62);
+ colormap_.col(241) = Color(78, 205, 59);
+ colormap_.col(242) = Color(75, 203, 57);
+ colormap_.col(243) = Color(71, 201, 54);
+ colormap_.col(244) = Color(68, 200, 50);
+ colormap_.col(245) = Color(64, 198, 47);
+ colormap_.col(246) = Color(60, 196, 44);
+ colormap_.col(247) = Color(56, 195, 41);
+ colormap_.col(248) = Color(52, 193, 37);
+ colormap_.col(249) = Color(47, 191, 33);
+ colormap_.col(250) = Color(42, 189, 29);
+ colormap_.col(251) = Color(37, 187, 25);
+ colormap_.col(252) = Color(31, 186, 20);
+ colormap_.col(253) = Color(24, 184, 15);
+ colormap_.col(254) = Color(14, 182, 7);
+ colormap_.col(255) = Color(0, 180, 0);
}
////////////////////////////////////////////////////////////////////////////////
-pcl::ihs::OpenGLViewer::~OpenGLViewer ()
-{
- this->stopTimer ();
-}
+pcl::ihs::OpenGLViewer::~OpenGLViewer() { this->stopTimer(); }
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::OpenGLViewer::addMesh (const MeshConstPtr& mesh, const std::string& id, const Eigen::Isometry3d& T)
+pcl::ihs::OpenGLViewer::addMesh(const MeshConstPtr& mesh,
+ const std::string& id,
+ const Eigen::Isometry3d& T)
{
- if (!mesh)
- {
+ if (!mesh) {
std::cerr << "ERROR in opengl_viewer.cpp: Input mesh is not valid.\n";
return (false);
}
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
- if (this->getMeshIsAdded (id))
- drawn_meshes_ [id] = FaceVertexMeshPtr (new FaceVertexMesh (*mesh, T));
+ if (this->getMeshIsAdded(id))
+ drawn_meshes_[id] = FaceVertexMeshPtr(new FaceVertexMesh(*mesh, T));
else
- drawn_meshes_.insert (std::make_pair (id, FaceVertexMeshPtr (new FaceVertexMesh (*mesh, T))));
+ drawn_meshes_.insert(
+ std::make_pair(id, FaceVertexMeshPtr(new FaceVertexMesh(*mesh, T))));
return (true);
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::OpenGLViewer::addMesh (const CloudXYZRGBNormalConstPtr& cloud, const std::string& id, const Eigen::Isometry3d& T)
+pcl::ihs::OpenGLViewer::addMesh(const CloudXYZRGBNormalConstPtr& cloud,
+ const std::string& id,
+ const Eigen::Isometry3d& T)
{
- if (!cloud)
- {
+ if (!cloud) {
std::cerr << "ERROR in opengl_viewer.cpp: Input cloud is not valid.\n";
return (false);
}
- if (!cloud->isOrganized ())
- {
+ if (!cloud->isOrganized()) {
std::cerr << "ERROR in opengl_viewer.cpp: Input cloud is not organized.\n";
return (false);
}
// 2 - 1 //
// | / | //
// 3 - 0 //
- const int w = cloud->width;
- const int h = cloud->height;
+ const int w = cloud->width;
+ const int h = cloud->height;
const int offset_1 = -w;
const int offset_2 = -w - 1;
- const int offset_3 = - 1;
+ const int offset_3 = -1;
- FaceVertexMeshPtr mesh (new FaceVertexMesh ());
+ FaceVertexMeshPtr mesh(new FaceVertexMesh());
mesh->transformation = T;
- std::vector <int> indices (w * h, -1); // Map the original indices to the vertex indices.
+ std::vector<int> indices(w * h,
+ -1); // Map the original indices to the vertex indices.
CloudIHS& vertices = mesh->vertices;
- std::vector <FaceVertexMesh::Triangle>& triangles = mesh->triangles;
- vertices.reserve (cloud->size ());
- triangles.reserve (2 * (w-1) * (h-1));
+ std::vector<FaceVertexMesh::Triangle>& triangles = mesh->triangles;
+ vertices.reserve(cloud->size());
+ triangles.reserve(2 * (w - 1) * (h - 1));
// Helper functor
- struct AddVertex
- {
- inline int operator () (const PointXYZRGBNormal& pt, CloudIHS& vertices, int& ind_o) const
+ struct AddVertex {
+ inline int
+ operator()(const PointXYZRGBNormal& pt, CloudIHS& vertices, int& ind_o) const
{
- if (ind_o == -1)
- {
- ind_o = vertices.size ();
- vertices.push_back (PointIHS (pt, -pt.normal_z));
- std::swap (vertices.back ().r, vertices.back ().b);
+ if (ind_o == -1) {
+ ind_o = vertices.size();
+ vertices.push_back(PointIHS(pt, -pt.normal_z));
+ std::swap(vertices.back().r, vertices.back().b);
}
return (ind_o);
}
int ind_o_0, ind_o_1, ind_o_2, ind_o_3; // Index into the organized cloud.
int ind_v_0, ind_v_1, ind_v_2, ind_v_3; // Index to the new vertices.
- for (int r=1; r<h; ++r)
- {
- for (int c=1; c<w; ++c)
- {
- ind_o_0 = r*w + c;
+ for (int r = 1; r < h; ++r) {
+ for (int c = 1; c < w; ++c) {
+ ind_o_0 = r * w + c;
ind_o_1 = ind_o_0 + offset_1;
ind_o_2 = ind_o_0 + offset_2;
ind_o_3 = ind_o_0 + offset_3;
- const PointXYZRGBNormal& pt_0 = cloud->operator [] (ind_o_0);
- const PointXYZRGBNormal& pt_1 = cloud->operator [] (ind_o_1);
- const PointXYZRGBNormal& pt_2 = cloud->operator [] (ind_o_2);
- const PointXYZRGBNormal& pt_3 = cloud->operator [] (ind_o_3);
+ const PointXYZRGBNormal& pt_0 = cloud->operator[](ind_o_0);
+ const PointXYZRGBNormal& pt_1 = cloud->operator[](ind_o_1);
+ const PointXYZRGBNormal& pt_2 = cloud->operator[](ind_o_2);
+ const PointXYZRGBNormal& pt_3 = cloud->operator[](ind_o_3);
- if (!std::isnan (pt_1.x) && !std::isnan (pt_3.x))
- {
- if (!std::isnan (pt_2.x)) // 1-2-3 is valid
+ if (!std::isnan(pt_1.x) && !std::isnan(pt_3.x)) {
+ if (!std::isnan(pt_2.x)) // 1-2-3 is valid
{
- if (std::abs (pt_1.z - pt_2.z) < 1 &&
- std::abs (pt_1.z - pt_3.z) < 1 &&
- std::abs (pt_2.z - pt_3.z) < 1) // distance threshold
+ if (std::abs(pt_1.z - pt_2.z) < 1 && std::abs(pt_1.z - pt_3.z) < 1 &&
+ std::abs(pt_2.z - pt_3.z) < 1) // distance threshold
{
- ind_v_1 = addVertex (pt_1, vertices, indices [ind_o_1]);
- ind_v_2 = addVertex (pt_2, vertices, indices [ind_o_2]);
- ind_v_3 = addVertex (pt_3, vertices, indices [ind_o_3]);
+ ind_v_1 = addVertex(pt_1, vertices, indices[ind_o_1]);
+ ind_v_2 = addVertex(pt_2, vertices, indices[ind_o_2]);
+ ind_v_3 = addVertex(pt_3, vertices, indices[ind_o_3]);
triangles.emplace_back(ind_v_1, ind_v_2, ind_v_3);
}
}
- if (!std::isnan (pt_0.x)) // 0-1-3 is valid
+ if (!std::isnan(pt_0.x)) // 0-1-3 is valid
{
- if (std::abs (pt_0.z - pt_1.z) < 1 &&
- std::abs (pt_0.z - pt_3.z) < 1 &&
- std::abs (pt_1.z - pt_3.z) < 1) // distance threshold
+ if (std::abs(pt_0.z - pt_1.z) < 1 && std::abs(pt_0.z - pt_3.z) < 1 &&
+ std::abs(pt_1.z - pt_3.z) < 1) // distance threshold
{
- ind_v_1 = addVertex (pt_1, vertices, indices [ind_o_1]);
- ind_v_3 = addVertex (pt_3, vertices, indices [ind_o_3]);
- ind_v_0 = addVertex (pt_0, vertices, indices [ind_o_0]);
+ ind_v_1 = addVertex(pt_1, vertices, indices[ind_o_1]);
+ ind_v_3 = addVertex(pt_3, vertices, indices[ind_o_3]);
+ ind_v_0 = addVertex(pt_0, vertices, indices[ind_o_0]);
triangles.emplace_back(ind_v_1, ind_v_3, ind_v_0);
}
}
// Finally add the mesh.
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
- if (this->getMeshIsAdded (id))
- drawn_meshes_ [id] = mesh;
+ if (this->getMeshIsAdded(id))
+ drawn_meshes_[id] = mesh;
else
- drawn_meshes_.insert (std::make_pair (id, mesh));
+ drawn_meshes_.insert(std::make_pair(id, mesh));
return (true);
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::OpenGLViewer::removeMesh (const std::string& id)
+pcl::ihs::OpenGLViewer::removeMesh(const std::string& id)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
- if (!this->getMeshIsAdded (id)) return (false);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
+ if (!this->getMeshIsAdded(id))
+ return (false);
- drawn_meshes_.erase (id);
+ drawn_meshes_.erase(id);
return (true);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::removeAllMeshes ()
+pcl::ihs::OpenGLViewer::removeAllMeshes()
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
- drawn_meshes_.clear ();
+ std::lock_guard<std::mutex> lock(mutex_vis_);
+ drawn_meshes_.clear();
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setBoxCoefficients (const BoxCoefficients& coeffs)
+pcl::ihs::OpenGLViewer::setBoxCoefficients(const BoxCoefficients& coeffs)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
box_coefficients_ = coeffs;
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setDrawBox (const bool enabled)
+pcl::ihs::OpenGLViewer::setDrawBox(const bool enabled)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
draw_box_ = enabled;
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::OpenGLViewer::getDrawBox () const
+pcl::ihs::OpenGLViewer::getDrawBox() const
{
return (draw_box_);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setPivot (const Eigen::Vector3d& pivot)
+pcl::ihs::OpenGLViewer::setPivot(const Eigen::Vector3d& pivot)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
cam_pivot_ = pivot;
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setPivot (const std::string& id)
+pcl::ihs::OpenGLViewer::setPivot(const std::string& id)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
cam_pivot_id_ = id;
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::stopTimer ()
+pcl::ihs::OpenGLViewer::stopTimer()
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
- if (timer_vis_)
- {
- timer_vis_->stop ();
+ std::lock_guard<std::mutex> lock(mutex_vis_);
+ if (timer_vis_) {
+ timer_vis_->stop();
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setVisibilityConfidenceNormalization (const float vis_conf_norm)
+pcl::ihs::OpenGLViewer::setVisibilityConfidenceNormalization(const float vis_conf_norm)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
vis_conf_norm_ = vis_conf_norm < 1 ? 1 : vis_conf_norm;
}
////////////////////////////////////////////////////////////////////////////////
QSize
-pcl::ihs::OpenGLViewer::minimumSizeHint () const
+pcl::ihs::OpenGLViewer::minimumSizeHint() const
{
- return (QSize (160, 120));
+ return (QSize(160, 120));
}
////////////////////////////////////////////////////////////////////////////////
QSize
-pcl::ihs::OpenGLViewer::sizeHint () const
+pcl::ihs::OpenGLViewer::sizeHint() const
{
- return (QSize (640, 480));
+ return (QSize(640, 480));
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setScalingFactor (const double scale)
+pcl::ihs::OpenGLViewer::setScalingFactor(const double scale)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
scaling_factor_ = scale;
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::timerCallback ()
+pcl::ihs::OpenGLViewer::timerCallback()
{
- QWidget::update ();
+ QWidget::update();
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::resetCamera ()
+pcl::ihs::OpenGLViewer::resetCamera()
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
- R_cam_ = Eigen::Quaterniond (1., 0., 0., 0.);
- t_cam_ = Eigen::Vector3d (0., 0., 0.);
+ R_cam_ = Eigen::Quaterniond(1., 0., 0., 0.);
+ t_cam_ = Eigen::Vector3d(0., 0., 0.);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::toggleMeshRepresentation ()
+pcl::ihs::OpenGLViewer::toggleMeshRepresentation()
{
- switch (mesh_representation_)
- {
- case MR_POINTS: this->setMeshRepresentation (MR_EDGES); break;
- case MR_EDGES: this->setMeshRepresentation (MR_FACES); break;
- case MR_FACES: this->setMeshRepresentation (MR_POINTS); break;
- default: std::cerr << "ERROR in opengl_viewer.cpp: Unknown mesh representation\n"; exit (EXIT_FAILURE);
+ switch (mesh_representation_) {
+ case MR_POINTS:
+ this->setMeshRepresentation(MR_EDGES);
+ break;
+ case MR_EDGES:
+ this->setMeshRepresentation(MR_FACES);
+ break;
+ case MR_FACES:
+ this->setMeshRepresentation(MR_POINTS);
+ break;
+ default:
+ std::cerr << "ERROR in opengl_viewer.cpp: Unknown mesh representation\n";
+ exit(EXIT_FAILURE);
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setMeshRepresentation (const MeshRepresentation& representation)
+pcl::ihs::OpenGLViewer::setMeshRepresentation(const MeshRepresentation& representation)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
-
- switch (mesh_representation_)
- {
- case MR_POINTS: std::cerr << "Drawing the points.\n"; break;
- case MR_EDGES: std::cerr << "Drawing the edges.\n"; break;
- case MR_FACES: std::cerr << "Drawing the faces.\n"; break;
- default: std::cerr << "ERROR in opengl_viewer.cpp: Unknown mesh representation\n"; exit (EXIT_FAILURE);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
+
+ switch (mesh_representation_) {
+ case MR_POINTS:
+ std::cerr << "Drawing the points.\n";
+ break;
+ case MR_EDGES:
+ std::cerr << "Drawing the edges.\n";
+ break;
+ case MR_FACES:
+ std::cerr << "Drawing the faces.\n";
+ break;
+ default:
+ std::cerr << "ERROR in opengl_viewer.cpp: Unknown mesh representation\n";
+ exit(EXIT_FAILURE);
}
mesh_representation_ = representation;
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::toggleColoring ()
+pcl::ihs::OpenGLViewer::toggleColoring()
{
- switch (coloring_)
- {
- case COL_RGB: this->setColoring (COL_ONE_COLOR); break;
- case COL_ONE_COLOR: this->setColoring (COL_VISCONF); break;
- case COL_VISCONF: this->setColoring (COL_RGB); break;
- default: std::cerr << "ERROR in opengl_viewer.cpp: Unknown coloring\n"; exit (EXIT_FAILURE);
+ switch (coloring_) {
+ case COL_RGB:
+ this->setColoring(COL_ONE_COLOR);
+ break;
+ case COL_ONE_COLOR:
+ this->setColoring(COL_VISCONF);
+ break;
+ case COL_VISCONF:
+ this->setColoring(COL_RGB);
+ break;
+ default:
+ std::cerr << "ERROR in opengl_viewer.cpp: Unknown coloring\n";
+ exit(EXIT_FAILURE);
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setColoring (const Coloring& coloring)
+pcl::ihs::OpenGLViewer::setColoring(const Coloring& coloring)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
-
- switch (coloring)
- {
- case COL_RGB: std::cerr << "Coloring according to the rgb values.\n"; break;
- case COL_ONE_COLOR: std::cerr << "Use one color for all points.\n"; break;
- case COL_VISCONF: std::cerr << "Coloring according to the visibility confidence.\n"; break;
- default: std::cerr << "ERROR in opengl_viewer.cpp: Unknown coloring\n"; exit (EXIT_FAILURE);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
+
+ switch (coloring) {
+ case COL_RGB:
+ std::cerr << "Coloring according to the rgb values.\n";
+ break;
+ case COL_ONE_COLOR:
+ std::cerr << "Use one color for all points.\n";
+ break;
+ case COL_VISCONF:
+ std::cerr << "Coloring according to the visibility confidence.\n";
+ break;
+ default:
+ std::cerr << "ERROR in opengl_viewer.cpp: Unknown coloring\n";
+ exit(EXIT_FAILURE);
}
coloring_ = coloring;
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::paintEvent (QPaintEvent* /*event*/)
+pcl::ihs::OpenGLViewer::paintEvent(QPaintEvent* /*event*/)
{
- this->calcPivot ();
- this->makeCurrent ();
+ this->calcPivot();
+ this->makeCurrent();
// Clear information from the last draw
- glClearColor (0.f, 0.f, 0.f, 0.f);
- glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glClearColor(0.f, 0.f, 0.f, 0.f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- this->setupViewport (this->width (), this->height ());
+ this->setupViewport(this->width(), this->height());
// Move light with camera (see example 5-7)
// http://www.glprogramming.com/red/chapter05.html
glLoadIdentity();
// light 0 (directional)
- glLightfv (GL_LIGHT0, GL_AMBIENT , Eigen::Vector4f (0.1f, 0.1f, 0.1f, 1.0f).eval ().data ());
- glLightfv (GL_LIGHT0, GL_DIFFUSE , Eigen::Vector4f (0.6f, 0.6f, 0.6f, 1.0f).eval ().data () );
- glLightfv (GL_LIGHT0, GL_SPECULAR, Eigen::Vector4f (0.2f, 0.2f, 0.2f, 1.0f).eval ().data ());
- glLightfv (GL_LIGHT0, GL_POSITION, Eigen::Vector4f (0.3f, 0.5f, 0.8f, 0.0f).normalized ().eval ().data ());
+ glLightfv(
+ GL_LIGHT0, GL_AMBIENT, Eigen::Vector4f(0.1f, 0.1f, 0.1f, 1.0f).eval().data());
+ glLightfv(
+ GL_LIGHT0, GL_DIFFUSE, Eigen::Vector4f(0.6f, 0.6f, 0.6f, 1.0f).eval().data());
+ glLightfv(
+ GL_LIGHT0, GL_SPECULAR, Eigen::Vector4f(0.2f, 0.2f, 0.2f, 1.0f).eval().data());
+ glLightfv(GL_LIGHT0,
+ GL_POSITION,
+ Eigen::Vector4f(0.3f, 0.5f, 0.8f, 0.0f).normalized().eval().data());
// light 1 (directional)
- glLightfv (GL_LIGHT1, GL_AMBIENT , Eigen::Vector4f ( 0.0f, 0.0f, 0.0f, 1.0f).eval ().data ());
- glLightfv (GL_LIGHT1, GL_DIFFUSE , Eigen::Vector4f ( 0.3f, 0.3f, 0.3f, 1.0f).eval ().data () );
- glLightfv (GL_LIGHT1, GL_SPECULAR, Eigen::Vector4f ( 0.1f, 0.1f, 0.1f, 1.0f).eval ().data ());
- glLightfv (GL_LIGHT1, GL_POSITION, Eigen::Vector4f (-0.3f, 0.5f, 0.8f, 0.0f).normalized ().eval ().data ());
+ glLightfv(
+ GL_LIGHT1, GL_AMBIENT, Eigen::Vector4f(0.0f, 0.0f, 0.0f, 1.0f).eval().data());
+ glLightfv(
+ GL_LIGHT1, GL_DIFFUSE, Eigen::Vector4f(0.3f, 0.3f, 0.3f, 1.0f).eval().data());
+ glLightfv(
+ GL_LIGHT1, GL_SPECULAR, Eigen::Vector4f(0.1f, 0.1f, 0.1f, 1.0f).eval().data());
+ glLightfv(GL_LIGHT1,
+ GL_POSITION,
+ Eigen::Vector4f(-0.3f, 0.5f, 0.8f, 0.0f).normalized().eval().data());
// Material
- glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
- glMaterialfv (GL_FRONT, GL_SPECULAR , Eigen::Vector4f (0.1f, 0.1f, 0.1f, 1.0f).eval ().data ());
- glMaterialf (GL_FRONT, GL_SHININESS, 25.f);
-
- glEnable (GL_DEPTH_TEST);
- glEnable (GL_NORMALIZE);
- glEnable (GL_COLOR_MATERIAL);
- glEnable (GL_LIGHTING);
- glEnable (GL_LIGHT0);
- glEnable (GL_LIGHT1);
+ glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
+ glMaterialfv(
+ GL_FRONT, GL_SPECULAR, Eigen::Vector4f(0.1f, 0.1f, 0.1f, 1.0f).eval().data());
+ glMaterialf(GL_FRONT, GL_SHININESS, 25.f);
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_NORMALIZE);
+ glEnable(GL_COLOR_MATERIAL);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
// Projection matrix
- glMatrixMode (GL_PROJECTION);
- glLoadIdentity ();
- gluPerspective (43., 4./3., 0.01 / scaling_factor_, 10. / scaling_factor_);
- glMatrixMode (GL_MODELVIEW);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(43., 4. / 3., 0.01 / scaling_factor_, 10. / scaling_factor_);
+ glMatrixMode(GL_MODELVIEW);
// ModelView matrix
Eigen::Quaterniond R_cam;
- Eigen::Vector3d t_cam;
+ Eigen::Vector3d t_cam;
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
R_cam = R_cam_;
t_cam = t_cam_;
}
- const Eigen::Vector3d o = Eigen::Vector3d::Zero ();
- const Eigen::Vector3d ey = Eigen::Vector3d::UnitY ();
- const Eigen::Vector3d ez = Eigen::Vector3d::UnitZ ();
+ const Eigen::Vector3d o = Eigen::Vector3d::Zero();
+ const Eigen::Vector3d ey = Eigen::Vector3d::UnitY();
+ const Eigen::Vector3d ez = Eigen::Vector3d::UnitZ();
- const Eigen::Vector3d eye = R_cam * o + t_cam;
- const Eigen::Vector3d center = R_cam * ez + t_cam;
- const Eigen::Vector3d up = (R_cam * -ey).normalized ();
+ const Eigen::Vector3d eye = R_cam * o + t_cam;
+ const Eigen::Vector3d center = R_cam * ez + t_cam;
+ const Eigen::Vector3d up = (R_cam * -ey).normalized();
- glMatrixMode (GL_MODELVIEW);
- gluLookAt (eye. x (), eye. y (), eye. z (),
- center.x (), center.y (), center.z (),
- up. x (), up. y (), up. z ());
+ glMatrixMode(GL_MODELVIEW);
+ gluLookAt(eye.x(),
+ eye.y(),
+ eye.z(),
+ center.x(),
+ center.y(),
+ center.z(),
+ up.x(),
+ up.y(),
+ up.z());
// Draw everything
- this->drawMeshes ();
+ this->drawMeshes();
- glDisable (GL_LIGHTING); // This is needed so the color is right.
- this->drawBox ();
+ glDisable(GL_LIGHTING); // This is needed so the color is right.
+ this->drawBox();
}
////////////////////////////////////////////////////////////////////////////////
bool
-pcl::ihs::OpenGLViewer::getMeshIsAdded (const std::string& id)
+pcl::ihs::OpenGLViewer::getMeshIsAdded(const std::string& id)
{
// std::lock_guard<std::mutex> lock (mutex_vis_);
- return (drawn_meshes_.find (id) != drawn_meshes_.end ());
+ return (drawn_meshes_.find(id) != drawn_meshes_.end());
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::calcPivot ()
+pcl::ihs::OpenGLViewer::calcPivot()
{
- std::unique_lock<std::mutex> lock (mutex_vis_);
- if (this->getMeshIsAdded (cam_pivot_id_))
- {
+ std::unique_lock<std::mutex> lock(mutex_vis_);
+ if (this->getMeshIsAdded(cam_pivot_id_)) {
Eigen::Vector4f pivot;
- const FaceVertexMeshConstPtr mesh = drawn_meshes_ [cam_pivot_id_];
+ const FaceVertexMeshConstPtr mesh = drawn_meshes_[cam_pivot_id_];
- if (pcl::compute3DCentroid (mesh->vertices, pivot))
- {
- const Eigen::Vector3d p = mesh->transformation * pivot.head <3> ().cast <double> ();
- lock.unlock ();
- this->setPivot (p);
+ if (pcl::compute3DCentroid(mesh->vertices, pivot)) {
+ const Eigen::Vector3d p = mesh->transformation * pivot.head<3>().cast<double>();
+ lock.unlock();
+ this->setPivot(p);
}
}
- cam_pivot_id_.clear ();
+ cam_pivot_id_.clear();
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::drawMeshes ()
+pcl::ihs::OpenGLViewer::drawMeshes()
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
-
- glEnableClientState (GL_VERTEX_ARRAY);
- glEnableClientState (GL_NORMAL_ARRAY);
- switch (coloring_)
- {
- case COL_RGB: glEnableClientState (GL_COLOR_ARRAY); break;
- case COL_ONE_COLOR: glDisableClientState (GL_COLOR_ARRAY); break;
- case COL_VISCONF: glEnableClientState (GL_COLOR_ARRAY); break;
- default: std::cerr << "ERROR in opengl_viewer.cpp: Unknown coloring\n"; exit (EXIT_FAILURE);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ switch (coloring_) {
+ case COL_RGB:
+ glEnableClientState(GL_COLOR_ARRAY);
+ break;
+ case COL_ONE_COLOR:
+ glDisableClientState(GL_COLOR_ARRAY);
+ break;
+ case COL_VISCONF:
+ glEnableClientState(GL_COLOR_ARRAY);
+ break;
+ default:
+ std::cerr << "ERROR in opengl_viewer.cpp: Unknown coloring\n";
+ exit(EXIT_FAILURE);
}
- switch (mesh_representation_)
- {
- case MR_POINTS: break;
- case MR_EDGES: glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); break;
- case MR_FACES: glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); break;
- default: std::cerr << "ERROR in opengl_viewer.cpp: Unknown mesh representation\n"; exit (EXIT_FAILURE);
+ switch (mesh_representation_) {
+ case MR_POINTS:
+ break;
+ case MR_EDGES:
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ break;
+ case MR_FACES:
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ break;
+ default:
+ std::cerr << "ERROR in opengl_viewer.cpp: Unknown mesh representation\n";
+ exit(EXIT_FAILURE);
}
- for (FaceVertexMeshMap::const_iterator it=drawn_meshes_.begin (); it!=drawn_meshes_.end (); ++it)
- {
- if (it->second && !it->second->vertices.empty ())
- {
- const FaceVertexMesh& mesh = *it->second;
+ for (const auto& drawn_mesh : drawn_meshes_) {
+ if (drawn_mesh.second && !drawn_mesh.second->vertices.empty()) {
+ const FaceVertexMesh& mesh = *drawn_mesh.second;
- glVertexPointer (3, GL_FLOAT, sizeof (PointIHS), &(mesh.vertices [0].x ));
- glNormalPointer ( GL_FLOAT, sizeof (PointIHS), &(mesh.vertices [0].normal_x));
+ glVertexPointer(3, GL_FLOAT, sizeof(PointIHS), &(mesh.vertices[0].x));
+ glNormalPointer(GL_FLOAT, sizeof(PointIHS), &(mesh.vertices[0].normal_x));
- Colors colors (3, mesh.vertices.size ());
+ Colors colors(3, mesh.vertices.size());
- switch (coloring_)
- {
- case COL_RGB:
- {
- glColorPointer (3, GL_UNSIGNED_BYTE, sizeof (PointIHS), &(mesh.vertices [0].b));
- break;
- }
- case COL_ONE_COLOR:
- {
- glColor3f (.7f, .7f, .7f);
- break;
+ switch (coloring_) {
+ case COL_RGB: {
+ glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(PointIHS), &(mesh.vertices[0].b));
+ break;
+ }
+ case COL_ONE_COLOR: {
+ glColor3f(.7f, .7f, .7f);
+ break;
+ }
+ case COL_VISCONF: {
+ for (std::size_t i = 0; i < mesh.vertices.size(); ++i) {
+ const unsigned int n = pcl::ihs::countDirections(mesh.vertices[i].directions);
+ const unsigned int index =
+ static_cast<unsigned int>(static_cast<float>(colormap_.cols()) *
+ static_cast<float>(n) / vis_conf_norm_);
+
+ colors.col(i) = colormap_.col(index < 256 ? index : 255);
}
- case COL_VISCONF:
- {
- for (std::size_t i=0; i<mesh.vertices.size (); ++i)
- {
- const unsigned int n = pcl::ihs::countDirections (mesh.vertices [i].directions);
- const unsigned int index = static_cast <unsigned int> (
- static_cast <float> (colormap_.cols ()) *
- static_cast <float> (n) / vis_conf_norm_);
-
- colors.col (i) = colormap_.col (index < 256 ? index : 255);
- }
- glColorPointer (3, GL_UNSIGNED_BYTE, 0, colors.data ());
- }
+ glColorPointer(3, GL_UNSIGNED_BYTE, 0, colors.data());
+ }
}
- glPushMatrix ();
+ glPushMatrix();
{
- glMultMatrixd (mesh.transformation.matrix ().data ());
+ glMultMatrixd(mesh.transformation.matrix().data());
- switch (mesh_representation_)
- {
- case MR_POINTS:
- {
- glDrawArrays (GL_POINTS, 0, mesh.vertices.size ());
- break;
- }
- case MR_EDGES: case MR_FACES:
- {
- glDrawElements (GL_TRIANGLES, 3*mesh.triangles.size (), GL_UNSIGNED_INT, &mesh.triangles [0]);
- break;
- }
+ switch (mesh_representation_) {
+ case MR_POINTS: {
+ glDrawArrays(GL_POINTS, 0, mesh.vertices.size());
+ break;
+ }
+ case MR_EDGES:
+ case MR_FACES: {
+ glDrawElements(GL_TRIANGLES,
+ 3 * mesh.triangles.size(),
+ GL_UNSIGNED_INT,
+ &mesh.triangles[0]);
+ break;
+ }
}
}
- glPopMatrix ();
+ glPopMatrix();
}
}
- glDisableClientState (GL_VERTEX_ARRAY);
- glDisableClientState (GL_NORMAL_ARRAY);
- glDisableClientState (GL_COLOR_ARRAY);
- glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::drawBox ()
+pcl::ihs::OpenGLViewer::drawBox()
{
BoxCoefficients coeffs;
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
- if (draw_box_) coeffs = box_coefficients_;
- else return;
+ std::lock_guard<std::mutex> lock(mutex_vis_);
+ if (draw_box_)
+ coeffs = box_coefficients_;
+ else
+ return;
}
- glColor3f (1.f, 1.f, 1.f);
+ glColor3f(1.f, 1.f, 1.f);
- glPushMatrix ();
+ glPushMatrix();
{
- glMultMatrixd (coeffs.transformation.matrix ().data ());
+ glMultMatrixd(coeffs.transformation.matrix().data());
// Front
glBegin(GL_LINE_STRIP);
{
- glVertex3f (coeffs.x_min, coeffs.y_min, coeffs.z_min);
- glVertex3f (coeffs.x_max, coeffs.y_min, coeffs.z_min);
- glVertex3f (coeffs.x_max, coeffs.y_max, coeffs.z_min);
- glVertex3f (coeffs.x_min, coeffs.y_max, coeffs.z_min);
- glVertex3f (coeffs.x_min, coeffs.y_min, coeffs.z_min);
+ glVertex3f(coeffs.x_min, coeffs.y_min, coeffs.z_min);
+ glVertex3f(coeffs.x_max, coeffs.y_min, coeffs.z_min);
+ glVertex3f(coeffs.x_max, coeffs.y_max, coeffs.z_min);
+ glVertex3f(coeffs.x_min, coeffs.y_max, coeffs.z_min);
+ glVertex3f(coeffs.x_min, coeffs.y_min, coeffs.z_min);
}
glEnd();
// Back
- glBegin (GL_LINE_STRIP);
+ glBegin(GL_LINE_STRIP);
{
- glVertex3f (coeffs.x_min, coeffs.y_min, coeffs.z_max);
- glVertex3f (coeffs.x_max, coeffs.y_min, coeffs.z_max);
- glVertex3f (coeffs.x_max, coeffs.y_max, coeffs.z_max);
- glVertex3f (coeffs.x_min, coeffs.y_max, coeffs.z_max);
- glVertex3f (coeffs.x_min, coeffs.y_min, coeffs.z_max);
+ glVertex3f(coeffs.x_min, coeffs.y_min, coeffs.z_max);
+ glVertex3f(coeffs.x_max, coeffs.y_min, coeffs.z_max);
+ glVertex3f(coeffs.x_max, coeffs.y_max, coeffs.z_max);
+ glVertex3f(coeffs.x_min, coeffs.y_max, coeffs.z_max);
+ glVertex3f(coeffs.x_min, coeffs.y_min, coeffs.z_max);
}
glEnd();
// Sides
- glBegin (GL_LINES);
+ glBegin(GL_LINES);
{
- glVertex3f (coeffs.x_min, coeffs.y_min, coeffs.z_min);
- glVertex3f (coeffs.x_min, coeffs.y_min, coeffs.z_max);
+ glVertex3f(coeffs.x_min, coeffs.y_min, coeffs.z_min);
+ glVertex3f(coeffs.x_min, coeffs.y_min, coeffs.z_max);
- glVertex3f (coeffs.x_max, coeffs.y_min, coeffs.z_min);
- glVertex3f (coeffs.x_max, coeffs.y_min, coeffs.z_max);
+ glVertex3f(coeffs.x_max, coeffs.y_min, coeffs.z_min);
+ glVertex3f(coeffs.x_max, coeffs.y_min, coeffs.z_max);
- glVertex3f (coeffs.x_max, coeffs.y_max, coeffs.z_min);
- glVertex3f (coeffs.x_max, coeffs.y_max, coeffs.z_max);
+ glVertex3f(coeffs.x_max, coeffs.y_max, coeffs.z_min);
+ glVertex3f(coeffs.x_max, coeffs.y_max, coeffs.z_max);
- glVertex3f (coeffs.x_min, coeffs.y_max, coeffs.z_min);
- glVertex3f (coeffs.x_min, coeffs.y_max, coeffs.z_max);
+ glVertex3f(coeffs.x_min, coeffs.y_max, coeffs.z_min);
+ glVertex3f(coeffs.x_min, coeffs.y_max, coeffs.z_max);
}
glEnd();
}
- glPopMatrix ();
+ glPopMatrix();
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::initializeGL ()
-{
-}
+pcl::ihs::OpenGLViewer::initializeGL()
+{}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::setupViewport (const int w, const int h)
+pcl::ihs::OpenGLViewer::setupViewport(const int w, const int h)
{
- const float aspect_ratio = 4./3.;
+ const float aspect_ratio = 4. / 3.;
// Use the biggest possible area of the window to draw to
// case 1 (w < w_scaled): case 2 (w >= w_scaled):
const float w_scaled = h * aspect_ratio;
const float h_scaled = w / aspect_ratio;
- if (w < w_scaled)
- {
- glViewport (0, static_cast <GLint> ((h - h_scaled) / 2.f), w, static_cast <GLsizei> (h_scaled));
+ if (w < w_scaled) {
+ glViewport(
+ 0, static_cast<GLint>((h - h_scaled) / 2.f), w, static_cast<GLsizei>(h_scaled));
}
- else
- {
- glViewport (static_cast <GLint> ((w - w_scaled) / 2.f), 0, static_cast <GLsizei> (w_scaled), h);
+ else {
+ glViewport(
+ static_cast<GLint>((w - w_scaled) / 2.f), 0, static_cast<GLsizei>(w_scaled), h);
}
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::resizeGL (int w, int h)
+pcl::ihs::OpenGLViewer::resizeGL(int w, int h)
{
- this->setupViewport (w, h);
+ this->setupViewport(w, h);
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::mousePressEvent (QMouseEvent* /*event*/)
+pcl::ihs::OpenGLViewer::mousePressEvent(QMouseEvent* /*event*/)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
mouse_pressed_begin_ = true;
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::mouseMoveEvent (QMouseEvent* event)
+pcl::ihs::OpenGLViewer::mouseMoveEvent(QMouseEvent* event)
{
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ std::lock_guard<std::mutex> lock(mutex_vis_);
- if (mouse_pressed_begin_)
- {
- x_prev_ = event->pos ().x ();
- y_prev_ = event->pos ().y ();
+ if (mouse_pressed_begin_) {
+ x_prev_ = event->pos().x();
+ y_prev_ = event->pos().y();
mouse_pressed_begin_ = false;
return;
}
- if (event->pos ().x () == x_prev_ && event->pos ().y () == y_prev_) return;
- if (this->width () == 0 || this->height () == 0) return;
+ if (event->pos().x() == x_prev_ && event->pos().y() == y_prev_)
+ return;
+ if (this->width() == 0 || this->height() == 0)
+ return;
- const double dx = static_cast <double> (event->pos ().x ()) - static_cast <double> (x_prev_);
- const double dy = static_cast <double> (event->pos ().y ()) - static_cast <double> (y_prev_);
- const double w = static_cast <double> (this->width ());
- const double h = static_cast <double> (this->height ());
- const double d = std::sqrt (w*w + h*h);
+ const double dx =
+ static_cast<double>(event->pos().x()) - static_cast<double>(x_prev_);
+ const double dy =
+ static_cast<double>(event->pos().y()) - static_cast<double>(y_prev_);
+ const double w = static_cast<double>(this->width());
+ const double h = static_cast<double>(this->height());
+ const double d = std::sqrt(w * w + h * h);
- const Eigen::Vector3d o = Eigen::Vector3d::Zero ();
- const Eigen::Vector3d ex = Eigen::Vector3d::UnitX ();
- const Eigen::Vector3d ey = Eigen::Vector3d::UnitY ();
- const Eigen::Vector3d ez = Eigen::Vector3d::UnitZ ();
+ const Eigen::Vector3d o = Eigen::Vector3d::Zero();
+ const Eigen::Vector3d ex = Eigen::Vector3d::UnitX();
+ const Eigen::Vector3d ey = Eigen::Vector3d::UnitY();
+ const Eigen::Vector3d ez = Eigen::Vector3d::UnitZ();
// Scale with the distance between the pivot and camera eye.
- const double scale = std::max ((cam_pivot_ - R_cam_ * o - t_cam_).norm (), .1 / scaling_factor_) / d;
+ const double scale =
+ std::max((cam_pivot_ - R_cam_ * o - t_cam_).norm(), .1 / scaling_factor_) / d;
- if (QApplication::mouseButtons () == Qt::LeftButton)
- {
- const double rot_angle = -7. * std::atan (std::sqrt ((dx*dx + dy*dy)) / d);
- const Eigen::Vector3d rot_axis = (R_cam_ * ex * dy - R_cam_ * ey * dx).normalized ();
+ if (QApplication::mouseButtons() == Qt::LeftButton) {
+ const double rot_angle = -7. * std::atan(std::sqrt((dx * dx + dy * dy)) / d);
+ const Eigen::Vector3d rot_axis = (R_cam_ * ex * dy - R_cam_ * ey * dx).normalized();
- const Eigen::Quaterniond dR (Eigen::AngleAxisd (rot_angle, rot_axis));
+ const Eigen::Quaterniond dR(Eigen::AngleAxisd(rot_angle, rot_axis));
t_cam_ = dR * (t_cam_ - cam_pivot_) + cam_pivot_;
- R_cam_ = (dR * R_cam_).normalized ();
+ R_cam_ = (dR * R_cam_).normalized();
}
- else if (QApplication::mouseButtons () == Qt::MiddleButton)
- {
- t_cam_ += 1.3 * scale * Eigen::Vector3d (R_cam_ * (ey * -dy + ex * -dx));
+ else if (QApplication::mouseButtons() == Qt::MiddleButton) {
+ t_cam_ += 1.3 * scale * Eigen::Vector3d(R_cam_ * (ey * -dy + ex * -dx));
}
- else if (QApplication::mouseButtons () == Qt::RightButton)
- {
- t_cam_ += 2.6 * scale * Eigen::Vector3d (R_cam_ * (ez * -dy));
+ else if (QApplication::mouseButtons() == Qt::RightButton) {
+ t_cam_ += 2.6 * scale * Eigen::Vector3d(R_cam_ * (ez * -dy));
}
- x_prev_ = event->pos ().x ();
- y_prev_ = event->pos ().y ();
+ x_prev_ = event->pos().x();
+ y_prev_ = event->pos().y();
}
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::OpenGLViewer::wheelEvent (QWheelEvent* event)
+pcl::ihs::OpenGLViewer::wheelEvent(QWheelEvent* event)
{
- if (QApplication::mouseButtons () == Qt::NoButton)
- {
- std::lock_guard<std::mutex> lock (mutex_vis_);
+ if (QApplication::mouseButtons() == Qt::NoButton) {
+ std::lock_guard<std::mutex> lock(mutex_vis_);
// Scale with the distance between the pivot and camera eye.
- const Eigen::Vector3d o = Eigen::Vector3d::Zero ();
- const Eigen::Vector3d ez = Eigen::Vector3d::UnitZ ();
- const double w = static_cast <double> (this->width ());
- const double h = static_cast <double> (this->height ());
- const double d = std::sqrt (w*w + h*h);
- const double scale = std::max ((cam_pivot_ - R_cam_ * o - t_cam_).norm (), .1 / scaling_factor_) / d;
+ const Eigen::Vector3d o = Eigen::Vector3d::Zero();
+ const Eigen::Vector3d ez = Eigen::Vector3d::UnitZ();
+ const double w = static_cast<double>(this->width());
+ const double h = static_cast<double>(this->height());
+ const double d = std::sqrt(w * w + h * h);
+ const double scale =
+ std::max((cam_pivot_ - R_cam_ * o - t_cam_).norm(), .1 / scaling_factor_) / d;
// http://doc.qt.digia.com/qt/qwheelevent.html#delta
- t_cam_ += scale * Eigen::Vector3d (R_cam_ * (ez * static_cast <double> (event->delta ())));
+ t_cam_ +=
+ scale * Eigen::Vector3d(R_cam_ * (ez * static_cast<double>(event->delta())));
}
}
*/
#include <pcl/apps/in_hand_scanner/visibility_confidence.h>
+
#include <Eigen/Geometry> // for Isometry3f
-pcl::ihs::Dome::Dome ()
+pcl::ihs::Dome::Dome()
{
- vertices_.col ( 0) = Eigen::Vector4f (-0.000000119f, 0.000000000f, 1.000000000f, 0.f);
- vertices_.col ( 1) = Eigen::Vector4f ( 0.894427180f, 0.000000000f, 0.447213739f, 0.f);
- vertices_.col ( 2) = Eigen::Vector4f ( 0.276393145f, 0.850650907f, 0.447213650f, 0.f);
- vertices_.col ( 3) = Eigen::Vector4f (-0.723606884f, 0.525731146f, 0.447213531f, 0.f);
- vertices_.col ( 4) = Eigen::Vector4f (-0.723606884f, -0.525731146f, 0.447213531f, 0.f);
- vertices_.col ( 5) = Eigen::Vector4f ( 0.276393145f, -0.850650907f, 0.447213650f, 0.f);
- vertices_.col ( 6) = Eigen::Vector4f ( 0.343278527f, 0.000000000f, 0.939233720f, 0.f);
- vertices_.col ( 7) = Eigen::Vector4f ( 0.686557174f, 0.000000000f, 0.727075875f, 0.f);
- vertices_.col ( 8) = Eigen::Vector4f ( 0.792636156f, 0.326477438f, 0.514918089f, 0.f);
- vertices_.col ( 9) = Eigen::Vector4f ( 0.555436373f, 0.652954817f, 0.514918029f, 0.f);
- vertices_.col (10) = Eigen::Vector4f ( 0.106078848f, 0.326477438f, 0.939233720f, 0.f);
- vertices_.col (11) = Eigen::Vector4f ( 0.212157741f, 0.652954817f, 0.727075756f, 0.f);
- vertices_.col (12) = Eigen::Vector4f (-0.065560505f, 0.854728878f, 0.514917910f, 0.f);
- vertices_.col (13) = Eigen::Vector4f (-0.449357629f, 0.730025530f, 0.514917850f, 0.f);
- vertices_.col (14) = Eigen::Vector4f (-0.277718395f, 0.201774135f, 0.939233661f, 0.f);
- vertices_.col (15) = Eigen::Vector4f (-0.555436671f, 0.403548241f, 0.727075696f, 0.f);
- vertices_.col (16) = Eigen::Vector4f (-0.833154857f, 0.201774105f, 0.514917850f, 0.f);
- vertices_.col (17) = Eigen::Vector4f (-0.833154857f, -0.201774150f, 0.514917850f, 0.f);
- vertices_.col (18) = Eigen::Vector4f (-0.277718395f, -0.201774135f, 0.939233661f, 0.f);
- vertices_.col (19) = Eigen::Vector4f (-0.555436671f, -0.403548241f, 0.727075696f, 0.f);
- vertices_.col (20) = Eigen::Vector4f (-0.449357659f, -0.730025649f, 0.514917910f, 0.f);
- vertices_.col (21) = Eigen::Vector4f (-0.065560460f, -0.854728937f, 0.514917850f, 0.f);
- vertices_.col (22) = Eigen::Vector4f ( 0.106078848f, -0.326477438f, 0.939233720f, 0.f);
- vertices_.col (23) = Eigen::Vector4f ( 0.212157741f, -0.652954817f, 0.727075756f, 0.f);
- vertices_.col (24) = Eigen::Vector4f ( 0.555436373f, -0.652954757f, 0.514917970f, 0.f);
- vertices_.col (25) = Eigen::Vector4f ( 0.792636156f, -0.326477349f, 0.514918089f, 0.f);
- vertices_.col (26) = Eigen::Vector4f ( 0.491123378f, 0.356822133f, 0.794654608f, 0.f);
- vertices_.col (27) = Eigen::Vector4f (-0.187592626f, 0.577350259f, 0.794654429f, 0.f);
- vertices_.col (28) = Eigen::Vector4f (-0.607062101f, -0.000000016f, 0.794654369f, 0.f);
- vertices_.col (29) = Eigen::Vector4f (-0.187592626f, -0.577350378f, 0.794654489f, 0.f);
- vertices_.col (30) = Eigen::Vector4f ( 0.491123348f, -0.356822133f, 0.794654548f, 0.f);
-
- for (Eigen::Index i=0; i < vertices_.cols (); ++i)
- {
- vertices_.col (i).head <3> ().normalize ();
+ vertices_.col(0) = Eigen::Vector4f(-0.000000119f, 0.000000000f, 1.000000000f, 0.f);
+ vertices_.col(1) = Eigen::Vector4f(0.894427180f, 0.000000000f, 0.447213739f, 0.f);
+ vertices_.col(2) = Eigen::Vector4f(0.276393145f, 0.850650907f, 0.447213650f, 0.f);
+ vertices_.col(3) = Eigen::Vector4f(-0.723606884f, 0.525731146f, 0.447213531f, 0.f);
+ vertices_.col(4) = Eigen::Vector4f(-0.723606884f, -0.525731146f, 0.447213531f, 0.f);
+ vertices_.col(5) = Eigen::Vector4f(0.276393145f, -0.850650907f, 0.447213650f, 0.f);
+ vertices_.col(6) = Eigen::Vector4f(0.343278527f, 0.000000000f, 0.939233720f, 0.f);
+ vertices_.col(7) = Eigen::Vector4f(0.686557174f, 0.000000000f, 0.727075875f, 0.f);
+ vertices_.col(8) = Eigen::Vector4f(0.792636156f, 0.326477438f, 0.514918089f, 0.f);
+ vertices_.col(9) = Eigen::Vector4f(0.555436373f, 0.652954817f, 0.514918029f, 0.f);
+ vertices_.col(10) = Eigen::Vector4f(0.106078848f, 0.326477438f, 0.939233720f, 0.f);
+ vertices_.col(11) = Eigen::Vector4f(0.212157741f, 0.652954817f, 0.727075756f, 0.f);
+ vertices_.col(12) = Eigen::Vector4f(-0.065560505f, 0.854728878f, 0.514917910f, 0.f);
+ vertices_.col(13) = Eigen::Vector4f(-0.449357629f, 0.730025530f, 0.514917850f, 0.f);
+ vertices_.col(14) = Eigen::Vector4f(-0.277718395f, 0.201774135f, 0.939233661f, 0.f);
+ vertices_.col(15) = Eigen::Vector4f(-0.555436671f, 0.403548241f, 0.727075696f, 0.f);
+ vertices_.col(16) = Eigen::Vector4f(-0.833154857f, 0.201774105f, 0.514917850f, 0.f);
+ vertices_.col(17) = Eigen::Vector4f(-0.833154857f, -0.201774150f, 0.514917850f, 0.f);
+ vertices_.col(18) = Eigen::Vector4f(-0.277718395f, -0.201774135f, 0.939233661f, 0.f);
+ vertices_.col(19) = Eigen::Vector4f(-0.555436671f, -0.403548241f, 0.727075696f, 0.f);
+ vertices_.col(20) = Eigen::Vector4f(-0.449357659f, -0.730025649f, 0.514917910f, 0.f);
+ vertices_.col(21) = Eigen::Vector4f(-0.065560460f, -0.854728937f, 0.514917850f, 0.f);
+ vertices_.col(22) = Eigen::Vector4f(0.106078848f, -0.326477438f, 0.939233720f, 0.f);
+ vertices_.col(23) = Eigen::Vector4f(0.212157741f, -0.652954817f, 0.727075756f, 0.f);
+ vertices_.col(24) = Eigen::Vector4f(0.555436373f, -0.652954757f, 0.514917970f, 0.f);
+ vertices_.col(25) = Eigen::Vector4f(0.792636156f, -0.326477349f, 0.514918089f, 0.f);
+ vertices_.col(26) = Eigen::Vector4f(0.491123378f, 0.356822133f, 0.794654608f, 0.f);
+ vertices_.col(27) = Eigen::Vector4f(-0.187592626f, 0.577350259f, 0.794654429f, 0.f);
+ vertices_.col(28) = Eigen::Vector4f(-0.607062101f, -0.000000016f, 0.794654369f, 0.f);
+ vertices_.col(29) = Eigen::Vector4f(-0.187592626f, -0.577350378f, 0.794654489f, 0.f);
+ vertices_.col(30) = Eigen::Vector4f(0.491123348f, -0.356822133f, 0.794654548f, 0.f);
+
+ for (Eigen::Index i = 0; i < vertices_.cols(); ++i) {
+ vertices_.col(i).head<3>().normalize();
}
}
////////////////////////////////////////////////////////////////////////////////
pcl::ihs::Dome::Vertices
-pcl::ihs::Dome::getVertices () const
+pcl::ihs::Dome::getVertices() const
{
return (vertices_);
}
////////////////////////////////////////////////////////////////////////////////
-namespace pcl
-{
- namespace ihs
- {
- static const pcl::ihs::Dome dome;
- } // End namespace ihs
+namespace pcl {
+namespace ihs {
+static const pcl::ihs::Dome dome;
+} // End namespace ihs
} // End namespace pcl
////////////////////////////////////////////////////////////////////////////////
void
-pcl::ihs::addDirection (const Eigen::Vector4f& normal,
- const Eigen::Vector4f& direction,
- std::uint32_t& directions)
+pcl::ihs::addDirection(const Eigen::Vector4f& normal,
+ const Eigen::Vector4f& direction,
+ std::uint32_t& directions)
{
// Find the rotation that aligns the normal with [0; 0; 1]
- const float dot = normal.z ();
+ const float dot = normal.z();
- Eigen::Isometry3f R = Eigen::Isometry3f::Identity ();
+ Eigen::Isometry3f R = Eigen::Isometry3f::Identity();
- // No need to transform if the normal is already very close to [0; 0; 1] (also avoids numerical issues)
+ // No need to transform if the normal is already very close to [0; 0; 1] (also avoids
+ // numerical issues)
// TODO: The threshold is hard coded for a frequency=3.
// It can be calculated with
// - max_z = maximum z value of the dome vertices (excluding [0; 0; 1])
// - thresh = std::cos (std::acos (max_z) / 2)
// - always round up!
// - with max_z = 0.939 -> thresh = 0.9847 ~ 0.985
- if (dot <= .985f)
- {
- const Eigen::Vector3f axis = Eigen::Vector3f (normal.y (), -normal.x (), 0.f).normalized ();
- R = Eigen::Isometry3f (Eigen::AngleAxisf (std::acos (dot), axis));
+ if (dot <= .985f) {
+ const auto axis = Eigen::Vector3f(normal.y(), -normal.x(), 0.f).normalized();
+ R = Eigen::Isometry3f(Eigen::AngleAxisf(std::acos(dot), axis));
}
- // Transform the direction into the dome coordinate system (which is aligned with the normal)
+ // Transform the direction into the dome coordinate system (which is aligned with the
+ // normal)
Eigen::Vector4f aligned_direction = (R * direction);
- aligned_direction.head <3> ().normalize ();
+ aligned_direction.head<3>().normalize();
- if (aligned_direction.z () < 0)
- {
+ if (aligned_direction.z() < 0) {
return;
}
// std::acos (angle) = dot (a, b) / (norm (a) * norm (b)
// m_sphere_vertices are already normalized
unsigned int index = 0;
- aligned_direction.transpose ().lazyProduct (pcl::ihs::dome.getVertices ()).maxCoeff (&index);
+ aligned_direction.transpose()
+ .lazyProduct(pcl::ihs::dome.getVertices())
+ .maxCoeff(&index);
// Set the observed direction bit at 'index'
// http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c/47990#47990
////////////////////////////////////////////////////////////////////////////////
unsigned int
-pcl::ihs::countDirections (const std::uint32_t directions)
+pcl::ihs::countDirections(const std::uint32_t directions)
{
// http://stackoverflow.com/questions/109023/best-algorithm-to-count-the-number-of-set-bits-in-a-32-bit-integer/109025#109025
unsigned int i = directions - ((directions >> 1) & 0x55555555);
ManualRegistration();
- ~ManualRegistration() {}
+ ~ManualRegistration() override = default;
void
setSrcCloud(pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_src)
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
-#include <cfloat> // for FLT_MAX
+#include <limits>
+#include <map> // for std::map
namespace pcl {
{
// Do not limit the number of dimensions used in the tree
typename pcl::CustomPointRepresentation<PointT>::Ptr cpr(
- new pcl::CustomPointRepresentation<PointT>(INT_MAX, 0));
+ new pcl::CustomPointRepresentation<PointT>(std::numeric_limits<int>::max(), 0));
tree_.reset(new pcl::KdTreeFLANN<PointT>);
tree_->setPointRepresentation(cpr);
tree_->setInputCloud(features);
* \return pair of label and score for each training class from the neighborhood
*/
ResultPtr
- classify(const PointT& p_q, double radius, float gaussian_param, int max_nn = INT_MAX)
+ classify(const PointT& p_q,
+ double radius,
+ float gaussian_param,
+ int max_nn = std::numeric_limits<int>::max())
{
pcl::Indices k_indices;
std::vector<float> k_sqr_distances;
double radius,
pcl::Indices& k_indices,
std::vector<float>& k_sqr_distances,
- int max_nn = INT_MAX)
+ int max_nn = std::numeric_limits<int>::max())
{
return tree_->radiusSearch(p_q, radius, k_indices, k_sqr_distances, max_nn);
}
std::vector<float>& k_sqr_distances)
{
// Reserve space for distances
- auto sqr_distances = std::make_shared<std::vector<float>>(classes_.size(), FLT_MAX);
+ auto sqr_distances = std::make_shared<std::vector<float>>(
+ classes_.size(), std::numeric_limits<float>::max());
// Select square distance to each class
for (auto i = k_indices.cbegin(); i != k_indices.cend(); ++i)
for (std::vector<float>::const_iterator it = sqr_distances->begin();
it != sqr_distances->end();
++it)
- if (*it != FLT_MAX) {
+ if (*it != std::numeric_limits<float>::max()) {
result->first.push_back(classes_[it - sqr_distances->begin()]);
result->second.push_back(sqrt(*it));
sum_dist += result->second.back();
for (std::vector<float>::const_iterator it = sqr_distances->begin();
it != sqr_distances->end();
++it)
- if (*it != FLT_MAX) {
+ if (*it != std::numeric_limits<float>::max()) {
result->first.push_back(classes_[it - sqr_distances->begin()]);
// TODO leave it squared, and relate param to sigma...
result->second.push_back(std::exp(-std::sqrt(*it) / gaussian_param));
OpenNIPassthrough(pcl::OpenNIGrabber& grabber);
- ~OpenNIPassthrough()
+ ~OpenNIPassthrough() override
{
if (grabber_.isRunning())
grabber_.stop();
OrganizedSegmentationDemo(pcl::Grabber& grabber);
- ~OrganizedSegmentationDemo()
+ ~OrganizedSegmentationDemo() override
{
if (grabber_.isRunning())
grabber_.stop();
PCDVideoPlayer();
- ~PCDVideoPlayer() {}
+ ~PCDVideoPlayer() override = default;
protected:
void
endif()
PCL_SUBSUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSUBSYS_DEPEND(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" DEPS ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSUBSYS_NAME} PARENT_NAME ${SUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
PCL_ADD_DOC("${SUBSUBSYS_NAME}")
class AbstractItem {
public:
AbstractItem();
- ~AbstractItem();
void
showContextMenu(const QPoint* position);
CloudMesh();
CloudMesh(PointCloudPtr cloud);
- ~CloudMesh();
PointCloudPtr&
getCloud()
CloudMeshItem(QTreeWidgetItem* parent, const std::string& filename);
CloudMeshItem(QTreeWidgetItem* parent, CloudMesh::PointCloudPtr cloud);
CloudMeshItem(QTreeWidgetItem* parent, const CloudMeshItem& cloud_mesh_item);
- ~CloudMeshItem();
inline CloudMesh::Ptr&
getCloudMesh()
public:
CloudMeshItemUpdater(CloudMeshItem* cloud_mesh_item);
- ~CloudMeshItemUpdater();
public Q_SLOTS:
void
Qt::WindowFlags flags = Qt::WindowFlags());
explicit DockWidget(QWidget* parent = nullptr,
Qt::WindowFlags flags = Qt::WindowFlags());
- ~DockWidget();
void
setFocusBasedStyle(bool focused);
ICPRegistrationWorker(CloudMesh::PointCloudPtr cloud,
const QList<CloudMeshItem*>& cloud_mesh_items,
QWidget* parent = nullptr);
- ~ICPRegistrationWorker();
protected:
std::string
NormalsActorItem(QTreeWidgetItem* parent,
const CloudMesh::Ptr& cloud_mesh,
const vtkSmartPointer<vtkRenderWindow>& render_window);
- ~NormalsActorItem();
std::string
getItemName() const override
const boost::any& value)
: name_(name), description_(description), default_value_(value), current_value_(value)
{}
- ~Parameter() {}
+ virtual ~Parameter() = default;
const std::string&
getName() const
BoolParameter(const std::string& name, const std::string& description, bool value)
: Parameter(name, description, value)
{}
- ~BoolParameter() {}
operator bool() const { return boost::any_cast<bool>(current_value_); }
int step = 1)
: Parameter(name, description, value), low_(low), high_(high), step_(step)
{}
- virtual ~IntParameter() {}
operator int() const { return boost::any_cast<int>(current_value_); }
const std::map<T, std::string>& candidates)
: Parameter(name, description, value), candidates_(candidates)
{}
- ~EnumParameter() {}
operator T() const { return boost::any_cast<T>(current_value_); }
double step = 0.01)
: Parameter(name, description, value), low_(low), high_(high), step_(step)
{}
- virtual ~DoubleParameter() {}
operator double() const { return boost::any_cast<double>(current_value_); }
const QColor& value)
: Parameter(name, description, value)
{}
- ~ColorParameter() {}
operator QColor() const { return boost::any_cast<QColor>(current_value_); }
ParameterModel(int rows, int columns, QObject* parent = nullptr)
: QStandardItemModel(rows, columns, parent)
{}
- ~ParameterModel() {}
Qt::ItemFlags
flags(const QModelIndex& index) const override
Q_OBJECT
public:
ParameterDialog(const std::string& title, QWidget* parent = nullptr);
- ~ParameterDialog() {}
void
addParameter(Parameter* parameter);
PointsActorItem(QTreeWidgetItem* parent,
const CloudMesh::Ptr& cloud_mesh,
const vtkSmartPointer<vtkRenderWindow>& render_window);
- ~PointsActorItem();
std::string
getItemName() const override
public:
RenderWindow(RenderWindowItem* render_window_item,
QWidget* parent = nullptr,
- Qt::WindowFlags flags = nullptr);
+ Qt::WindowFlags flags = {});
~RenderWindow();
QSize
public:
SceneTree(QWidget* parent = nullptr);
- ~SceneTree();
QSize
sizeHint() const override;
SurfaceActorItem(QTreeWidgetItem* parent,
const CloudMesh::Ptr& cloud_mesh,
const vtkSmartPointer<vtkRenderWindow>& render_window);
- ~SurfaceActorItem();
std::string
getItemName() const override
//////////////////////////////////////////////////////////////////////////////////////////////
pcl::modeler::AbstractItem::AbstractItem() {}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::AbstractItem::~AbstractItem() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::AbstractItem::showContextMenu(const QPoint* position)
updateVtkPoints();
}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::CloudMesh::~CloudMesh() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
std::vector<std::string>
pcl::modeler::CloudMesh::getAvaiableFieldNames() const
treeWidget()->expandItem(this);
}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::CloudMeshItem::~CloudMeshItem() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
bool
pcl::modeler::CloudMeshItem::savePointCloud(const QList<CloudMeshItem*>& items,
: cloud_mesh_item_(cloud_mesh_item)
{}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::CloudMeshItemUpdater::~CloudMeshItemUpdater() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::CloudMeshItemUpdater::updateCloudMeshItem()
setFocusPolicy(Qt::StrongFocus);
}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::DockWidget::~DockWidget() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::DockWidget::focusInEvent(QFocusEvent* event)
, euclidean_fitness_epsilon_(nullptr)
{}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::ICPRegistrationWorker::~ICPRegistrationWorker() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::ICPRegistrationWorker::initParameters(CloudMeshItem* cloud_mesh_item)
, scale_(0.1)
{}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::NormalsActorItem::~NormalsActorItem() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::NormalsActorItem::createNormalLines()
parent, cloud_mesh, render_window, vtkSmartPointer<vtkLODActor>::New(), "Points")
{}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::PointsActorItem::~PointsActorItem() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::PointsActorItem::initImpl()
mapper->SetScalarModeToUsePointData();
mapper->InterpolateScalarsBeforeMappingOn();
mapper->ScalarVisibilityOn();
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- mapper->ImmediateModeRenderingOff();
-#endif
vtkSmartPointer<vtkLODActor> actor =
vtkSmartPointer<vtkLODActor>(dynamic_cast<vtkLODActor*>(actor_.GetPointer()));
SLOT(slotOnItemDoubleClicked(QTreeWidgetItem*)));
}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::SceneTree::~SceneTree() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
QSize
pcl::modeler::SceneTree::sizeHint() const
closePointCloud(cloud_mesh_items);
}
- for (QStringList::const_iterator filenames_it = filenames.begin();
- filenames_it != filenames.end();
- ++filenames_it) {
- if (!openPointCloud(*filenames_it))
+ for (const auto& filename : filenames) {
+ if (!openPointCloud(filename))
QMessageBox::warning(main_window,
tr("Failed to Open Point Cloud"),
tr("Can not open point cloud file %1, please check if it's "
"in valid .pcd format!")
- .arg(*filenames_it));
+ .arg(filename));
}
}
if (filenames.isEmpty())
return;
- for (QStringList::const_iterator filenames_it = filenames.begin();
- filenames_it != filenames.end();
- ++filenames_it) {
- if (!openPointCloud(*filenames_it))
+ for (const auto& filename : filenames) {
+ if (!openPointCloud(filename)) {
QMessageBox::warning(
main_window,
tr("Failed to Import Point Cloud"),
- tr("Can not import point cloud file %1 as .pcd file!").arg(*filenames_it));
+ tr("Can not import point cloud file %1 as .pcd file!").arg(filename));
+ }
}
}
delete item;
}
- for (QList<RenderWindowItem*>::const_iterator render_window_items_it =
- render_window_items.begin();
- render_window_items_it != render_window_items.end();
- ++render_window_items_it) {
- (*render_window_items_it)->getRenderWindow()->render();
+ for (const auto& render_window_item : render_window_items) {
+ render_window_item->getRenderWindow()->render();
}
}
const QItemSelection& deselected)
{
QModelIndexList selected_indices = selected.indexes();
- for (QModelIndexList::const_iterator selected_indices_it = selected_indices.begin();
- selected_indices_it != selected_indices.end();
- ++selected_indices_it) {
- QTreeWidgetItem* item = itemFromIndex(*selected_indices_it);
+ for (const auto& selected_index : selected_indices) {
+ QTreeWidgetItem* item = itemFromIndex(selected_index);
RenderWindowItem* render_window_item = dynamic_cast<RenderWindowItem*>(item);
if (render_window_item != nullptr) {
render_window_item->getRenderWindow()->setActive(true);
}
QModelIndexList deselected_indices = deselected.indexes();
- for (QModelIndexList::const_iterator deselected_indices_it =
- deselected_indices.begin();
- deselected_indices_it != deselected_indices.end();
- ++deselected_indices_it) {
- QTreeWidgetItem* item = itemFromIndex(*deselected_indices_it);
- RenderWindowItem* render_window_item = dynamic_cast<RenderWindowItem*>(item);
+ for (const auto& deselected_index : deselected_indices) {
+ QTreeWidgetItem* item = itemFromIndex(deselected_index);
+ auto* render_window_item = dynamic_cast<RenderWindowItem*>(item);
if (render_window_item != nullptr) {
render_window_item->getRenderWindow()->setActive(false);
}
parent, cloud_mesh, render_window, vtkSmartPointer<vtkLODActor>::New(), "Surface")
{}
-//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::modeler::SurfaceActorItem::~SurfaceActorItem() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::modeler::SurfaceActorItem::initImpl()
mapper->SetScalarModeToUsePointData();
mapper->InterpolateScalarsBeforeMappingOn();
mapper->ScalarVisibilityOn();
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- mapper->ImmediateModeRenderingOff();
-#endif
vtkSmartPointer<vtkLODActor> actor =
vtkSmartPointer<vtkLODActor>(dynamic_cast<vtkLODActor*>(actor_.GetPointer()));
set(DEFAULT FALSE)
endif()
-PCL_SUBSUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSUBSYS_DEPEND(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
+PCL_SUBSUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSUBSYS_NAME}" "${SUBSUBSYS_DESC}" ${DEFAULT} "${REASON}")
+PCL_SUBSYS_DEPEND(build NAME ${SUBSUBSYS_NAME} PARENT_NAME ${SUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} EXT_DEPS ${SUBSUBSYS_EXT_DEPS})
PCL_ADD_DOC(${SUBSUBSYS_NAME})
if(NOT build)
CloudEditorWidget (QWidget *parent = nullptr);
/// @brief Destructor
- ~CloudEditorWidget ();
+ ~CloudEditorWidget () override;
/// @brief Attempts to load the point cloud designated by the passed file
/// name.
CloudTransformTool (CloudPtr cloud_ptr);
/// @brief Destructor
- ~CloudTransformTool ();
+ ~CloudTransformTool () override;
/// @brief Initialize the current transform with mouse screen coordinates
/// and key modifiers.
public:
/// @brief Destructor
virtual ~Command ()
- {
- }
+ = default;
protected:
/// Allows command queues to be the only objects which are able to execute
/// @brief Destructor
~CommandQueue ()
- {
- }
+ = default;
/// @brief Executes a command. If the command has an undo function, then
/// adds the command to the queue.
operator= (const CutCommand&) = delete;
/// @brief Destructor
- ~CutCommand ();
+ ~CutCommand () override;
protected:
/// @brief Moves the selected points to the copy buffer and removes them
DenoiseParameterForm();
/// @brief Destructor
- ~DenoiseParameterForm ();
+ ~DenoiseParameterForm () override;
/// @brief Returns the mean
inline
MainWindow (int argc, char **argv);
/// @brief Destructor
- ~MainWindow ();
+ ~MainWindow () override;
/// @brief Increase the value of the spinbox by 1.
void
Select1DTool (SelectionPtr selection_ptr, CloudPtr cloud_ptr);
/// @brief Destructor
- ~Select1DTool ()
- {
- }
+ ~Select1DTool () override
+ = default;
/// @brief Does nothing for 1D selection.
/// @sa end
Select2DTool (SelectionPtr selection_ptr, CloudPtr cloud_ptr);
/// @brief Destructor
- ~Select2DTool ();
+ ~Select2DTool () override;
/// @brief Initializes the selection tool with the initial mouse screen
/// coordinates and key modifiers. The passed coordinates are used for
CommandQueuePtr command_queue_ptr);
/// @brief Destructor
- ~SelectionTransformTool ()
- {
- }
+ ~SelectionTransformTool () override
+ = default;
/// @brief Initialize the transform tool with mouse screen coordinates
/// and key modifiers.
public:
/// @brief Destructor
virtual ~Statistics ()
- {
- }
+ = default;
/// @brief Returns the strings of the statistics.
static
protected:
/// @brief The default constructor.
Statistics ()
- {
- }
+ = default;
/// @brief Copy Constructor
Statistics (const Statistics&)
/// @brief Default Constructor
StatisticsDialog(QWidget *parent = nullptr);
/// @brief Destructor
- ~StatisticsDialog ();
+ ~StatisticsDialog () override;
public Q_SLOTS:
/// @brief update the dialog box.
public:
/// @brief Destructor.
virtual ~ToolInterface ()
- {
- }
+ = default;
/// @brief set the initial state of the tool from the screen coordinates
/// of the mouse as well as the value of the modifier.
protected:
/// @brief Default constructor
ToolInterface ()
- {
- }
+ = default;
private:
/// @brief Copy constructor - tools are non-copyable
}
CloudEditorWidget::~CloudEditorWidget ()
-{
-}
+= default;
void
CloudEditorWidget::loadFile(const std::string &filename)
}
CloudTransformTool::~CloudTransformTool ()
-{
-}
+= default;
void
CloudTransformTool::start (int x, int y, BitMask, BitMask)
r[i * MATRIX_SIZE_DIM + j] = sum;
}
}
- std::copy(r, r+MATRIX_SIZE, result);
+ std::copy(r, r + MATRIX_SIZE, result);
}
}
CutCommand::~CutCommand ()
-{
-}
+= default;
void
CutCommand::execute ()
}
MainWindow::~MainWindow()
-{
-
-}
+= default;
void
MainWindow::about ()
}
Select2DTool::~Select2DTool ()
-{
-}
+= default;
void
Select2DTool::start (int x, int y, BitMask, BitMask)
Selection::const_iterator it = selection_ptr_->begin();
Point3D point_3d = cloud_ptr_->getObjectSpacePoint (*it);
float *pt = &(point_3d.data[X]);
- std::copy(pt, pt+XYZ_SIZE, max_xyz);
- std::copy(max_xyz, max_xyz+XYZ_SIZE, min_xyz);
+ std::copy(pt, pt + XYZ_SIZE, max_xyz);
+ std::copy(max_xyz, max_xyz + XYZ_SIZE, min_xyz);
for (++it; it != selection_ptr_->end(); ++it)
{
(TRACKBALL_RADIUS_SCALE * static_cast<float>(WINDOW_WIDTH));
}
-TrackBall::TrackBall(const TrackBall ©) :
- quat_(copy.quat_), origin_x_(copy.origin_x_), origin_y_(copy.origin_y_),
- origin_z_(copy.origin_z_), radius_sqr_(copy.radius_sqr_)
-{
-
-}
+TrackBall::TrackBall(const TrackBall ©)
+= default;
TrackBall::~TrackBall()
-{
-
-}
+= default;
TrackBall&
TrackBall::operator=(const TrackBall &rhs)
-{
- quat_ = rhs.quat_;
- origin_x_ = rhs.origin_x_;
- origin_y_ = rhs.origin_y_;
- origin_z_ = rhs.origin_z_;
- radius_sqr_ = rhs.radius_sqr_;
- return *this;
-}
+= default;
void
TrackBall::start(int s_x, int s_y)
translate_z_(translate_z)
{
internal_selection_ptr_ = SelectionPtr(new Selection(*selection_ptr));
- std::copy(matrix, matrix+MATRIX_SIZE, transform_matrix_);
+ std::copy(matrix, matrix + MATRIX_SIZE, transform_matrix_);
const float *cloud_matrix = cloud_ptr_->getMatrix();
- std::copy(cloud_matrix, cloud_matrix+MATRIX_SIZE, cloud_matrix_);
+ std::copy(cloud_matrix, cloud_matrix + MATRIX_SIZE, cloud_matrix_);
invertMatrix(cloud_matrix, cloud_matrix_inv_);
cloud_ptr_->getCenter(cloud_center_[X], cloud_center_[Y], cloud_center_[Z]);
}
// user don't need help find convolving direction
// convolve row
- if (pcl::console::find_switch(argc, argv, "-r"))
+ if (pcl::console::find_switch(argc, argv, "-r")) {
direction = 0;
+ }
else {
// convolve column
- if (pcl::console::find_switch(argc, argv, "-c"))
+ if (pcl::console::find_switch(argc, argv, "-c")) {
direction = 1;
- else
- // convolve both
- if (pcl::console::find_switch(argc, argv, "-s"))
- direction = 2;
- else {
- // wrong direction given print usage
- usage(argv);
- return 1;
}
+ else
+ // convolve both
+ if (pcl::console::find_switch(argc, argv, "-s")) {
+ direction = 2;
+ }
+ else {
+ // wrong direction given print usage
+ usage(argv);
+ return 1;
+ }
}
// number of threads if any
: pcl::GrabCut<pcl::PointXYZRGB>(K, lambda)
{}
- ~GrabCutHelper() {}
+ ~GrabCutHelper() override = default;
void
setInputCloud(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr& cloud) override;
GrabCutHelper::buildImages()
{
using namespace pcl::segmentation::grabcut;
- memset(&(*n_links_image_)[0], 0, sizeof(float) * n_links_image_->size());
+ std::fill(n_links_image_->begin(), n_links_image_->end(), 0.0f);
for (int y = 0; y < static_cast<int>(image_->height); ++y) {
for (int x = 0; x < static_cast<int>(image_->width); ++x) {
std::size_t index = y * image_->width + x;
#include <QEvent>
#include <QMutexLocker>
#include <QObject>
+
+#include <vtkVersion.h>
+#if VTK_MAJOR_VERSION >= 9 || (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 2)
+#define HAS_QVTKOPENGLWINDOW_H
+#include <QVTKOpenGLWindow.h>
+#endif
#include <ui_manual_registration.h>
#include <vtkCamera.h>
int
main(int argc, char** argv)
{
+#ifdef HAS_QVTKOPENGLWINDOW_H
+ QSurfaceFormat::setDefaultFormat(QVTKOpenGLWindow::defaultFormat());
+#endif
QApplication app(argc, argv);
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr cloud_src(
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb(cloud);
return 1;
}
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(arg);
if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgba>()) {
PCL_INFO("PointXYZRGBA mode enabled.\n");
- OpenNI3DConcaveHull<pcl::PointXYZRGBA> v("");
+ OpenNI3DConcaveHull<pcl::PointXYZRGBA> v(arg);
v.run();
}
else {
PCL_INFO("PointXYZ mode enabled.\n");
- OpenNI3DConcaveHull<pcl::PointXYZ> v("");
+ OpenNI3DConcaveHull<pcl::PointXYZ> v(arg);
v.run();
}
return 0;
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb(cloud);
return 1;
}
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(arg);
if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgba>()) {
PCL_INFO("PointXYZRGBA mode enabled.\n");
- OpenNI3DConvexHull<pcl::PointXYZRGBA> v("");
+ OpenNI3DConvexHull<pcl::PointXYZRGBA> v(arg);
v.run();
}
else {
PCL_INFO("PointXYZ mode enabled.\n");
- OpenNI3DConvexHull<pcl::PointXYZ> v("");
+ OpenNI3DConvexHull<pcl::PointXYZ> v(arg);
v.run();
}
return 0;
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr&)> f =
[this](const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr& cloud) {
return 1;
}
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(arg);
if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgb>()) {
- OpenNIIntegralImageNormalEstimation v("");
+ OpenNIIntegralImageNormalEstimation v(arg);
v.run();
}
else
void
run()
{
- pcl::OpenNIGrabber interface{};
+ pcl::OpenNIGrabber interface;
std::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
[this](const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr& cloud) {
void
run(int argc, char** argv)
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb(cloud);
return 1;
}
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(arg);
if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgba>()) {
PCL_INFO("PointXYZRGBA mode enabled.\n");
- OpenNIFastMesh<pcl::PointXYZRGBA> v("");
+ OpenNIFastMesh<pcl::PointXYZRGBA> v(arg);
v.run(argc, argv);
}
else {
PCL_INFO("PointXYZ mode enabled.\n");
- OpenNIFastMesh<pcl::PointXYZ> v("");
+ OpenNIFastMesh<pcl::PointXYZ> v(arg);
v.run(argc, argv);
}
return 0;
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb(cloud);
"MultiscaleFeaturePersistence class using the FPFH features\n"
<< "Use \"-h\" to get more info about the available options.\n";
+ std::string arg = "";
+ if ((argc > 1) && (argv[1][0] != '-'))
+ arg = std::string(argv[1]);
+
if (pcl::console::find_argument(argc, argv, "-h") == -1) {
usage(argv);
return 1;
float alpha = default_alpha;
pcl::console::parse_argument(argc, argv, "-persistence_alpha", alpha);
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(arg);
if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgba>()) {
PCL_INFO("PointXYZRGBA mode enabled.\n");
OpenNIFeaturePersistence<pcl::PointXYZRGBA> v(
- subsampling_leaf_size, normal_search_radius, scales_vector, alpha, "");
+ subsampling_leaf_size, normal_search_radius, scales_vector, alpha, arg);
v.run();
}
else {
PCL_INFO("PointXYZ mode enabled.\n");
OpenNIFeaturePersistence<pcl::PointXYZ> v(
- subsampling_leaf_size, normal_search_radius, scales_vector, alpha, "");
+ subsampling_leaf_size, normal_search_radius, scales_vector, alpha, arg);
v.run();
}
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/common/float_image_utils.h>
#include <pcl/visualization/image_viewer.h>
-#include <pcl/visualization/vtk.h>
#include <pcl/point_types.h>
#include <boost/filesystem.hpp>
<< "Supported image modes for device: " << device->getVendorName()
<< " , " << device->getProductName() << std::endl;
modes = grabber.getAvailableImageModes();
- for (std::vector<std::pair<int, XnMapOutputMode>>::const_iterator it =
- modes.begin();
- it != modes.end();
- ++it) {
- std::cout << it->first << " = " << it->second.nXRes << " x "
- << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ for (const auto& mode : modes) {
+ std::cout << mode.first << " = " << mode.second.nXRes << " x "
+ << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
}
}
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb(cloud);
std::cout << "<Q,q> quit\n\n";
// clang-format on
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(arg);
if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgba>()) {
PCL_INFO("PointXYZRGBA mode enabled.\n");
- OpenNIIntegralImageNormalEstimation<pcl::PointXYZRGBA> v("");
+ OpenNIIntegralImageNormalEstimation<pcl::PointXYZRGBA> v(arg);
v.run();
}
else {
PCL_INFO("PointXYZ mode enabled.\n");
- OpenNIIntegralImageNormalEstimation<pcl::PointXYZ> v("");
+ OpenNIIntegralImageNormalEstimation<pcl::PointXYZ> v(arg);
v.run();
}
<< " , " << device->getProductName() << std::endl;
std::vector<std::pair<int, XnMapOutputMode>> modes =
grabber.getAvailableDepthModes();
- for (std::vector<std::pair<int, XnMapOutputMode>>::const_iterator it =
- modes.begin();
- it != modes.end();
- ++it) {
- std::cout << it->first << " = " << it->second.nXRes << " x "
- << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ for (const auto& mode : modes) {
+ std::cout << mode.first << " = " << mode.second.nXRes << " x "
+ << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
if (device->hasImageStream()) {
<< "Supported image modes for device: " << device->getVendorName()
<< " , " << device->getProductName() << std::endl;
modes = grabber.getAvailableImageModes();
- for (std::vector<std::pair<int, XnMapOutputMode>>::const_iterator it =
- modes.begin();
- it != modes.end();
- ++it) {
- std::cout << it->first << " = " << it->second.nXRes << " x "
- << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ for (const auto& mode : modes) {
+ std::cout << mode.first << " = " << mode.second.nXRes << " x "
+ << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
}
}
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb_(cloud);
void
usage(char** argv)
{
- std::cout << "usage: " << argv[0] << " <options>\n"
+ std::cout << "usage: " << argv[0] << " <device_id> <options>\n"
<< "where options are:\n"
<< " -port p :: set the server port (default: 11111)\n"
<< " -leaf x, y, z :: set the voxel grid leaf size (default: 0.01)\n";
int
main(int argc, char** argv)
{
+ std::string device_id = "";
+ if ((argc > 1) && (argv[1][0] != '-'))
+ device_id = std::string(argv[1]);
+
if (pcl::console::find_argument(argc, argv, "-h") != -1) {
usage(argv);
return 0;
int port = 11111;
float leaf_x = 0.01f, leaf_y = 0.01f, leaf_z = 0.01f;
- std::string device_id;
pcl::console::parse_argument(argc, argv, "-port", port);
pcl::console::parse_3x_arguments(argc, argv, "-leaf", leaf_x, leaf_y, leaf_z, false);
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(device_id);
if (!grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgba>()) {
std::cout << "OpenNI grabber does not provide the rgba cloud format." << std::endl;
return 1;
{
// create a new grabber for OpenNI devices
- pcl::OpenNIGrabber interface{};
+ pcl::OpenNIGrabber interface;
// make callback function from member function
std::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
run()
{
// create a new grabber for OpenNI devices
- pcl::OpenNIGrabber interface{};
+ pcl::OpenNIGrabber interface;
// make callback function from member function
std::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
if (!bRawImageEncoding_) {
// create a new grabber for OpenNI devices
- pcl::OpenNIGrabber interface{};
+ pcl::OpenNIGrabber interface;
// make callback function from member function
std::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
{
if (!bRawImageEncoding_) {
// create a new grabber for OpenNI devices
- pcl::OpenNIGrabber interface{};
+ pcl::OpenNIGrabber interface;
// make callback function from member function
std::function<void(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
OpenNIOrganizedEdgeDetection()
: viewer(new pcl::visualization::PCLVisualizer("PCL Organized Edge Detection"))
{}
- ~OpenNIOrganizedEdgeDetection() {}
+ ~OpenNIOrganizedEdgeDetection() = default;
pcl::visualization::PCLVisualizer::Ptr
initCloudViewer(const pcl::PointCloud<PointT>::ConstPtr& cloud)
void
run()
{
- pcl::OpenNIGrabber interface{};
+ pcl::OpenNIGrabber interface;
std::function<void(const pcl::PointCloud<PointT>::ConstPtr&)> f =
[this](const pcl::PointCloud<PointT>::ConstPtr& cloud) { cloud_cb_(cloud); };
//std::cout << "<5> EDGELABEL_RGB_CANNY edge" << std::endl;
std::cout << "<Q,q> quit" << std::endl;
// clang-format on
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(arg);
if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgb>()) {
OpenNIOrganizedEdgeDetection app;
app.run();
std::mutex cloud_mutex;
public:
- OpenNIOrganizedMultiPlaneSegmentation() {}
- ~OpenNIOrganizedMultiPlaneSegmentation() {}
+ OpenNIOrganizedMultiPlaneSegmentation() = default;
+ ~OpenNIOrganizedMultiPlaneSegmentation() = default;
pcl::visualization::PCLVisualizer::Ptr
cloudViewer(const pcl::PointCloud<PointT>::ConstPtr& cloud)
void
run()
{
- pcl::OpenNIGrabber interface{};
+ pcl::OpenNIGrabber interface;
std::function<void(const pcl::PointCloud<PointT>::ConstPtr&)> f =
[this](const pcl::PointCloud<PointT>::ConstPtr& cloud) { cloud_cb_(cloud); };
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb_(cloud);
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb_(cloud);
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb(cloud);
};
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb_(cloud);
void
run()
{
- pcl::OpenNIGrabber interface{device_id_};
+ pcl::OpenNIGrabber interface(device_id_);
std::function<void(const CloudConstPtr&)> f = [this](const CloudConstPtr& cloud) {
cloud_cb_(cloud);
int
main(int argc, char** argv)
{
- if (pcl::console::find_argument(argc, argv, "-h") != -1)
+ std::string arg = "";
+ if ((argc > 1) && (argv[1][0] != '-'))
+ arg = std::string(argv[1]);
+
+ if (pcl::console::find_argument(argc, argv, "-h") != -1) {
usage(argv);
+ return 1;
+ }
float min_v = 0.0f, max_v = 5.0f;
pcl::console::parse_2x_arguments(argc, argv, "-minmax", min_v, max_v);
pcl::console::parse_3x_arguments(argc, argv, "-leaf", leaf_x, leaf_y, leaf_z);
PCL_INFO("Using %f, %f, %f as a leaf size for VoxelGrid.\n", leaf_x, leaf_y, leaf_z);
- pcl::OpenNIGrabber grabber("");
+ pcl::OpenNIGrabber grabber(arg);
if (grabber.providesCallback<pcl::OpenNIGrabber::sig_cb_openni_point_cloud_rgba>()) {
OpenNIVoxelGrid<pcl::PointXYZRGBA> v(
- "", field_name, min_v, max_v, leaf_x, leaf_y, leaf_z);
+ arg, field_name, min_v, max_v, leaf_x, leaf_y, leaf_z);
v.run();
}
else {
OpenNIVoxelGrid<pcl::PointXYZ> v(
- "", field_name, min_v, max_v, leaf_x, leaf_y, leaf_z);
+ arg, field_name, min_v, max_v, leaf_x, leaf_y, leaf_z);
v.run();
}
#include <QMutexLocker>
#include <QObject>
#include <QRadioButton>
+#if VTK_MAJOR_VERSION >= 9 || (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 2)
+#define HAS_QVTKOPENGLWINDOW_H
+#include <QVTKOpenGLWindow.h>
+#endif
#include <ui_pcd_video_player.h>
#include <vtkCamera.h>
int
main(int argc, char** argv)
{
+#ifdef HAS_QVTKOPENGLWINDOW_H
+ QSurfaceFormat::setDefaultFormat(QVTKOpenGLWindow::defaultFormat());
+#endif
QApplication app(argc, argv);
PCDVideoPlayer VideoPlayer;
mapper->SetInputConnection(trans_filter_scale->GetOutputPort());
mapper->Update();
- //////////////////////////////
- // * Compute area of the mesh
- //////////////////////////////
- vtkSmartPointer<vtkCellArray> cells = mapper->GetInput()->GetPolys();
- vtkIdType npts = 0;
- vtkCellPtsPtr ptIds = nullptr;
-
- double p1[3], p2[3], p3[3], totalArea = 0;
- for (cells->InitTraversal(); cells->GetNextCell(npts, ptIds);) {
- polydata_->GetPoint(ptIds[0], p1);
- polydata_->GetPoint(ptIds[1], p2);
- polydata_->GetPoint(ptIds[2], p3);
- totalArea += vtkTriangle::TriangleArea(p1, p2, p3);
- }
-
// create icosahedron
vtkSmartPointer<vtkPlatonicSolidSource> ico =
vtkSmartPointer<vtkPlatonicSolidSource>::New();
road_comparator->setAngularThreshold(pcl::deg2rad(3.0f));
}
- ~HRCSSegmentation() {}
+ ~HRCSSegmentation() = default;
void
cloud_cb_(const pcl::PointCloud<PointT>::ConstPtr& cloud)
set(build TRUE)
set(REASON "Disabled by default")
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
if(NOT build)
return()
endif()
find_package(benchmark REQUIRED)
+get_target_property(BenchmarkBuildType benchmark::benchmark TYPE)
+
add_custom_target(run_benchmarks)
PCL_ADD_BENCHMARK(features_normal_3d FILES features/normal_3d.cpp
set(multiValueArgs)
cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to UseCompilerCache: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
if(NOT ARGS_CCACHE)
set(ARGS_CCACHE ccache)
endif()
endforeach()
- if(NOT QUIET)
+ if(NOT ARGS_QUIET)
message(STATUS "Using Compiler Cache (${CCACHE_PROGRAM}) v${version} in the C/C++ toolchain")
endif()
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx")
- # Cuda support only added in CMake 3.10
- set(cuda_supported FALSE)
- if (NOT (CMAKE_VERSION VERSION_LESS 3.10) AND CMAKE_CUDA_COMPILER)
- set(cuda_supported TRUE)
- endif()
- if(${cuda_supported})
+ if(CMAKE_CUDA_COMPILER)
pcl_ccache_compat_file_gen("launch-cuda" ${CCACHE_PROGRAM} ${CMAKE_CUDA_COMPILER})
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-cuda")
message(STATUS "Compiler cache via launch files to support Unix Makefiles and Ninja")
set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-c" PARENT_SCOPE)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-cxx" PARENT_SCOPE)
- if (${cuda_supported})
+ if (CMAKE_CUDA_COMPILER)
set(CMAKE_CUDA_COMPILER_LAUNCHER "${CMAKE_BINARY_DIR}/launch-cuda" PARENT_SCOPE)
endif()
endif()
-find_package(ClangFormat 10)
+find_package(ClangFormat 14)
# search for version number in clang-format without version number
if(ClangFormat_FOUND)
message(STATUS "Adding target 'format'")
endif()
set(Boost_ADDITIONAL_VERSIONS
- "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75"
+ "1.80.0" "1.80"
+ "1.79.0" "1.79" "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")
function(checkVTKComponents)
- cmake_parse_arguments(PARAM "" "MISSING_COMPONENTS" "COMPONENTS" ${ARGN})
+ cmake_parse_arguments(ARGS "" "MISSING_COMPONENTS" "COMPONENTS" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to checkVTKComponents: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
set(vtkMissingComponents)
- foreach(vtkComponent ${PARAM_COMPONENTS})
+ foreach(vtkComponent ${ARGS_COMPONENTS})
if (VTK_VERSION VERSION_LESS 9.0)
if (NOT TARGET ${vtkComponent})
list(APPEND vtkMissingComponents ${vtkComponent})
endif()
endforeach()
- set(${PARAM_MISSING_COMPONENTS} ${vtkMissingComponents} PARENT_SCOPE)
+ if(ARGS_MISSING_COMPONENTS)
+ set(${ARGS_MISSING_COMPONENTS} ${vtkMissingComponents} PARENT_SCOPE)
+ endif()
endfunction()
# Start with a generic call to find any VTK version we are supporting, so we retrieve
ViewsContext2D
)
-#If VTK version 6 use OpenGL
-if(VTK_VERSION VERSION_LESS 7.0)
- set(VTK_RENDERING_BACKEND "OpenGL")
- set(VTK_RENDERING_BACKEND_OPENGL_VERSION "1")
- message(DEPRECATION "The rendering backend OpenGL is deprecated and not available anymore since VTK 8.2."
- "Please switch to the OpenGL2 backend instead, which is available since VTK 6.2."
- "Support of the deprecated backend will be dropped with PCL 1.13.")
-
-#If VTK version 7,8 or 9 use OpenGL2
-else()
- set(VTK_RENDERING_BACKEND "OpenGL2")
- set(VTK_RENDERING_BACKEND_OPENGL_VERSION "2")
-endif()
-
-list(APPEND NON_PREFIX_PCL_VTK_COMPONENTS Rendering${VTK_RENDERING_BACKEND})
+set(VTK_RENDERING_BACKEND "OpenGL2")
+set(VTK_RENDERING_BACKEND_OPENGL_VERSION "2")
+list(APPEND NON_PREFIX_PCL_VTK_COMPONENTS Rendering${VTK_RENDERING_BACKEND} RenderingContext${VTK_RENDERING_BACKEND})
#Append vtk to components if version is <9.0
if(VTK_VERSION VERSION_LESS 9.0)
checkVTKComponents(COMPONENTS ${PCL_VTK_COMPONENTS} MISSING_COMPONENTS vtkMissingComponents)
if (vtkMissingComponents)
- set(VTK_FOUND FALSE)
- message(WARNING "Missing vtk modules: ${vtkMissingComponents}")
+ message(FATAL_ERROR "Missing vtk modules: ${vtkMissingComponents}")
endif()
if("vtkGUISupportQt" IN_LIST VTK_MODULES_ENABLED)
# they are not being built.
# _var The cumulative build variable. This will be set to FALSE if the
# dependencies are not met.
-# _name The name of the subsystem.
# ARGN The subsystems and external libraries to depend on.
-macro(PCL_SUBSYS_DEPEND _var _name)
+macro(PCL_SUBSYS_DEPEND _var)
set(options)
set(oneValueArgs)
- set(multiValueArgs DEPS EXT_DEPS OPT_DEPS)
- cmake_parse_arguments(SUBSYS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
- if(SUBSYS_DEPS)
- SET_IN_GLOBAL_MAP(PCL_SUBSYS_DEPS ${_name} "${SUBSYS_DEPS}")
+ set(multiValueArgs DEPS EXT_DEPS OPT_DEPS NAME PARENT_NAME)
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_SUBSYS_DEPEND: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT ARGS_NAME)
+ message(FATAL_ERROR "PCL_SUBSYS_DEPEND requires parameter NAME!")
endif()
- if(SUBSYS_EXT_DEPS)
- SET_IN_GLOBAL_MAP(PCL_SUBSYS_EXT_DEPS ${_name} "${SUBSYS_EXT_DEPS}")
+
+ set(_name ${ARGS_NAME})
+ if(ARGS_PARENT_NAME)
+ string(PREPEND _name "${ARGS_PARENT_NAME}_")
+ endif()
+
+ if(ARGS_DEPS)
+ SET_IN_GLOBAL_MAP(PCL_SUBSYS_DEPS ${_name} "${ARGS_DEPS}")
endif()
- if(SUBSYS_OPT_DEPS)
- SET_IN_GLOBAL_MAP(PCL_SUBSYS_OPT_DEPS ${_name} "${SUBSYS_OPT_DEPS}")
+ if(ARGS_EXT_DEPS)
+ SET_IN_GLOBAL_MAP(PCL_SUBSYS_EXT_DEPS ${_name} "${ARGS_EXT_DEPS}")
+ endif()
+ if(ARGS_OPT_DEPS)
+ SET_IN_GLOBAL_MAP(PCL_SUBSYS_OPT_DEPS ${_name} "${ARGS_OPT_DEPS}")
endif()
GET_IN_MAP(subsys_status PCL_SUBSYS_HYPERSTATUS ${_name})
if(${_var} AND (NOT ("${subsys_status}" STREQUAL "AUTO_OFF")))
- if(SUBSYS_DEPS)
- foreach(_dep ${SUBSYS_DEPS})
+ if(ARGS_DEPS)
+ foreach(_dep ${ARGS_DEPS})
PCL_GET_SUBSYS_STATUS(_status ${_dep})
if(NOT _status)
set(${_var} FALSE)
endif()
endforeach()
endif()
- if(SUBSYS_EXT_DEPS)
- foreach(_dep ${SUBSYS_EXT_DEPS})
+ if(ARGS_EXT_DEPS)
+ foreach(_dep ${ARGS_EXT_DEPS})
string(TOUPPER "${_dep}_found" EXT_DEP_FOUND)
#Variable EXT_DEP_FOUND expands to ie. QHULL_FOUND which in turn is then used to see if the EXT_DEPS is found.
if(NOT ${EXT_DEP_FOUND})
endif()
endforeach()
endif()
- if(SUBSYS_OPT_DEPS)
- foreach(_dep ${SUBSYS_OPT_DEPS})
+ if(ARGS_OPT_DEPS)
+ foreach(_dep ${ARGS_OPT_DEPS})
PCL_GET_SUBSYS_INCLUDE_DIR(_include_dir ${_dep})
include_directories(${PROJECT_SOURCE_DIR}/${_include_dir}/include)
endforeach()
endif()
endmacro()
-###############################################################################
-# Make one subsystem depend on one or more other subsystems, and disable it if
-# they are not being built.
-# _var The cumulative build variable. This will be set to FALSE if the
-# dependencies are not met.
-# _parent The parent subsystem name.
-# _name The name of the subsubsystem.
-# ARGN The subsystems and external libraries to depend on.
-macro(PCL_SUBSUBSYS_DEPEND _var _parent _name)
- set(options)
- set(parentArg)
- set(nameArg)
- set(multiValueArgs DEPS EXT_DEPS OPT_DEPS)
- cmake_parse_arguments(SUBSYS "${options}" "${parentArg}" "${nameArg}" "${multiValueArgs}" ${ARGN})
- if(SUBSUBSYS_DEPS)
- SET_IN_GLOBAL_MAP(PCL_SUBSYS_DEPS ${_parent}_${_name} "${SUBSUBSYS_DEPS}")
- endif()
- if(SUBSUBSYS_EXT_DEPS)
- SET_IN_GLOBAL_MAP(PCL_SUBSYS_EXT_DEPS ${_parent}_${_name} "${SUBSUBSYS_EXT_DEPS}")
- endif()
- if(SUBSUBSYS_OPT_DEPS)
- SET_IN_GLOBAL_MAP(PCL_SUBSYS_OPT_DEPS ${_parent}_${_name} "${SUBSUBSYS_OPT_DEPS}")
- endif()
- GET_IN_MAP(subsys_status PCL_SUBSYS_HYPERSTATUS ${_parent}_${_name})
- if(${_var} AND (NOT ("${subsys_status}" STREQUAL "AUTO_OFF")))
- if(SUBSUBSYS_DEPS)
- foreach(_dep ${SUBSUBSYS_DEPS})
- PCL_GET_SUBSYS_STATUS(_status ${_dep})
- if(NOT _status)
- set(${_var} FALSE)
- PCL_SET_SUBSYS_STATUS(${_parent}_${_name} FALSE "Requires ${_dep}.")
- else()
- PCL_GET_SUBSYS_INCLUDE_DIR(_include_dir ${_dep})
- include_directories(${PROJECT_SOURCE_DIR}/${_include_dir}/include)
- endif()
- endforeach()
- endif()
- if(SUBSUBSYS_EXT_DEPS)
- foreach(_dep ${SUBSUBSYS_EXT_DEPS})
- string(TOUPPER "${_dep}_found" EXT_DEP_FOUND)
- if(NOT ${EXT_DEP_FOUND})
- set(${_var} FALSE)
- PCL_SET_SUBSYS_STATUS(${_parent}_${_name} FALSE "Requires external library ${_dep}.")
- endif()
- endforeach()
- endif()
- endif()
-endmacro()
-
###############################################################################
# Adds version information to executable/library in form of a version.rc. This works only with MSVC.
#
set(options)
set(oneValueArgs COMPONENT)
set(multiValueArgs SOURCES)
- cmake_parse_arguments(ADD_LIBRARY_OPTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_ADD_LIBRARY: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT ARGS_COMPONENT)
+ message(FATAL_ERROR "PCL_ADD_LIBRARY requires parameter COMPONENT.")
+ endif()
- add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES})
+ add_library(${_name} ${PCL_LIB_TYPE} ${ARGS_SOURCES})
PCL_ADD_VERSION_INFO(${_name})
target_compile_features(${_name} PUBLIC ${PCL_CXX_COMPILE_FEATURES})
endif()
if((UNIX AND NOT ANDROID) OR MINGW)
- target_link_libraries(${_name} m)
+ target_link_libraries(${_name} m ${ATOMIC_LIBRARY})
endif()
if(MINGW)
set_target_properties(${_name} PROPERTIES FOLDER "Libraries")
install(TARGETS ${_name}
- 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})
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT pcl_${ARGS_COMPONENT}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR} COMPONENT pcl_${ARGS_COMPONENT}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT pcl_${ARGS_COMPONENT})
# Copy PDB if available
- if(MSVC AND PCL_SHARED_LIBS)
+ if(MSVC AND ${PCL_LIB_TYPE} EQUAL "SHARED")
install(FILES $<TARGET_PDB_FILE:${_name}> DESTINATION ${BIN_INSTALL_DIR} OPTIONAL)
endif()
endfunction()
set(options)
set(oneValueArgs COMPONENT)
set(multiValueArgs SOURCES)
- cmake_parse_arguments(ADD_LIBRARY_OPTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_CUDA_ADD_LIBRARY: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT ARGS_COMPONENT)
+ message(FATAL_ERROR "PCL_CUDA_ADD_LIBRARY requires parameter COMPONENT.")
+ endif()
REMOVE_VTK_DEFINITIONS()
- add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES})
+ add_library(${_name} ${PCL_LIB_TYPE} ${ARGS_SOURCES})
PCL_ADD_VERSION_INFO(${_name})
target_include_directories(${_name} PRIVATE ${CUDA_TOOLKIT_INCLUDE})
+ if(MSVC)
+ target_link_libraries(${_name} delayimp.lib) # because delay load is enabled for openmp.dll
+ endif()
+
set_target_properties(${_name} PROPERTIES
VERSION ${PCL_VERSION}
- SOVERSION ${PCL_VERSION_MAJOR}
+ SOVERSION ${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}
DEFINE_SYMBOL "PCLAPI_EXPORTS")
set_target_properties(${_name} PROPERTIES FOLDER "Libraries")
install(TARGETS ${_name}
- 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})
+ RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT pcl_${ARGS_COMPONENT}
+ LIBRARY DESTINATION ${LIB_INSTALL_DIR} COMPONENT pcl_${ARGS_COMPONENT}
+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT pcl_${ARGS_COMPONENT})
endfunction()
###############################################################################
set(options BUNDLE)
set(oneValueArgs COMPONENT)
set(multiValueArgs SOURCES)
- cmake_parse_arguments(ADD_LIBRARY_OPTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_ADD_EXECUTABLE: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT ARGS_COMPONENT)
+ message(FATAL_ERROR "PCL_ADD_EXECUTABLE requires parameter COMPONENT.")
+ endif()
- if(ADD_LIBRARY_OPTION_BUNDLE AND APPLE AND VTK_USE_COCOA)
- add_executable(${_name} MACOSX_BUNDLE ${ADD_LIBRARY_OPTION_SOURCES})
+ if(ARGS_BUNDLE AND APPLE AND VTK_USE_COCOA)
+ add_executable(${_name} MACOSX_BUNDLE ${ARGS_SOURCES})
else()
- add_executable(${_name} ${ADD_LIBRARY_OPTION_SOURCES})
+ add_executable(${_name} ${ARGS_SOURCES})
endif()
PCL_ADD_VERSION_INFO(${_name})
-
+
target_link_libraries(${_name} Threads::Threads)
if(WIN32 AND MSVC)
# Some app targets report are defined with subsys other than apps
# It's simpler check for tools and assume everythin else as an app
- if(${ADD_LIBRARY_OPTION_COMPONENT} STREQUAL "tools")
+ if(${ARGS_COMPONENT} STREQUAL "tools")
set_target_properties(${_name} PROPERTIES FOLDER "Tools")
else()
set_target_properties(${_name} PROPERTIES FOLDER "Apps")
set(PCL_EXECUTABLES ${PCL_EXECUTABLES} ${_name})
- if(ADD_LIBRARY_OPTION_BUNDLE AND APPLE AND VTK_USE_COCOA)
- install(TARGETS ${_name} BUNDLE DESTINATION ${BIN_INSTALL_DIR} COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT})
+ if(ARGS_BUNDLE AND APPLE AND VTK_USE_COCOA)
+ install(TARGETS ${_name} BUNDLE DESTINATION ${BIN_INSTALL_DIR} COMPONENT pcl_${ARGS_COMPONENT})
else()
- install(TARGETS ${_name} RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT})
+ install(TARGETS ${_name} RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT pcl_${ARGS_COMPONENT})
endif()
- string(TOUPPER ${ADD_LIBRARY_OPTION_COMPONENT} _component_upper)
+ string(TOUPPER ${ARGS_COMPONENT} _component_upper)
set(PCL_${_component_upper}_ALL_TARGETS ${PCL_${_component_upper}_ALL_TARGETS} ${_name} PARENT_SCOPE)
endfunction()
set(options)
set(oneValueArgs COMPONENT)
set(multiValueArgs SOURCES)
- cmake_parse_arguments(ADD_LIBRARY_OPTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_CUDA_ADD_EXECUTABLE: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT ARGS_COMPONENT)
+ message(FATAL_ERROR "PCL_CUDA_ADD_EXECUTABLE requires parameter COMPONENT.")
+ endif()
REMOVE_VTK_DEFINITIONS()
-
- add_executable(${_name} ${ADD_LIBRARY_OPTION_SOURCES})
-
+
+ add_executable(${_name} ${ARGS_SOURCES})
+
PCL_ADD_VERSION_INFO(${_name})
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(PCL_EXECUTABLES ${PCL_EXECUTABLES} ${_name})
install(TARGETS ${_name} RUNTIME DESTINATION ${BIN_INSTALL_DIR}
- COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT})
+ COMPONENT pcl_${ARGS_COMPONENT})
endfunction()
###############################################################################
set(options)
set(oneValueArgs)
set(multiValueArgs FILES ARGUMENTS LINK_WITH)
- cmake_parse_arguments(PCL_ADD_TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
- add_executable(${_exename} ${PCL_ADD_TEST_FILES})
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_ADD_TEST: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ add_executable(${_exename} ${ARGS_FILES})
if(NOT WIN32)
set_target_properties(${_exename} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif()
- #target_link_libraries(${_exename} ${GTEST_BOTH_LIBRARIES} ${PCL_ADD_TEST_LINK_WITH})
- target_link_libraries(${_exename} ${PCL_ADD_TEST_LINK_WITH} ${CLANG_LIBRARIES})
+ #target_link_libraries(${_exename} ${GTEST_BOTH_LIBRARIES} ${ARGS_LINK_WITH})
+ target_link_libraries(${_exename} ${ARGS_LINK_WITH} ${CLANG_LIBRARIES})
- target_link_libraries(${_exename} Threads::Threads)
+ target_link_libraries(${_exename} Threads::Threads ${ATOMIC_LIBRARY})
#Only applies to MSVC
if(MSVC)
SET (ArgumentWarningShown TRUE PARENT_SCOPE)
else()
#Only add if there are arguments to test
- if(PCL_ADD_TEST_ARGUMENTS)
- string (REPLACE ";" " " PCL_ADD_TEST_ARGUMENTS_STR "${PCL_ADD_TEST_ARGUMENTS}")
- set_target_properties(${_exename} PROPERTIES VS_DEBUGGER_COMMAND_ARGUMENTS ${PCL_ADD_TEST_ARGUMENTS_STR})
+ if(ARGS_ARGUMENTS)
+ string (REPLACE ";" " " ARGS_ARGUMENTS_STR "${ARGS_ARGUMENTS}")
+ set_target_properties(${_exename} PROPERTIES VS_DEBUGGER_COMMAND_ARGUMENTS ${ARGS_ARGUMENTS_STR})
endif()
endif()
endif()
set_target_properties(${_exename} PROPERTIES FOLDER "Tests")
- add_test(NAME ${_name} COMMAND ${_exename} ${PCL_ADD_TEST_ARGUMENTS})
+ add_test(NAME ${_name} COMMAND ${_exename} ${ARGS_ARGUMENTS})
add_dependencies(tests ${_exename})
endmacro()
set(options)
set(oneValueArgs)
set(multiValueArgs FILES ARGUMENTS LINK_WITH)
- cmake_parse_arguments(PCL_ADD_BENCHMARK "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_ADD_BENCHMARK: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
- add_executable(benchmark_${_name} ${PCL_ADD_BENCHMARK_FILES})
+ add_executable(benchmark_${_name} ${ARGS_FILES})
set_target_properties(benchmark_${_name} PROPERTIES FOLDER "Benchmarks")
- target_link_libraries(benchmark_${_name} benchmark::benchmark ${PCL_ADD_BENCHMARK_LINK_WITH})
+ target_link_libraries(benchmark_${_name} benchmark::benchmark ${ARGS_LINK_WITH})
set_target_properties(benchmark_${_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
-
+
+ # See https://github.com/google/benchmark/issues/1457
+ if(BenchmarkBuildType STREQUAL "STATIC_LIBRARY" AND benchmark_VERSION STREQUAL "1.7.0")
+ target_compile_definitions(benchmark_${_name} PUBLIC -DBENCHMARK_STATIC_DEFINE)
+ endif()
+
#Only applies to MSVC
if(MSVC)
#Requires CMAKE version 3.13.0
set_target_properties(run_benchmarks PROPERTIES PCL_BENCHMARK_ARGUMENTS_WARNING_SHOWN TRUE)
else()
#Only add if there are arguments to test
- if(PCL_ADD_BENCHMARK_ARGUMENTS)
- string (REPLACE ";" " " PCL_ADD_BENCHMARK_ARGUMENTS_STR "${PCL_ADD_BENCHMARK_ARGUMENTS}")
- set_target_properties(benchmark_${_name} PROPERTIES VS_DEBUGGER_COMMAND_ARGUMENTS ${PCL_ADD_BENCHMARK_ARGUMENTS_STR})
+ if(ARGS_ARGUMENTS)
+ string (REPLACE ";" " " ARGS_ARGUMENTS_STR "${ARGS_ARGUMENTS}")
+ set_target_properties(benchmark_${_name} PROPERTIES VS_DEBUGGER_COMMAND_ARGUMENTS ${ARGS_ARGUMENTS_STR})
endif()
endif()
endif()
-
- add_custom_target(run_benchmark_${_name} benchmark_${_name} ${PCL_ADD_BENCHMARK_ARGUMENTS})
+
+ add_custom_target(run_benchmark_${_name} benchmark_${_name} ${ARGS_ARGUMENTS})
set_target_properties(run_benchmark_${_name} PROPERTIES FOLDER "Benchmarks")
-
+
add_dependencies(run_benchmarks run_benchmark_${_name})
endfunction()
set(options)
set(oneValueArgs)
set(multiValueArgs FILES LINK_WITH)
- cmake_parse_arguments(PCL_ADD_EXAMPLE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
- add_executable(${_name} ${PCL_ADD_EXAMPLE_FILES})
- target_link_libraries(${_name} ${PCL_ADD_EXAMPLE_LINK_WITH} ${CLANG_LIBRARIES})
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_ADD_EXAMPLE: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ add_executable(${_name} ${ARGS_FILES})
+ target_link_libraries(${_name} ${ARGS_LINK_WITH} ${CLANG_LIBRARIES})
if(WIN32 AND MSVC)
set_target_properties(${_name} PROPERTIES DEBUG_OUTPUT_NAME ${_name}${CMAKE_DEBUG_POSTFIX}
RELEASE_OUTPUT_NAME ${_name}${CMAKE_RELEASE_POSTFIX})
set(options HEADER_ONLY)
set(oneValueArgs COMPONENT DESC CFLAGS LIB_FLAGS)
set(multiValueArgs PCL_DEPS INT_DEPS EXT_DEPS)
- cmake_parse_arguments(PKGCONFIG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments given to PCL_MAKE_PKGCONFIG: ${ARGS_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT ARGS_COMPONENT)
+ message(FATAL_ERROR "PCL_MAKE_PKGCONFIG requires parameter COMPONENT.")
+ endif()
set(PKG_NAME ${_name})
- set(PKG_DESC ${PKGCONFIG_DESC})
- set(PKG_CFLAGS ${PKGCONFIG_CFLAGS})
- set(PKG_LIBFLAGS ${PKGCONFIG_LIB_FLAGS})
- LIST_TO_STRING(PKG_EXTERNAL_DEPS "${PKGCONFIG_EXT_DEPS}")
- foreach(_dep ${PKGCONFIG_PCL_DEPS})
- string(APPEND PKG_EXTERNAL_DEPS " pcl_${_dep}-${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}")
+ set(PKG_DESC ${ARGS_DESC})
+ set(PKG_CFLAGS ${ARGS_CFLAGS})
+ set(PKG_LIBFLAGS ${ARGS_LIB_FLAGS})
+ LIST_TO_STRING(PKG_EXTERNAL_DEPS "${ARGS_EXT_DEPS}")
+ foreach(_dep ${ARGS_PCL_DEPS})
+ string(APPEND PKG_EXTERNAL_DEPS " pcl_${_dep}")
endforeach()
set(PKG_INTERNAL_DEPS "")
- foreach(_dep ${PKGCONFIG_INT_DEPS})
+ foreach(_dep ${ARGS_INT_DEPS})
string(APPEND PKG_INTERNAL_DEPS " -l${_dep}")
endforeach()
- set(_pc_file ${CMAKE_CURRENT_BINARY_DIR}/${_name}-${PCL_VERSION_MAJOR}.${PCL_VERSION_MINOR}.pc)
- if(PKGCONFIG_HEADER_ONLY)
+ set(_pc_file ${CMAKE_CURRENT_BINARY_DIR}/${_name}.pc)
+ if(ARGS_HEADER_ONLY)
configure_file(${PROJECT_SOURCE_DIR}/cmake/pkgconfig-headeronly.cmake.in ${_pc_file} @ONLY)
else()
configure_file(${PROJECT_SOURCE_DIR}/cmake/pkgconfig.cmake.in ${_pc_file} @ONLY)
endif()
install(FILES ${_pc_file}
DESTINATION ${PKGCFG_INSTALL_DIR}
- COMPONENT pcl_${PKGCONFIG_COMPONENT})
+ COMPONENT pcl_${ARGS_COMPONENT})
endfunction()
###############################################################################
macro(PCL_SET_TEST_DEPENDENCIES _var _module)
set(${_var} global_tests ${_module} ${PCL_SUBSYS_DEPS_${_module}})
endmacro()
+
+###############################################################################
+# Add two test targets for both values of PCL_RUN_TESTS_AT_COMPILE_TIME
+# boolean flag, binaries produced are named with "_runtime" and "_compiletime"
+# for false and true values accordingly.
+# _name The test name.
+# _exename The exe name.
+# ARGN :
+# see PCL_ADD_TEST documentation
+macro (PCL_ADD_COMPILETIME_AND_RUNTIME_TEST _name _exename)
+ PCL_ADD_TEST("${_name}_runtime" "${_exename}_runtime" ${ARGN})
+ target_compile_definitions("${_exename}_runtime" PRIVATE PCL_RUN_TESTS_AT_COMPILE_TIME=false)
+ PCL_ADD_TEST("${_name}_compiletime" "${_exename}_compiletime" ${ARGN})
+ target_compile_definitions("${_exename}_compiletime" PRIVATE PCL_RUN_TESTS_AT_COMPILE_TIME=true)
+endmacro()
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS eigen boost)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS eigen boost)
PCL_ADD_DOC("${SUBSYS_NAME}")
target_compile_definitions(${LIB_NAME} PUBLIC _ENABLE_EXTENDED_ALIGNED_STORAGE)
endif()
-PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC})
+set(EXT_DEPS eigen3)
+PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} EXT_DEPS ${EXT_DEPS})
# Install include files
PCL_ADD_INCLUDES("${SUBSYS_NAME}" "" ${incs})
{
struct ModelCoefficients
{
- ModelCoefficients ()
- {
- }
+ ModelCoefficients () = default;
::pcl::PCLHeader header;
{
return (PCLPointCloud2 (*this) += rhs);
}
+
+ /** \brief Get value at specified offset.
+ * \param[in] point_index point index.
+ * \param[in] field_offset offset.
+ * \return value at the given offset.
+ */
+ template<typename T> inline
+ const T& at(const pcl::uindex_t& point_index, const pcl::uindex_t& field_offset) const {
+ const auto position = point_index * point_step + field_offset;
+ if (data.size () >= (position + sizeof(T)))
+ return reinterpret_cast<const T&>(data[position]);
+ else
+ throw std::out_of_range("PCLPointCloud2::at");
+ }
+
+ /** \brief Get value at specified offset.
+ * \param[in] point_index point index.
+ * \param[in] field_offset offset.
+ * \return value at the given offset.
+ */
+ template<typename T> inline
+ T& at(const pcl::uindex_t& point_index, const pcl::uindex_t& field_offset) {
+ const auto position = point_index * point_step + field_offset;
+ if (data.size () >= (position + sizeof(T)))
+ return reinterpret_cast<T&>(data[position]);
+ else
+ throw std::out_of_range("PCLPointCloud2::at");
+ }
}; // struct PCLPointCloud2
using PCLPointCloud2Ptr = PCLPointCloud2::Ptr;
std::uint8_t datatype = 0;
uindex_t count = 0;
- enum PointFieldTypes { INT8 = traits::asEnum_v<std::int8_t>,
+ enum PointFieldTypes { BOOL = traits::asEnum_v<bool>,
+ INT8 = traits::asEnum_v<std::int8_t>,
UINT8 = traits::asEnum_v<std::uint8_t>,
INT16 = traits::asEnum_v<std::int16_t>,
UINT16 = traits::asEnum_v<std::uint16_t>,
INT32 = traits::asEnum_v<std::int32_t>,
UINT32 = traits::asEnum_v<std::uint32_t>,
+ INT64 = traits::asEnum_v<std::int64_t>,
+ UINT64 = traits::asEnum_v<std::uint64_t>,
FLOAT32 = traits::asEnum_v<float>,
FLOAT64 = traits::asEnum_v<double>};
s << "offset: ";
s << " " << v.offset << std::endl;
s << "datatype: ";
- s << " " << v.datatype << std::endl;
+ switch(v.datatype) {
+ case ::pcl::PCLPointField::PointFieldTypes::INT8: s << " INT8" << std::endl; break;
+ case ::pcl::PCLPointField::PointFieldTypes::UINT8: s << " UINT8" << std::endl; break;
+ case ::pcl::PCLPointField::PointFieldTypes::INT16: s << " INT16" << std::endl; break;
+ case ::pcl::PCLPointField::PointFieldTypes::UINT16: s << " UINT16" << std::endl; break;
+ case ::pcl::PCLPointField::PointFieldTypes::INT32: s << " INT32" << std::endl; break;
+ case ::pcl::PCLPointField::PointFieldTypes::UINT32: s << " UINT32" << std::endl; break;
+ case ::pcl::PCLPointField::PointFieldTypes::FLOAT32: s << " FLOAT32" << std::endl; break;
+ case ::pcl::PCLPointField::PointFieldTypes::FLOAT64: s << " FLOAT64" << std::endl; break;
+ default: s << " " << static_cast<int>(v.datatype) << std::endl;
+ }
s << "count: ";
s << " " << v.count << std::endl;
return (s);
using Ptr = shared_ptr< ::pcl::PointIndices>;
using ConstPtr = shared_ptr<const ::pcl::PointIndices>;
- PointIndices ()
- {}
+ PointIndices () = default;
::pcl::PCLHeader header;
{
struct PolygonMesh
{
- PolygonMesh ()
- {}
+ PolygonMesh () = default;
::pcl::PCLHeader header;
return true;
}
- /** \brief Concatenate two pcl::PCLPointCloud2
+ /** \brief Concatenate two pcl::PolygonMesh
* \param[in] mesh1 the first input mesh
* \param[in] mesh2 the second input mesh
* \param[out] mesh_out the resultant output mesh
pcl::PCLHeader header;
- std::vector<std::vector<pcl::Vertices> > tex_polygons; // polygon which is mapped with specific texture defined in TexMaterial
- std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > tex_coordinates; // UV coordinates
- std::vector<pcl::TexMaterial> tex_materials; // define texture material
+ /** \brief polygon which is mapped with specific texture defined in TexMaterial */
+ std::vector<std::vector<pcl::Vertices> > tex_polygons;
+ /** \brief UV coordinates */
+ std::vector<std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> > > tex_coordinates;
+ /** \brief define texture material */
+ std::vector<pcl::TexMaterial> tex_materials;
+ /** \brief Specifies which texture coordinates from tex_coordinates each polygon/face uses.
+ * The vectors must have the same sizes as in tex_polygons, but the pcl::Vertices
+ * may be empty for those polygons/faces that do not use coordinates.
+ */
+ std::vector<std::vector<pcl::Vertices> > tex_coord_indices;
public:
using Ptr = shared_ptr<pcl::TextureMesh>;
*/
struct Vertices
{
- Vertices ()
- {}
+ Vertices () = default;
Indices vertices;
class Iterator
{
public:
- virtual ~Iterator () {}
+ virtual ~Iterator () = default;
virtual void operator ++ () = 0;
class Iterator
{
public:
- virtual ~Iterator () {}
+ virtual ~Iterator () = default;
virtual void operator ++ () = 0;
* \ingroup common
*/
template<typename IteratorT, typename Functor> inline auto
- computeMedian (IteratorT begin, IteratorT end, Functor f) noexcept -> typename std::result_of<Functor(decltype(*begin))>::type
+ computeMedian (IteratorT begin, IteratorT end, Functor f) noexcept ->
+ #if __cpp_lib_is_invocable
+ std::invoke_result_t<Functor, decltype(*begin)>
+ #else
+ std::result_of_t<Functor(decltype(*begin))>
+ #endif
{
const std::size_t size = std::distance(begin, end);
const std::size_t mid = size/2;
#pragma once
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-
#include <pcl/pcl_exports.h>
+#include <math.h> // NOLINT
+#include <stdio.h> // NOLINT
+#include <stdlib.h> // NOLINT
+#include <string.h> // NOLINT
+
#ifdef __cplusplus
extern "C" {
#endif
# endif
#endif
-typedef struct {
+typedef struct { // NOLINT
kiss_fft_scalar r;
kiss_fft_scalar i;
}kiss_fft_cpx;
-typedef struct kiss_fft_state* kiss_fft_cfg;
+typedef struct kiss_fft_state* kiss_fft_cfg; // NOLINT
/*
* kiss_fft_alloc
*/
-typedef struct kiss_fftr_state *kiss_fftr_cfg;
+typedef struct kiss_fftr_state *kiss_fftr_cfg; // NOLINT
kiss_fftr_cfg PCL_EXPORTS kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem);
compute3DCentroid (ConstCloudIterator<PointT> &cloud_iterator,
Eigen::Matrix<Scalar, 4, 1> ¢roid)
{
- // Initialize to 0
- centroid.setZero ();
+ Eigen::Matrix<Scalar, 4, 1> accumulator {0, 0, 0, 0};
- unsigned cp = 0;
+ unsigned int cp = 0;
// For each point in the cloud
// If the data is dense, we don't need to check for NaN
// Check if the point is invalid
if (pcl::isFinite (*cloud_iterator))
{
- centroid[0] += cloud_iterator->x;
- centroid[1] += cloud_iterator->y;
- centroid[2] += cloud_iterator->z;
+ accumulator[0] += cloud_iterator->x;
+ accumulator[1] += cloud_iterator->y;
+ accumulator[2] += cloud_iterator->z;
++cp;
}
++cloud_iterator;
}
- centroid /= static_cast<Scalar> (cp);
- centroid[3] = 1;
+
+ if (cp > 0) {
+ centroid = accumulator;
+ centroid /= static_cast<Scalar> (cp);
+ centroid[3] = 1;
+ }
return (cp);
}
if (cloud.empty ())
return (0);
- // Initialize to 0
- centroid.setZero ();
// For each point in the cloud
// If the data is dense, we don't need to check for NaN
if (cloud.is_dense)
{
+ // Initialize to 0
+ centroid.setZero ();
for (const auto& point: cloud)
{
centroid[0] += point.x;
return (static_cast<unsigned int> (cloud.size ()));
}
// NaN or Inf values could exist => check for them
- unsigned cp = 0;
+ unsigned int cp = 0;
+ Eigen::Matrix<Scalar, 4, 1> accumulator {0, 0, 0, 0};
for (const auto& point: cloud)
{
// Check if the point is invalid
if (!isFinite (point))
continue;
- centroid[0] += point.x;
- centroid[1] += point.y;
- centroid[2] += point.z;
+ accumulator[0] += point.x;
+ accumulator[1] += point.y;
+ accumulator[2] += point.z;
++cp;
}
- centroid /= static_cast<Scalar> (cp);
- centroid[3] = 1;
+ if (cp > 0) {
+ centroid = accumulator;
+ centroid /= static_cast<Scalar> (cp);
+ centroid[3] = 1;
+ }
return (cp);
}
if (indices.empty ())
return (0);
- // Initialize to 0
- centroid.setZero ();
// If the data is dense, we don't need to check for NaN
if (cloud.is_dense)
{
+ // Initialize to 0
+ centroid.setZero ();
for (const auto& index : indices)
{
centroid[0] += cloud[index].x;
return (static_cast<unsigned int> (indices.size ()));
}
// NaN or Inf values could exist => check for them
- unsigned cp = 0;
+ Eigen::Matrix<Scalar, 4, 1> accumulator {0, 0, 0, 0};
+ unsigned int cp = 0;
for (const auto& index : indices)
{
// Check if the point is invalid
if (!isFinite (cloud [index]))
continue;
- centroid[0] += cloud[index].x;
- centroid[1] += cloud[index].y;
- centroid[2] += cloud[index].z;
+ accumulator[0] += cloud[index].x;
+ accumulator[1] += cloud[index].y;
+ accumulator[2] += cloud[index].z;
++cp;
}
- centroid /= static_cast<Scalar> (cp);
- centroid[3] = 1;
+ if (cp > 0) {
+ centroid = accumulator;
+ centroid /= static_cast<Scalar> (cp);
+ centroid[3] = 1;
+ }
return (cp);
}
if (cloud.empty ())
return (0);
- // Initialize to 0
- covariance_matrix.setZero ();
-
unsigned point_count;
// If the data is dense, we don't need to check for NaN
if (cloud.is_dense)
{
+ covariance_matrix.setZero ();
point_count = static_cast<unsigned> (cloud.size ());
// For each point in the cloud
for (const auto& point: cloud)
// NaN or Inf values could exist => check for them
else
{
+ Eigen::Matrix<Scalar, 3, 3> temp_covariance_matrix;
+ temp_covariance_matrix.setZero();
point_count = 0;
// For each point in the cloud
for (const auto& point: cloud)
pt[1] = point.y - centroid[1];
pt[2] = point.z - centroid[2];
- covariance_matrix (1, 1) += pt.y () * pt.y ();
- covariance_matrix (1, 2) += pt.y () * pt.z ();
+ temp_covariance_matrix (1, 1) += pt.y () * pt.y ();
+ temp_covariance_matrix (1, 2) += pt.y () * pt.z ();
- covariance_matrix (2, 2) += pt.z () * pt.z ();
+ temp_covariance_matrix (2, 2) += pt.z () * pt.z ();
pt *= pt.x ();
- covariance_matrix (0, 0) += pt.x ();
- covariance_matrix (0, 1) += pt.y ();
- covariance_matrix (0, 2) += pt.z ();
+ temp_covariance_matrix (0, 0) += pt.x ();
+ temp_covariance_matrix (0, 1) += pt.y ();
+ temp_covariance_matrix (0, 2) += pt.z ();
++point_count;
}
+ if (point_count > 0) {
+ covariance_matrix = temp_covariance_matrix;
+ }
+ }
+ if (point_count == 0) {
+ return 0;
}
covariance_matrix (1, 0) = covariance_matrix (0, 1);
covariance_matrix (2, 0) = covariance_matrix (0, 2);
if (indices.empty ())
return (0);
- // Initialize to 0
- covariance_matrix.setZero ();
-
std::size_t point_count;
// If the data is dense, we don't need to check for NaN
if (cloud.is_dense)
{
+ covariance_matrix.setZero ();
point_count = indices.size ();
// For each point in the cloud
for (const auto& idx: indices)
// NaN or Inf values could exist => check for them
else
{
+ Eigen::Matrix<Scalar, 3, 3> temp_covariance_matrix;
+ temp_covariance_matrix.setZero ();
point_count = 0;
// For each point in the cloud
for (const auto &index : indices)
pt[1] = cloud[index].y - centroid[1];
pt[2] = cloud[index].z - centroid[2];
- covariance_matrix (1, 1) += pt.y () * pt.y ();
- covariance_matrix (1, 2) += pt.y () * pt.z ();
+ temp_covariance_matrix (1, 1) += pt.y () * pt.y ();
+ temp_covariance_matrix (1, 2) += pt.y () * pt.z ();
- covariance_matrix (2, 2) += pt.z () * pt.z ();
+ temp_covariance_matrix (2, 2) += pt.z () * pt.z ();
pt *= pt.x ();
- covariance_matrix (0, 0) += pt.x ();
- covariance_matrix (0, 1) += pt.y ();
- covariance_matrix (0, 2) += pt.z ();
+ temp_covariance_matrix (0, 0) += pt.x ();
+ temp_covariance_matrix (0, 1) += pt.y ();
+ temp_covariance_matrix (0, 2) += pt.z ();
++point_count;
}
+ if (point_count > 0) {
+ covariance_matrix = temp_covariance_matrix;
+ }
+ }
+ if (point_count == 0) {
+ return 0;
}
covariance_matrix (1, 0) = covariance_matrix (0, 1);
covariance_matrix (2, 0) = covariance_matrix (0, 2);
#include <pcl/point_types.h>
#include <pcl/common/common.h>
-#include <cfloat> // for FLT_MAX
+#include <limits>
//////////////////////////////////////////////////////////////////////////////////////////////
inline double
template<typename PointT> inline void
pcl::getMaxDistance (const pcl::PointCloud<PointT> &cloud, const Eigen::Vector4f &pivot_pt, Eigen::Vector4f &max_pt)
{
- float max_dist = -FLT_MAX;
+ float max_dist = std::numeric_limits<float>::lowest();
int max_idx = -1;
float dist;
const Eigen::Vector3f pivot_pt3 = pivot_pt.head<3> ();
pcl::getMaxDistance (const pcl::PointCloud<PointT> &cloud, const Indices &indices,
const Eigen::Vector4f &pivot_pt, Eigen::Vector4f &max_pt)
{
- float max_dist = -FLT_MAX;
+ float max_dist = std::numeric_limits<float>::lowest();
int max_idx = -1;
float dist;
const Eigen::Vector3f pivot_pt3 = pivot_pt.head<3> ();
template <typename PointT> inline void
pcl::getMinMax3D (const pcl::PointCloud<PointT> &cloud, Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt)
{
- min_pt.setConstant (FLT_MAX);
- max_pt.setConstant (-FLT_MAX);
+ min_pt.setConstant (std::numeric_limits<float>::max());
+ max_pt.setConstant (std::numeric_limits<float>::lowest());
// If the data is dense, we don't need to check for NaN
if (cloud.is_dense)
pcl::getMinMax3D (const pcl::PointCloud<PointT> &cloud, const Indices &indices,
Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt)
{
- min_pt.setConstant (FLT_MAX);
- max_pt.setConstant (-FLT_MAX);
+ min_pt.setConstant (std::numeric_limits<float>::max());
+ max_pt.setConstant (std::numeric_limits<float>::lowest());
// If the data is dense, we don't need to check for NaN
if (cloud.is_dense)
template <typename PointT> inline void
pcl::getMinMax (const PointT &histogram, int len, float &min_p, float &max_p)
{
- min_p = FLT_MAX;
- max_p = -FLT_MAX;
+ min_p = std::numeric_limits<float>::max();
+ max_p = std::numeric_limits<float>::lowest();
for (int i = 0; i < len; ++i)
{
#include <pcl/common/concatenate.h>
#include <pcl/common/copy_point.h>
#include <pcl/common/io.h>
-#include <pcl/point_types.h>
-
namespace pcl
{
PointT* out_inner = out + cloud_out.width*top + left;
for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
{
- if (out_inner != in)
- memcpy (out_inner, in, cloud_in.width * sizeof (PointT));
+ if (out_inner != in) {
+ std::copy(in, in + cloud_in.width, out_inner);
+ }
}
}
else
for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
{
- if (out_inner != in)
- memcpy (out_inner, in, cloud_in.width * sizeof (PointT));
+ if (out_inner != in) {
+ std::copy(in, in + cloud_in.width, out_inner);
+ }
for (int j = 0; j < left; j++)
out_inner[j - left] = in[padding[j]];
for (int i = 0; i < top; i++)
{
int j = pcl::interpolatePointIndex (i - top, cloud_in.height, border_type);
- memcpy (out + i*cloud_out.width,
- out + (j+top) * cloud_out.width,
- sizeof (PointT) * cloud_out.width);
+ std::copy(out + (j+top) * cloud_out.width, out + (j+top) * cloud_out.width + cloud_out.width,
+ out + i*cloud_out.width);
}
for (int i = 0; i < bottom; i++)
{
int j = pcl::interpolatePointIndex (i + cloud_in.height, cloud_in.height, border_type);
- memcpy (out + (i + cloud_in.height + top)*cloud_out.width,
- out + (j+top)*cloud_out.width,
- cloud_out.width * sizeof (PointT));
+ std::copy(out + (j+top)*cloud_out.width, out + (j+top)*cloud_out.width + cloud_out.width,
+ out + (i + cloud_in.height + top)*cloud_out.width);
}
}
catch (pcl::BadArgumentException&)
for (std::uint32_t i = 0; i < cloud_in.height; i++, out_inner += cloud_out.width, in += cloud_in.width)
{
- if (out_inner != in)
- memcpy (out_inner, in, cloud_in.width * sizeof (PointT));
+ if (out_inner != in) {
+ std::copy(in, in + cloud_in.width, out_inner);
+ }
- memcpy (out_inner - left, buff_ptr, left * sizeof (PointT));
- memcpy (out_inner + cloud_in.width, buff_ptr, right * sizeof (PointT));
+ std::copy(buff_ptr, buff_ptr + left, out_inner - left);
+ std::copy(buff_ptr, buff_ptr + right, out_inner + cloud_in.width);
}
for (int i = 0; i < top; i++)
{
- memcpy (out + i*cloud_out.width, buff_ptr, cloud_out.width * sizeof (PointT));
+ std::copy(buff_ptr, buff_ptr + cloud_out.width, out + i*cloud_out.width);
}
for (int i = 0; i < bottom; i++)
{
- memcpy (out + (i + cloud_in.height + top)*cloud_out.width,
- buff_ptr,
- cloud_out.width * sizeof (PointT));
+ std::copy(buff_ptr, buff_ptr + cloud_out.width,
+ out + (i + cloud_in.height + top)*cloud_out.width);
}
}
}
for (std::size_t j = 0; j < old_height; ++j)
for(std::size_t i = 0; i < amount; ++i)
{
- typename PointCloud<PointT>::iterator start = output.begin () + (j * new_width);
+ auto start = output.begin () + (j * new_width);
output.insert (start, *start);
start = output.begin () + (j * new_width) + old_width + i;
output.insert (start, *start);
for (std::size_t j = 0; j < old_height; ++j)
for(std::size_t i = 0; i < amount; ++i)
{
- typename PointCloud<PointT>::iterator start = output.begin () + (j * new_width);
+ auto start = output.begin () + (j * new_width);
output.insert (start, *(start + 2*i));
start = output.begin () + (j * new_width) + old_width + 2*i;
output.insert (start+1, *(start - 2*i));
std::uint32_t new_width = old_width - 2 * amount;
for(std::size_t j = 0; j < old_height; j++)
{
- typename PointCloud<PointT>::iterator start = output.begin () + j * new_width;
+ auto start = output.begin () + j * new_width;
output.erase (start, start + amount);
start = output.begin () + (j+1) * new_width;
output.erase (start, start + amount);
}
+inline void
+transformPointCloud(const pcl::PointCloud<pcl::PointXY> &cloud_in,
+ pcl::PointCloud<pcl::PointXY> &cloud_out,
+ const Eigen::Affine2f &transform,
+ bool copy_all_fields)
+ {
+ if (&cloud_in != &cloud_out)
+ {
+ cloud_out.header = cloud_in.header;
+ cloud_out.is_dense = cloud_in.is_dense;
+ cloud_out.reserve (cloud_in.size ());
+ if (copy_all_fields)
+ cloud_out.assign (cloud_in.begin (), cloud_in.end (), cloud_in.width);
+ else
+ cloud_out.resize (cloud_in.width, cloud_in.height);
+ cloud_out.sensor_orientation_ = cloud_in.sensor_orientation_;
+ cloud_out.sensor_origin_ = cloud_in.sensor_origin_;
+ }
+ if(cloud_in.is_dense)
+ {
+ for (std::size_t i = 0; i < cloud_out.size (); ++i)
+ {
+ cloud_out[i].getVector2fMap () = transform * cloud_in[i].getVector2fMap();
+ }
+ }
+ else
+ {
+ for (std::size_t i = 0; i < cloud_out.size (); ++i)
+ {
+ if (!std::isfinite(cloud_in[i].x) || !std::isfinite(cloud_in[i].y))
+ {
+ continue;
+ }
+ cloud_out[i].getVector2fMap () = transform * cloud_in[i].getVector2fMap();
+ }
+ }
+ }
+
+
template <typename PointT, typename Scalar> void
transformPointCloudWithNormals (const pcl::PointCloud<PointT> &cloud_in,
pcl::PointCloud<PointT> &cloud_out,
{
switch (datatype)
{
- case pcl::PCLPointField::INT8:
+ case pcl::PCLPointField::BOOL:
+ return sizeof(bool);
+
+ case pcl::PCLPointField::INT8: PCL_FALLTHROUGH
case pcl::PCLPointField::UINT8:
return (1);
- case pcl::PCLPointField::INT16:
+ case pcl::PCLPointField::INT16: PCL_FALLTHROUGH
case pcl::PCLPointField::UINT16:
return (2);
- case pcl::PCLPointField::INT32:
- case pcl::PCLPointField::UINT32:
+ case pcl::PCLPointField::INT32: PCL_FALLTHROUGH
+ case pcl::PCLPointField::UINT32: PCL_FALLTHROUGH
case pcl::PCLPointField::FLOAT32:
return (4);
+ case pcl::PCLPointField::INT64: PCL_FALLTHROUGH
+ case pcl::PCLPointField::UINT64: PCL_FALLTHROUGH
case pcl::PCLPointField::FLOAT64:
return (8);
/** \brief Obtains the type of the PCLPointField from a specific size and type
* \param[in] size the size in bytes of the data field
- * \param[in] type a char describing the type of the field ('F' = float, 'I' = signed, 'U' = unsigned)
+ * \param[in] type a char describing the type of the field ('B' = bool, 'F' = float, 'I' = signed, 'U' = unsigned)
* \ingroup common
*/
inline int
getFieldType (const int size, char type)
{
type = std::toupper (type, std::locale::classic ());
+
+ // extra logic for bool because its size is undefined
+ if (type == 'B') {
+ if (size == sizeof(bool)) {
+ return pcl::PCLPointField::BOOL;
+ } else {
+ return -1;
+ }
+ }
+
switch (size)
{
case 1:
break;
case 8:
+ if (type == 'I')
+ return (pcl::PCLPointField::INT64);
+ if (type == 'U')
+ return (pcl::PCLPointField::UINT64);
if (type == 'F')
return (pcl::PCLPointField::FLOAT64);
break;
{
switch (type)
{
- case pcl::PCLPointField::INT8:
- case pcl::PCLPointField::INT16:
- case pcl::PCLPointField::INT32:
+ case pcl::PCLPointField::BOOL:
+ return ('B');
+
+ case pcl::PCLPointField::INT8: PCL_FALLTHROUGH
+ case pcl::PCLPointField::INT16: PCL_FALLTHROUGH
+ case pcl::PCLPointField::INT32: PCL_FALLTHROUGH
+ case pcl::PCLPointField::INT64:
return ('I');
- case pcl::PCLPointField::UINT8:
- case pcl::PCLPointField::UINT16:
- case pcl::PCLPointField::UINT32:
+ case pcl::PCLPointField::UINT8: PCL_FALLTHROUGH
+ case pcl::PCLPointField::UINT16: PCL_FALLTHROUGH
+ case pcl::PCLPointField::UINT32: PCL_FALLTHROUGH
+ case pcl::PCLPointField::UINT64:
return ('U');
- case pcl::PCLPointField::FLOAT32:
+ case pcl::PCLPointField::FLOAT32: PCL_FALLTHROUGH
case pcl::PCLPointField::FLOAT64:
return ('F');
+
default:
return ('?');
}
pcl::PCLPointCloud2 &cloud_out);
/** \brief Check if two given point types are the same or not. */
- template <typename Point1T, typename Point2T> inline bool
- isSamePointType ()
+template <typename Point1T, typename Point2T> constexpr bool
+ isSamePointType() noexcept
{
- return (typeid (Point1T) == typeid (Point2T));
+ return (std::is_same<remove_cvref_t<Point1T>, remove_cvref_t<Point2T>>::value);
}
/** \brief Extract the indices of a given point cloud as a new point cloud
{
public:
/** \brief Constructor. */
- StopWatch () : start_time_ (std::chrono::steady_clock::now())
- {
- }
+ StopWatch () = default;
/** \brief Retrieve the time in milliseconds spent since the last call to \a reset(). */
inline double
}
protected:
- std::chrono::time_point<std::chrono::steady_clock> start_time_;
+ std::chrono::time_point<std::chrono::steady_clock> start_time_ = std::chrono::steady_clock::now();
};
/** \brief Class to measure the time spent in a scope
#pragma once
#include <pcl/point_cloud.h>
-#include <pcl/point_types.h>
#include <pcl/common/centroid.h>
#include <pcl/common/eigen.h>
#include <pcl/PointIndices.h>
return (transformPointCloudWithNormals<PointT, float> (cloud_in, cloud_out, offset, rotation, copy_all_fields));
}
+ /** \brief Apply an affine transform on a pointcloud having points of type PointXY
+ * \param[in] cloud_in the input point cloud
+ * \param[out] cloud_out the resultant output point cloud
+ * \param[in] transform an affine transformation
+ * \param[in] copy_all_fields flag that controls whether the contents of the fields
+ * (other than x, y, z) should be copied into the new transformed cloud
+ * \ingroup common
+ */
+ void
+ transformPointCloud(const pcl::PointCloud<pcl::PointXY>& cloud_in,
+ pcl::PointCloud<pcl::PointXY>& cloud_out,
+ const Eigen::Affine2f& transform,
+ bool copy_all_fields = true);
+
/** \brief Transform a point with members x,y,z
* \param[in] point the point to transform
* \param[out] transform the transformation to apply
{
public:
- TicToc () {}
+ TicToc () = default;
void
tic ()
#include <pcl/for_each_type.h>
#include <pcl/console/print.h>
-#include <boost/foreach.hpp>
+#include <algorithm>
+#include <iterator>
namespace pcl
{
// Should usually be able to copy all rows at once
if (msg.row_step == cloud_row_step)
{
- memcpy (cloud_data, msg_data, msg.data.size ());
+ std::copy(msg.data.cbegin(), msg.data.cend(), cloud_data);
}
else
{
const std::uint8_t* msg_data = row_data + col * msg.point_step;
for (const detail::FieldMapping& mapping : field_map)
{
- memcpy (cloud_data + mapping.struct_offset, msg_data + mapping.serialized_offset, mapping.size);
+ std::copy(msg_data + mapping.serialized_offset, msg_data + mapping.serialized_offset + mapping.size,
+ cloud_data + mapping.struct_offset);
}
cloud_data += sizeof (PointT);
}
for (std::size_t x = 0; x < cloud.width; x++, rgb_offset += point_step)
{
std::uint8_t * pixel = &(msg.data[y * msg.step + x * 3]);
- memcpy (pixel, &(cloud.data[rgb_offset]), 3 * sizeof (std::uint8_t));
+ std::copy(&cloud.data[rgb_offset], &cloud.data[rgb_offset] + 3, pixel);
}
}
}
};
/** \brief Standard constructor.
- * Sets \ref index_query to 0, \ref index_match to -1, and \ref distance to FLT_MAX.
+ * Sets \ref index_query to 0, \ref index_match to -1, and \ref distance to std::numeric_limits<float>::max().
*/
inline Correspondence () = default;
{
using arg = typename boost::mpl::deref<Iterator>::type;
-#if (defined _WIN32 && defined _MSC_VER)
+#if (defined _WIN32 && defined _MSC_VER && !defined(__clang__))
boost::mpl::aux::unwrap (f, 0).operator()<arg> ();
#else
boost::mpl::aux::unwrap (f, 0).template operator()<arg> ();
{
}
- ~DefaultIterator ()
- {
- }
+ ~DefaultIterator () = default;
void operator ++ ()
{
{
}
- virtual ~IteratorIdx () {}
+ virtual ~IteratorIdx () = default;
void operator ++ ()
{
{
}
- ~DefaultConstIterator ()
- {
- }
+ ~DefaultConstIterator () override = default;
void operator ++ () override
{
{
}
- ~ConstIteratorIdx () {}
+ ~ConstIteratorIdx () override = default;
void operator ++ () override
{
static constexpr int descriptorSize_v = descriptorSize<FeaturePointT>::value;
}
}
-
+
+ using Vector2fMap = Eigen::Map<Eigen::Vector2f>;
+ using Vector2fMapConst = const Eigen::Map<const Eigen::Vector2f>;
using Array3fMap = Eigen::Map<Eigen::Array3f>;
using Array3fMapConst = const Eigen::Map<const Eigen::Array3f>;
using Array4fMap = Eigen::Map<Eigen::Array4f, Eigen::Aligned>;
};
#define PCL_ADD_EIGEN_MAPS_POINT4D \
+ inline pcl::Vector2fMap getVector2fMap () { return (pcl::Vector2fMap (data)); } \
+ inline pcl::Vector2fMapConst getVector2fMap () const { return (pcl::Vector2fMapConst (data)); } \
inline pcl::Vector3fMap getVector3fMap () { return (pcl::Vector3fMap (data)); } \
inline pcl::Vector3fMapConst getVector3fMap () const { return (pcl::Vector3fMapConst (data)); } \
inline pcl::Vector4fMap getVector4fMap () { return (pcl::Vector4fMap (data)); } \
*/
struct EIGEN_ALIGN16 PointXYZ : public _PointXYZ
{
- inline PointXYZ (const _PointXYZ &p): PointXYZ(p.x, p.y, p.z) {}
+ inline constexpr PointXYZ (const _PointXYZ &p): PointXYZ(p.x, p.y, p.z) {}
- inline PointXYZ (): PointXYZ(0.f, 0.f, 0.f) {}
+ inline constexpr PointXYZ (): PointXYZ(0.f, 0.f, 0.f) {}
- inline PointXYZ (float _x, float _y, float _z)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- }
+ inline constexpr PointXYZ (float _x, float _y, float _z) : _PointXYZ{{{_x, _y, _z, 1.f}}} {}
friend std::ostream& operator << (std::ostream& os, const PointXYZ& p);
PCL_MAKE_ALIGNED_OPERATOR_NEW
*/
struct RGB: public _RGB
{
- inline RGB (const _RGB &p)
- {
- rgba = p.rgba;
- }
+ inline constexpr RGB (const _RGB &p) : RGB{p.r, p.g, p.b, p.a} {}
- inline RGB (): RGB(0, 0, 0) {}
+ inline constexpr RGB (): RGB(0, 0, 0) {}
- inline RGB (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b)
- {
- r = _r; g = _g; b = _b;
- a = 255;
- }
+ inline constexpr RGB (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b, std::uint8_t _a = 255) : _RGB{{{{_b, _g, _r, _a}}}} {}
friend std::ostream& operator << (std::ostream& os, const RGB& p);
};
*/
struct Intensity: public _Intensity
{
- inline Intensity (const _Intensity &p)
- {
- intensity = p.intensity;
- }
+ inline constexpr Intensity (const _Intensity &p) : Intensity{p.intensity} {}
- inline Intensity (float _intensity = 0.f)
- {
- intensity = _intensity;
- }
+ inline constexpr Intensity (float _intensity = 0.f) : _Intensity{_intensity} {}
friend std::ostream& operator << (std::ostream& os, const Intensity& p);
};
*/
struct Intensity8u: public _Intensity8u
{
- inline Intensity8u (const _Intensity8u &p)
- {
- intensity = p.intensity;
- }
+ inline constexpr Intensity8u (const _Intensity8u &p) : Intensity8u{p.intensity} {}
- inline Intensity8u (std::uint8_t _intensity = 0)
- {
- intensity = _intensity;
- }
+ inline constexpr Intensity8u (std::uint8_t _intensity = 0) : _Intensity8u{_intensity} {}
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 1101
- operator unsigned char() const
+ inline constexpr operator unsigned char() const
{
return intensity;
}
*/
struct Intensity32u: public _Intensity32u
{
- inline Intensity32u (const _Intensity32u &p)
- {
- intensity = p.intensity;
- }
+ inline constexpr Intensity32u (const _Intensity32u &p) : Intensity32u{p.intensity} {}
- inline Intensity32u (std::uint32_t _intensity = 0)
- {
- intensity = _intensity;
- }
+ inline constexpr Intensity32u (std::uint32_t _intensity = 0) : _Intensity32u{_intensity} {}
friend std::ostream& operator << (std::ostream& os, const Intensity32u& p);
};
PCL_EXPORTS std::ostream& operator << (std::ostream& os, const PointXYZI& p);
struct PointXYZI : public _PointXYZI
{
- inline PointXYZI (const _PointXYZI &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- intensity = p.intensity;
- }
+ inline constexpr PointXYZI (const _PointXYZI &p) : PointXYZI{p.x, p.y, p.z, p.intensity} {}
- inline PointXYZI (float _intensity = 0.f): PointXYZI(0.f, 0.f, 0.f, _intensity) {}
-
- inline PointXYZI (float _x, float _y, float _z, float _intensity = 0.f)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- intensity = _intensity;
- }
+ inline constexpr PointXYZI (float _intensity = 0.f) : PointXYZI(0.f, 0.f, 0.f, _intensity) {}
+ inline constexpr PointXYZI (float _x, float _y, float _z, float _intensity = 0.f) : _PointXYZI{{{_x, _y, _z, 1.0f}}, {{_intensity}}} {}
+
friend std::ostream& operator << (std::ostream& os, const PointXYZI& p);
};
PCL_EXPORTS std::ostream& operator << (std::ostream& os, const PointXYZL& p);
struct PointXYZL : public _PointXYZL
{
- inline PointXYZL (const _PointXYZL &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- label = p.label;
- }
+ inline constexpr PointXYZL (const _PointXYZL &p) : PointXYZL{p.x, p.y, p.z, p.label} {}
- inline PointXYZL (std::uint32_t _label = 0): PointXYZL(0.f, 0.f, 0.f, _label) {}
+ inline constexpr PointXYZL (std::uint32_t _label = 0) : PointXYZL(0.f, 0.f, 0.f, _label) {}
- inline PointXYZL (float _x, float _y, float _z, std::uint32_t _label = 0)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- label = _label;
- }
+ inline constexpr PointXYZL (float _x, float _y, float _z, std::uint32_t _label = 0) : _PointXYZL{{{_x, _y, _z, 1.0f}}, _label} {}
friend std::ostream& operator << (std::ostream& os, const PointXYZL& p);
};
{
std::uint32_t label = 0;
- Label (std::uint32_t _label = 0): label(_label) {}
+ inline constexpr Label (std::uint32_t _label = 0): label(_label) {}
friend std::ostream& operator << (std::ostream& os, const Label& p);
};
*/
struct EIGEN_ALIGN16 PointXYZRGBA : public _PointXYZRGBA
{
- inline PointXYZRGBA (const _PointXYZRGBA &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- rgba = p.rgba;
- }
+ inline constexpr PointXYZRGBA (const _PointXYZRGBA &p) : PointXYZRGBA{p.x, p.y, p.z, p.r, p.g, p.b, p.a} {}
- inline PointXYZRGBA (): PointXYZRGBA (0, 0, 0, 255) {}
+ inline constexpr PointXYZRGBA (): PointXYZRGBA (0, 0, 0, 255) {}
- inline PointXYZRGBA (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b, std::uint8_t _a):
+ inline constexpr PointXYZRGBA (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b, std::uint8_t _a):
PointXYZRGBA (0.f, 0.f, 0.f, _r, _g, _b, _a) {}
- inline PointXYZRGBA (float _x, float _y, float _z):
+ inline constexpr PointXYZRGBA (float _x, float _y, float _z):
PointXYZRGBA (_x, _y, _z, 0, 0, 0, 255) {}
- inline PointXYZRGBA (float _x, float _y, float _z, std::uint8_t _r,
- std::uint8_t _g, std::uint8_t _b, std::uint8_t _a)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- r = _r; g = _g; b = _b; a = _a;
- }
+ inline constexpr PointXYZRGBA (float _x, float _y, float _z, std::uint8_t _r,
+ std::uint8_t _g, std::uint8_t _b, std::uint8_t _a) : _PointXYZRGBA{{{_x, _y, _z, 1.0f}}, {{{_b, _g, _r, _a}}}} {}
friend std::ostream& operator << (std::ostream& os, const PointXYZRGBA& p);
};
*/
struct EIGEN_ALIGN16 PointXYZRGB : public _PointXYZRGB
{
- inline PointXYZRGB (const _PointXYZRGB &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- rgb = p.rgb;
- }
+ inline constexpr PointXYZRGB (const _PointXYZRGB &p) : PointXYZRGB{p.x, p.y, p.z, p.r, p.g, p.b} {}
- inline PointXYZRGB (): PointXYZRGB (0.f, 0.f, 0.f) {}
+ inline constexpr PointXYZRGB (): PointXYZRGB (0.f, 0.f, 0.f) {}
- inline PointXYZRGB (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
+ inline constexpr PointXYZRGB (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
PointXYZRGB (0.f, 0.f, 0.f, _r, _g, _b) {}
- inline PointXYZRGB (float _x, float _y, float _z):
+ inline constexpr PointXYZRGB (float _x, float _y, float _z):
PointXYZRGB (_x, _y, _z, 0, 0, 0) {}
- inline PointXYZRGB (float _x, float _y, float _z,
- std::uint8_t _r, std::uint8_t _g, std::uint8_t _b)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- r = _r; g = _g; b = _b;
- a = 255;
- }
+ inline constexpr PointXYZRGB (float _x, float _y, float _z,
+ std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
+ _PointXYZRGB{{{_x, _y, _z, 1.0f}}, {{{_b, _g, _r, 255}}}} {}
friend std::ostream& operator << (std::ostream& os, const PointXYZRGB& p);
PCL_MAKE_ALIGNED_OPERATOR_NEW
PCL_EXPORTS std::ostream& operator << (std::ostream& os, const PointXYZRGBL& p);
struct EIGEN_ALIGN16 PointXYZRGBL : public _PointXYZRGBL
{
- inline PointXYZRGBL (const _PointXYZRGBL &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- rgba = p.rgba;
- label = p.label;
- }
+ inline constexpr PointXYZRGBL (const _PointXYZRGBL &p) : PointXYZRGBL{p.x, p.y, p.z, p.r, p.g, p.b, p.label, p.a} {}
- inline PointXYZRGBL (std::uint32_t _label = 0):
+ inline constexpr PointXYZRGBL (std::uint32_t _label = 0):
PointXYZRGBL (0.f, 0.f, 0.f, 0, 0, 0, _label) {}
- inline PointXYZRGBL (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
+ inline constexpr PointXYZRGBL (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
PointXYZRGBL (0.f, 0.f, 0.f, _r, _g, _b) {}
- inline PointXYZRGBL (float _x, float _y, float _z):
+ inline constexpr PointXYZRGBL (float _x, float _y, float _z):
PointXYZRGBL (_x, _y, _z, 0, 0, 0) {}
- inline PointXYZRGBL (float _x, float _y, float _z,
+ inline constexpr PointXYZRGBL (float _x, float _y, float _z,
std::uint8_t _r, std::uint8_t _g, std::uint8_t _b,
- std::uint32_t _label = 0)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- r = _r; g = _g; b = _b;
- a = 255;
- label = _label;
- }
+ std::uint32_t _label = 0, std::uint8_t _a = 255) :
+ _PointXYZRGBL{{{_x, _y, _z, 1.0f}}, {{{_b, _g, _r, _a}}}, _label} {}
friend std::ostream& operator << (std::ostream& os, const PointXYZRGBL& p);
PCL_MAKE_ALIGNED_OPERATOR_NEW
*/
struct PointXYZLAB : public _PointXYZLAB
{
- inline PointXYZLAB (const _PointXYZLAB &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- L = p.L; a = p.a; b = p.b;
- }
+ inline constexpr PointXYZLAB (const _PointXYZLAB &p) : PointXYZLAB{p.x, p.y, p.z, p.L, p.a, p.b} {}
- inline PointXYZLAB()
- {
- x = y = z = 0.0f;
- data[3] = 1.0f; // important for homogeneous coordinates
- L = a = b = 0.0f;
- data_lab[3] = 0.0f;
- }
+ inline constexpr PointXYZLAB() : PointXYZLAB{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f} {}
+
+ inline constexpr PointXYZLAB (float _x, float _y, float _z,
+ float _L, float _a, float _b) :
+ _PointXYZLAB{ {{_x, _y, _z, 1.0f}}, {{_L, _a, _b}} } {}
friend std::ostream& operator << (std::ostream& os, const PointXYZLAB& p);
PCL_MAKE_ALIGNED_OPERATOR_NEW
PCL_EXPORTS std::ostream& operator << (std::ostream& os, const PointXYZHSV& p);
struct EIGEN_ALIGN16 PointXYZHSV : public _PointXYZHSV
{
- inline PointXYZHSV (const _PointXYZHSV &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- h = p.h; s = p.s; v = p.v;
- }
+ inline constexpr PointXYZHSV (const _PointXYZHSV &p) :
+ PointXYZHSV{p.x, p.y, p.z, p.h, p.s, p.v} {}
- inline PointXYZHSV (): PointXYZHSV (0.f, 0.f, 0.f) {}
+ inline constexpr PointXYZHSV (): PointXYZHSV (0.f, 0.f, 0.f) {}
// @TODO: Use strong types??
// This is a dangerous type, doesn't behave like others
- inline PointXYZHSV (float _h, float _s, float _v):
+ inline constexpr PointXYZHSV (float _h, float _s, float _v):
PointXYZHSV (0.f, 0.f, 0.f, _h, _s, _v) {}
- inline PointXYZHSV (float _x, float _y, float _z,
- float _h, float _s, float _v)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- h = _h; s = _s; v = _v;
- data_c[3] = 0;
- }
+ inline constexpr PointXYZHSV (float _x, float _y, float _z,
+ float _h, float _s, float _v) :
+ _PointXYZHSV{{{_x, _y, _z, 1.0f}}, {{_h, _s, _v}}} {}
friend std::ostream& operator << (std::ostream& os, const PointXYZHSV& p);
PCL_MAKE_ALIGNED_OPERATOR_NEW
};
-
-
PCL_EXPORTS std::ostream& operator << (std::ostream& os, const PointXY& p);
/** \brief A 2D point structure representing Euclidean xy coordinates.
* \ingroup common
*/
struct PointXY
{
- float x = 0.f;
- float y = 0.f;
-
- inline PointXY() = default;
-
- inline PointXY(float _x, float _y): x(_x), y(_y) {}
+ union
+ {
+ float data[2];
+ struct
+ {
+ float x;
+ float y;
+ };
+ };
+ inline constexpr PointXY(float _x, float _y): x(_x), y(_y) {}
+ inline constexpr PointXY(): x(0.0f), y(0.0f) {}
+
+ inline pcl::Vector2fMap getVector2fMap () { return (pcl::Vector2fMap (data)); }
+ inline pcl::Vector2fMapConst getVector2fMap () const { return (pcl::Vector2fMapConst (data)); }
+
friend std::ostream& operator << (std::ostream& os, const PointXY& p);
};
float u = 0.f;
float v = 0.f;
- inline PointUV() = default;
+ inline constexpr PointUV() = default;
- inline PointUV(float _u, float _v): u(_u), v(_v) {}
+ inline constexpr PointUV(float _u, float _v): u(_u), v(_v) {}
friend std::ostream& operator << (std::ostream& os, const PointUV& p);
};
*/
struct Normal : public _Normal
{
- inline Normal (const _Normal &p)
- {
- normal_x = p.normal_x; normal_y = p.normal_y; normal_z = p.normal_z;
- data_n[3] = 0.0f;
- curvature = p.curvature;
- }
+ inline constexpr Normal (const _Normal &p) : Normal {p.normal_x, p.normal_y, p.normal_z, p.curvature} {}
- inline Normal (float _curvature = 0.f): Normal (0.f, 0.f, 0.f, _curvature) {}
+ inline constexpr Normal (float _curvature = 0.f): Normal (0.f, 0.f, 0.f, _curvature) {}
- inline Normal (float n_x, float n_y, float n_z, float _curvature = 0.f)
- {
- normal_x = n_x; normal_y = n_y; normal_z = n_z;
- data_n[3] = 0.0f;
- curvature = _curvature;
- }
+ inline constexpr Normal (float n_x, float n_y, float n_z, float _curvature = 0.f) :
+ _Normal{{{n_x, n_y, n_z, 0.0f}}, {{_curvature}}} {}
friend std::ostream& operator << (std::ostream& os, const Normal& p);
PCL_MAKE_ALIGNED_OPERATOR_NEW
*/
struct EIGEN_ALIGN16 Axis : public _Axis
{
- inline Axis (const _Axis &p)
- {
- normal_x = p.normal_x; normal_y = p.normal_y; normal_z = p.normal_z;
- data_n[3] = 0.0f;
- }
+ inline constexpr Axis (const _Axis &p) : Axis{p.normal_x, p.normal_y, p.normal_z} {}
- inline Axis (): Axis (0.f, 0.f, 0.f) {}
+ inline constexpr Axis (): Axis (0.f, 0.f, 0.f) {}
- inline Axis (float n_x, float n_y, float n_z)
- {
- normal_x = n_x; normal_y = n_y; normal_z = n_z;
- data_n[3] = 0.0f;
- }
+ inline constexpr Axis (float n_x, float n_y, float n_z) : _Axis{{{n_x, n_y, n_z, 0.0f}}} {}
friend std::ostream& operator << (std::ostream& os, const Axis& p);
PCL_MAKE_ALIGNED_OPERATOR_NEW
*/
struct PointNormal : public _PointNormal
{
- inline PointNormal (const _PointNormal &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- normal_x = p.normal_x; normal_y = p.normal_y; normal_z = p.normal_z; data_n[3] = 0.0f;
- curvature = p.curvature;
- }
+ inline constexpr PointNormal (const _PointNormal &p) : PointNormal{p.x, p.y, p.z, p.normal_x, p.normal_y, p.normal_z, p.curvature} {}
- inline PointNormal (float _curvature = 0.f): PointNormal (0.f, 0.f, 0.f, 0.f, 0.f, 0.f, _curvature) {}
+ inline constexpr PointNormal (float _curvature = 0.f): PointNormal (0.f, 0.f, 0.f, 0.f, 0.f, 0.f, _curvature) {}
- inline PointNormal (float _x, float _y, float _z):
+ inline constexpr PointNormal (float _x, float _y, float _z):
PointNormal (_x, _y, _z, 0.f, 0.f, 0.f, 0.f) {}
- inline PointNormal (float _x, float _y, float _z, float n_x, float n_y, float n_z, float _curvature = 0.f)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- normal_x = n_x; normal_y = n_y; normal_z = n_z;
- data_n[3] = 0.0f;
- curvature = _curvature;
- }
+ inline constexpr PointNormal (float _x, float _y, float _z, float n_x, float n_y, float n_z, float _curvature = 0.f) :
+ _PointNormal{{{_x, _y, _z, 1.0f}}, {{n_x, n_y, n_z, 0.0f}}, {{_curvature}}} {}
friend std::ostream& operator << (std::ostream& os, const PointNormal& p);
};
*/
struct PointXYZRGBNormal : public _PointXYZRGBNormal
{
- inline PointXYZRGBNormal (const _PointXYZRGBNormal &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- normal_x = p.normal_x; normal_y = p.normal_y; normal_z = p.normal_z; data_n[3] = 0.0f;
- curvature = p.curvature;
- rgba = p.rgba;
- }
+ inline constexpr PointXYZRGBNormal (const _PointXYZRGBNormal &p) :
+ PointXYZRGBNormal {p.x, p.y, p.z, p.r, p.g, p.b, p.a, p.normal_x, p.normal_y, p.normal_z, p.curvature} {}
- inline PointXYZRGBNormal (float _curvature = 0.f):
+ inline constexpr PointXYZRGBNormal (float _curvature = 0.f):
PointXYZRGBNormal (0.f, 0.f, 0.f, 0, 0, 0, 0.f, 0.f, 0.f, _curvature) {}
- inline PointXYZRGBNormal (float _x, float _y, float _z):
+ inline constexpr PointXYZRGBNormal (float _x, float _y, float _z):
PointXYZRGBNormal (_x, _y, _z, 0, 0, 0) {}
- inline PointXYZRGBNormal (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
+ inline constexpr PointXYZRGBNormal (std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
PointXYZRGBNormal (0.f, 0.f, 0.f, _r, _g, _b) {}
- inline PointXYZRGBNormal (float _x, float _y, float _z, std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
+ inline constexpr PointXYZRGBNormal (float _x, float _y, float _z, std::uint8_t _r, std::uint8_t _g, std::uint8_t _b):
PointXYZRGBNormal (_x, _y, _z, _r, _g, _b, 0.f, 0.f, 0.f) {}
- inline PointXYZRGBNormal (float _x, float _y, float _z, std::uint8_t _r, std::uint8_t _g, std::uint8_t _b,
- float n_x, float n_y, float n_z, float _curvature = 0.f)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- r = _r; g = _g; b = _b;
- a = 255;
- normal_x = n_x; normal_y = n_y; normal_z = n_z;
- data_n[3] = 0.f;
- curvature = _curvature;
- }
+ inline constexpr PointXYZRGBNormal (float _x, float _y, float _z, std::uint8_t _r, std::uint8_t _g, std::uint8_t _b,
+ float n_x, float n_y, float n_z, float _curvature = 0.f) :
+ _PointXYZRGBNormal{
+ {{_x, _y, _z, 1.0f}},
+ {{n_x, n_y, n_z, 0.0f}},
+ {{ {{{_b, _g, _r, 255u}}}, _curvature }}
+ }
+ {}
+
+ inline constexpr PointXYZRGBNormal (float _x, float _y, float _z, std::uint8_t _r, std::uint8_t _g, std::uint8_t _b,
+ std::uint8_t _a, float n_x, float n_y, float n_z, float _curvature = 0.f) :
+ _PointXYZRGBNormal{
+ {{_x, _y, _z, 1.0f}},
+ {{n_x, n_y, n_z, 0.0f}},
+ {{ {{{_b, _g, _r, _a}}}, _curvature }}
+ }
+ {}
+
friend std::ostream& operator << (std::ostream& os, const PointXYZRGBNormal& p);
};
*/
struct PointXYZINormal : public _PointXYZINormal
{
- inline PointXYZINormal (const _PointXYZINormal &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- normal_x = p.normal_x; normal_y = p.normal_y; normal_z = p.normal_z; data_n[3] = 0.0f;
- curvature = p.curvature;
- intensity = p.intensity;
- }
+ inline constexpr PointXYZINormal (const _PointXYZINormal &p) :
+ PointXYZINormal {p.x, p.y, p.z, p.intensity, p.normal_x, p.normal_y, p.normal_z, p.curvature} {}
- inline PointXYZINormal (float _intensity = 0.f): PointXYZINormal (0.f, 0.f, 0.f, _intensity) {}
+ inline constexpr PointXYZINormal (float _intensity = 0.f): PointXYZINormal (0.f, 0.f, 0.f, _intensity) {}
- inline PointXYZINormal (float _x, float _y, float _z, float _intensity = 0.f):
+ inline constexpr PointXYZINormal (float _x, float _y, float _z, float _intensity = 0.f):
PointXYZINormal (_x, _y, _z, _intensity, 0.f, 0.f, 0.f) {}
- inline PointXYZINormal (float _x, float _y, float _z, float _intensity,
- float n_x, float n_y, float n_z, float _curvature = 0.f)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- intensity = _intensity;
- normal_x = n_x; normal_y = n_y; normal_z = n_z;
- data_n[3] = 0.f;
- curvature = _curvature;
- }
+ inline constexpr PointXYZINormal (float _x, float _y, float _z, float _intensity,
+ float n_x, float n_y, float n_z, float _curvature = 0.f) :
+ _PointXYZINormal{
+ {{_x, _y, _z, 1.0f}},
+ {{n_x, n_y, n_z, 0.0f}},
+ {{_intensity, _curvature}}
+ }
+ {}
friend std::ostream& operator << (std::ostream& os, const PointXYZINormal& p);
};
*/
struct PointXYZLNormal : public _PointXYZLNormal
{
- inline PointXYZLNormal (const _PointXYZLNormal &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- normal_x = p.normal_x; normal_y = p.normal_y; normal_z = p.normal_z; data_n[3] = 0.0f;
- curvature = p.curvature;
- label = p.label;
- }
+ inline constexpr PointXYZLNormal (const _PointXYZLNormal &p) :
+ PointXYZLNormal {p.x, p.y, p.z, p.label, p.normal_x, p.normal_y, p.normal_z, p.curvature} {}
- inline PointXYZLNormal (std::uint32_t _label = 0): PointXYZLNormal (0.f, 0.f, 0.f, _label) {}
+ inline constexpr PointXYZLNormal (std::uint32_t _label = 0u): PointXYZLNormal (0.f, 0.f, 0.f, _label) {}
- inline PointXYZLNormal (float _x, float _y, float _z, std::uint32_t _label = 0.f):
+ inline constexpr PointXYZLNormal (float _x, float _y, float _z, std::uint32_t _label = 0u) :
PointXYZLNormal (_x, _y, _z, _label, 0.f, 0.f, 0.f) {}
- inline PointXYZLNormal (float _x, float _y, float _z, std::uint32_t _label,
- float n_x, float n_y, float n_z, float _curvature = 0.f)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- label = _label;
- normal_x = n_x; normal_y = n_y; normal_z = n_z;
- data_n[3] = 0.f;
- curvature = _curvature;
- }
+ inline constexpr PointXYZLNormal (float _x, float _y, float _z, std::uint32_t _label,
+ float n_x, float n_y, float n_z, float _curvature = 0.f) :
+ _PointXYZLNormal{
+ {{_x, _y, _z, 1.0f}},
+ {{n_x, n_y, n_z, 0.0f}},
+ {{_label, _curvature}}
+ }
+ {}
friend std::ostream& operator << (std::ostream& os, const PointXYZLNormal& p);
};
*/
struct PointWithRange : public _PointWithRange
{
- inline PointWithRange (const _PointWithRange &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- range = p.range;
- }
+ inline constexpr PointWithRange (const _PointWithRange &p) : PointWithRange{p.x, p.y, p.z, p.range} {}
- inline PointWithRange (float _range = 0.f): PointWithRange (0.f, 0.f, 0.f, _range) {}
+ inline constexpr PointWithRange (float _range = 0.f): PointWithRange (0.f, 0.f, 0.f, _range) {}
- inline PointWithRange (float _x, float _y, float _z, float _range = 0.f)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- range = _range;
- }
+ inline constexpr PointWithRange (float _x, float _y, float _z, float _range = 0.f) :
+ _PointWithRange{{{_x, _y, _z, 1.0f}}, {{_range}}} {}
friend std::ostream& operator << (std::ostream& os, const PointWithRange& p);
};
*/
struct EIGEN_ALIGN16 PointWithViewpoint : public _PointWithViewpoint
{
- inline PointWithViewpoint (const _PointWithViewpoint &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- vp_x = p.vp_x; vp_y = p.vp_y; vp_z = p.vp_z;
- }
+ inline constexpr PointWithViewpoint (const _PointWithViewpoint &p) : PointWithViewpoint{p.x, p.y, p.z, p.vp_x, p.vp_y, p.vp_z} {}
- inline PointWithViewpoint (): PointWithViewpoint (0.f, 0.f, 0.f) {}
+ inline constexpr PointWithViewpoint (): PointWithViewpoint (0.f, 0.f, 0.f) {}
- inline PointWithViewpoint (float _x, float _y, float _z): PointWithViewpoint (_x, _y, _z, 0.f, 0.f, 0.f) {}
+ inline constexpr PointWithViewpoint (float _x, float _y, float _z): PointWithViewpoint (_x, _y, _z, 0.f, 0.f, 0.f) {}
- inline PointWithViewpoint (float _x, float _y, float _z, float _vp_x, float _vp_y, float _vp_z)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- vp_x = _vp_x; vp_y = _vp_y; vp_z = _vp_z;
- }
+ inline constexpr PointWithViewpoint (float _x, float _y, float _z, float _vp_x, float _vp_y, float _vp_z) :
+ _PointWithViewpoint{{{_x, _y, _z, 1.0f}}, {{_vp_x, _vp_y, _vp_z}}} {}
friend std::ostream& operator << (std::ostream& os, const PointWithViewpoint& p);
};
{
float j1 = 0.f, j2 = 0.f, j3 = 0.f;
- inline MomentInvariants () = default;
+ inline constexpr MomentInvariants () = default;
- inline MomentInvariants (float _j1, float _j2, float _j3): j1 (_j1), j2 (_j2), j3 (_j3) {}
+ inline constexpr MomentInvariants (float _j1, float _j2, float _j3): j1 (_j1), j2 (_j2), j3 (_j3) {}
friend std::ostream& operator << (std::ostream& os, const MomentInvariants& p);
};
{
float r_min = 0.f, r_max = 0.f;
- inline PrincipalRadiiRSD () = default;
+ inline constexpr PrincipalRadiiRSD () = default;
- inline PrincipalRadiiRSD (float _r_min, float _r_max): r_min (_r_min), r_max (_r_max) {}
+ inline constexpr PrincipalRadiiRSD (float _r_min, float _r_max): r_min (_r_min), r_max (_r_max) {}
friend std::ostream& operator << (std::ostream& os, const PrincipalRadiiRSD& p);
};
std::uint8_t boundary_point = 0;
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 1101
- operator unsigned char() const
+ constexpr operator unsigned char() const
{
return boundary_point;
}
#endif
- inline Boundary (std::uint8_t _boundary = 0): boundary_point (_boundary) {}
+ inline constexpr Boundary (std::uint8_t _boundary = 0): boundary_point (_boundary) {}
friend std::ostream& operator << (std::ostream& os, const Boundary& p);
};
float pc1 = 0.f;
float pc2 = 0.f;
- inline PrincipalCurvatures (): PrincipalCurvatures (0.f, 0.f) {}
+ inline constexpr PrincipalCurvatures (): PrincipalCurvatures (0.f, 0.f) {}
- inline PrincipalCurvatures (float _pc1, float _pc2): PrincipalCurvatures (0.f, 0.f, 0.f, _pc1, _pc2) {}
+ inline constexpr PrincipalCurvatures (float _pc1, float _pc2): PrincipalCurvatures (0.f, 0.f, 0.f, _pc1, _pc2) {}
- inline PrincipalCurvatures (float _x, float _y, float _z): PrincipalCurvatures (_x, _y, _z, 0.f, 0.f) {}
+ inline constexpr PrincipalCurvatures (float _x, float _y, float _z): PrincipalCurvatures (_x, _y, _z, 0.f, 0.f) {}
- inline PrincipalCurvatures (float _x, float _y, float _z, float _pc1, float _pc2):
+ inline constexpr PrincipalCurvatures (float _x, float _y, float _z, float _pc1, float _pc2):
principal_curvature_x (_x), principal_curvature_y (_y), principal_curvature_z (_z), pc1 (_pc1), pc2 (_pc2) {}
friend std::ostream& operator << (std::ostream& os, const PrincipalCurvatures& p);
float histogram[125] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<PFHSignature125>; }
- inline PFHSignature125 () = default;
+ inline constexpr PFHSignature125 () = default;
friend std::ostream& operator << (std::ostream& os, const PFHSignature125& p);
};
float histogram[250] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<PFHRGBSignature250>; }
- inline PFHRGBSignature250 () = default;
+ inline constexpr PFHRGBSignature250 () = default;
friend std::ostream& operator << (std::ostream& os, const PFHRGBSignature250& p);
};
float f1 = 0.f, f2 = 0.f, f3 = 0.f, f4 = 0.f;
float alpha_m = 0.f;
- inline PPFSignature (float _alpha = 0.f): PPFSignature (0.f, 0.f, 0.f, 0.f, _alpha) {}
+ inline constexpr PPFSignature (float _alpha = 0.f): PPFSignature (0.f, 0.f, 0.f, 0.f, _alpha) {}
- inline PPFSignature (float _f1, float _f2, float _f3, float _f4, float _alpha = 0.f):
+ inline constexpr PPFSignature (float _f1, float _f2, float _f3, float _f4, float _alpha = 0.f):
f1 (_f1), f2 (_f2), f3 (_f3), f4 (_f4), alpha_m (_alpha) {}
friend std::ostream& operator << (std::ostream& os, const PPFSignature& p);
float f1, f2, f3, f4, f5, f6, f7, f8, f9, f10;
float alpha_m;
- inline CPPFSignature (float _alpha = 0.f):
+ inline constexpr CPPFSignature (float _alpha = 0.f):
CPPFSignature (0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, _alpha) {}
- inline CPPFSignature (float _f1, float _f2, float _f3, float _f4, float _f5, float _f6,
+ inline constexpr CPPFSignature (float _f1, float _f2, float _f3, float _f4, float _f5, float _f6,
float _f7, float _f8, float _f9, float _f10, float _alpha = 0.f):
f1 (_f1), f2 (_f2), f3 (_f3), f4 (_f4), f5 (_f5), f6 (_f6),
f7 (_f7), f8 (_f8), f9 (_f9), f10 (_f10), alpha_m (_alpha) {}
float r_ratio = 0.f, g_ratio = 0.f, b_ratio = 0.f;
float alpha_m = 0.f;
- inline PPFRGBSignature (float _alpha = 0.f): PPFRGBSignature (0.f, 0.f, 0.f, 0.f, _alpha) {}
+ inline constexpr PPFRGBSignature (float _alpha = 0.f): PPFRGBSignature (0.f, 0.f, 0.f, 0.f, _alpha) {}
- inline PPFRGBSignature (float _f1, float _f2, float _f3, float _f4, float _alpha = 0.f):
+ inline constexpr PPFRGBSignature (float _f1, float _f2, float _f3, float _f4, float _alpha = 0.f):
PPFRGBSignature (_f1, _f2, _f3, _f4, _alpha, 0.f, 0.f, 0.f) {}
- inline PPFRGBSignature (float _f1, float _f2, float _f3, float _f4, float _alpha, float _r, float _g, float _b):
+ inline constexpr PPFRGBSignature (float _f1, float _f2, float _f3, float _f4, float _alpha, float _r, float _g, float _b):
f1 (_f1), f2 (_f2), f3 (_f3), f4 (_f4), r_ratio (_r), g_ratio (_g), b_ratio (_b), alpha_m (_alpha) {}
friend std::ostream& operator << (std::ostream& os, const PPFRGBSignature& p);
{
float values[12] = {0.f};
- inline NormalBasedSignature12 () = default;
+ inline constexpr NormalBasedSignature12 () = default;
friend std::ostream& operator << (std::ostream& os, const NormalBasedSignature12& p);
};
float rf[9] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<ShapeContext1980>; }
- inline ShapeContext1980 () = default;
+ inline constexpr ShapeContext1980 () = default;
friend std::ostream& operator << (std::ostream& os, const ShapeContext1980& p);
};
float rf[9] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<UniqueShapeContext1960>; }
- inline UniqueShapeContext1960 () = default;
+ inline constexpr UniqueShapeContext1960 () = default;
friend std::ostream& operator << (std::ostream& os, const UniqueShapeContext1960& p);
};
float rf[9] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<SHOT352>; }
- inline SHOT352 () = default;
+ inline constexpr SHOT352 () = default;
friend std::ostream& operator << (std::ostream& os, const SHOT352& p);
};
float rf[9] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<SHOT1344>; }
- inline SHOT1344 () = default;
+ inline constexpr SHOT1344 () = default;
friend std::ostream& operator << (std::ostream& os, const SHOT1344& p);
};
PCL_EXPORTS std::ostream& operator << (std::ostream& os, const ReferenceFrame& p);
struct EIGEN_ALIGN16 ReferenceFrame : public _ReferenceFrame
{
- inline ReferenceFrame (const _ReferenceFrame &p)
+ inline constexpr ReferenceFrame (const _ReferenceFrame &p) :
+ ReferenceFrame{p.rf}
{
- std::copy_n(p.rf, 9, rf);
+ //std::copy_n(p.rf, 9, rf); // this algorithm is constexpr starting from C++20
}
- inline ReferenceFrame ()
+ inline constexpr ReferenceFrame () :
+ _ReferenceFrame{ {{0.0f}} }
{
- std::fill_n(x_axis, 3, 0.f);
+ // this algorithm is constexpr starting from C++20
+ /*std::fill_n(x_axis, 3, 0.f);
std::fill_n(y_axis, 3, 0.f);
- std::fill_n(z_axis, 3, 0.f);
+ std::fill_n(z_axis, 3, 0.f);*/
}
- // @TODO: add other ctors
+ inline constexpr ReferenceFrame (const float (&_rf)[9]) :
+ _ReferenceFrame{ {{_rf[0], _rf[1], _rf[2], _rf[3], _rf[4], _rf[5], _rf[6], _rf[7], _rf[8]}} } {}
friend std::ostream& operator << (std::ostream& os, const ReferenceFrame& p);
PCL_MAKE_ALIGNED_OPERATOR_NEW
float histogram[33] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<FPFHSignature33>; }
- inline FPFHSignature33 () = default;
+ inline constexpr FPFHSignature33 () = default;
friend std::ostream& operator << (std::ostream& os, const FPFHSignature33& p);
};
float histogram[308] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<VFHSignature308>; }
- inline VFHSignature308 () = default;
+ inline constexpr VFHSignature308 () = default;
friend std::ostream& operator << (std::ostream& os, const VFHSignature308& p);
};
float histogram[21] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<GRSDSignature21>; }
- inline GRSDSignature21 () = default;
+ inline constexpr GRSDSignature21 () = default;
friend std::ostream& operator << (std::ostream& os, const GRSDSignature21& p);
};
unsigned char descriptor[64] = {0};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<BRISKSignature512>; }
- inline BRISKSignature512 () = default;
+ inline constexpr BRISKSignature512 () = default;
- inline BRISKSignature512 (float _scale, float _orientation): scale (_scale), orientation (_orientation) {}
+ inline constexpr BRISKSignature512 (float _scale, float _orientation): scale (_scale), orientation (_orientation) {}
friend std::ostream& operator << (std::ostream& os, const BRISKSignature512& p);
};
float histogram[640] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<ESFSignature640>; }
- inline ESFSignature640 () = default;
+ inline constexpr ESFSignature640 () = default;
friend std::ostream& operator << (std::ostream& os, const ESFSignature640& p);
};
float histogram[512] = {0.f};
static constexpr int descriptorSize() { return detail::traits::descriptorSize_v<GASDSignature512>; }
- inline GASDSignature512 () = default;
+ inline constexpr GASDSignature512 () = default;
friend std::ostream& operator << (std::ostream& os, const GASDSignature512& p);
};
float histogram[984] = {0.f};
static constexpr int descriptorSize() { return detail::traits::descriptorSize_v<GASDSignature984>; }
- inline GASDSignature984 () = default;
+ inline constexpr GASDSignature984 () = default;
friend std::ostream& operator << (std::ostream& os, const GASDSignature984& p);
};
float histogram[7992] = {0.f};
static constexpr int descriptorSize() { return detail::traits::descriptorSize_v<GASDSignature7992>; }
- inline GASDSignature7992 () = default;
+ inline constexpr GASDSignature7992 () = default;
friend std::ostream& operator << (std::ostream& os, const GASDSignature7992& p);
};
float histogram[16] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<GFPFHSignature16>; }
- inline GFPFHSignature16 () = default;
+ inline constexpr GFPFHSignature16 () = default;
friend std::ostream& operator << (std::ostream& os, const GFPFHSignature16& p);
};
float descriptor[36] = {0.f};
static constexpr int descriptorSize () { return detail::traits::descriptorSize_v<Narf36>; }
- inline Narf36 () = default;
+ inline constexpr Narf36 () = default;
- inline Narf36 (float _x, float _y, float _z): Narf36 (_x, _y, _z, 0.f, 0.f, 0.f) {}
+ inline constexpr Narf36 (float _x, float _y, float _z): Narf36 (_x, _y, _z, 0.f, 0.f, 0.f) {}
- inline Narf36 (float _x, float _y, float _z, float _roll, float _pitch, float _yaw):
+ inline constexpr Narf36 (float _x, float _y, float _z, float _roll, float _pitch, float _yaw):
x (_x), y (_y), z (_z), roll (_roll), pitch (_pitch), yaw (_yaw) {}
friend std::ostream& operator << (std::ostream& os, const Narf36& p);
BorderTraits traits;
//std::vector<const BorderDescription*> neighbors;
- inline BorderDescription () = default;
+ inline constexpr BorderDescription () = default;
- // TODO: provide other ctors
+ inline constexpr BorderDescription (int _x, int _y) : x(_x), y(_y) {}
friend std::ostream& operator << (std::ostream& os, const BorderDescription& p);
};
};
};
- inline IntensityGradient (): IntensityGradient (0.f, 0.f, 0.f) {}
+ inline constexpr IntensityGradient (): IntensityGradient (0.f, 0.f, 0.f) {}
- inline IntensityGradient (float _x, float _y, float _z): gradient_x (_x), gradient_y (_y), gradient_z (_z) {}
+ inline constexpr IntensityGradient (float _x, float _y, float _z): gradient_x (_x), gradient_y (_y), gradient_z (_z) {}
friend std::ostream& operator << (std::ostream& os, const IntensityGradient& p);
};
*/
struct PointWithScale : public _PointWithScale
{
- inline PointWithScale (const _PointWithScale &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- scale = p.scale;
- angle = p.angle;
- response = p.response;
- octave = p.octave;
- }
-
- inline PointWithScale (): PointWithScale (0.f, 0.f, 0.f) {}
+ inline constexpr PointWithScale (const _PointWithScale &p) :
+ PointWithScale{p.x, p.y, p.z, p.scale, p.angle, p.response, p.octave} {}
- inline PointWithScale (float _x, float _y, float _z, float _scale = 1.f,
- float _angle = -1.f, float _response = 0.f, int _octave = 0)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- scale = _scale;
- angle = _angle;
- response = _response;
- octave = _octave;
- }
+ inline constexpr PointWithScale (): PointWithScale (0.f, 0.f, 0.f) {}
+ inline constexpr PointWithScale (float _x, float _y, float _z, float _scale = 1.f,
+ float _angle = -1.f, float _response = 0.f, int _octave = 0) :
+ _PointWithScale{{{_x, _y, _z, 1.0f}}, {_scale}, _angle, _response, _octave } {}
+
friend std::ostream& operator << (std::ostream& os, const PointWithScale& p);
};
*/
struct PointSurfel : public _PointSurfel
{
- inline PointSurfel (const _PointSurfel &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- rgba = p.rgba;
- radius = p.radius;
- confidence = p.confidence;
- curvature = p.curvature;
- }
+ inline constexpr PointSurfel (const _PointSurfel &p) :
+ PointSurfel{p.x, p.y, p.z, p.normal_x, p.normal_y, p.normal_z, p.r, p.g, p.b, p.a, p.radius, p.confidence, p.curvature} {}
- inline PointSurfel ()
- {
- x = y = z = 0.0f;
- data[3] = 1.0f;
- normal_x = normal_y = normal_z = data_n[3] = 0.0f;
- r = g = b = 0;
- a = 255;
- radius = confidence = curvature = 0.0f;
- }
+ inline constexpr PointSurfel () :
+ PointSurfel{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0u, 0u, 0u, 0u, 0.0f, 0.0f, 0.0f} {}
+
+ inline constexpr PointSurfel (float _x, float _y, float _z, float _nx,
+ float _ny, float _nz, std::uint8_t _r, std::uint8_t _g, std::uint8_t _b, std::uint8_t _a,
+ float _radius, float _confidence, float _curvature) :
+ _PointSurfel{
+ {{_x, _y, _z, 1.0f}},
+ {{_nx, _ny, _nz, 0.0f}},
+ {{{{{_b, _g, _r, _a}}}, _radius, _confidence, _curvature}}
+ } {}
- // TODO: add other ctor to PointSurfel
friend std::ostream& operator << (std::ostream& os, const PointSurfel& p);
};
*/
struct PointDEM : public _PointDEM
{
- inline PointDEM (const _PointDEM &p)
- {
- x = p.x; y = p.y; z = p.z; data[3] = 1.0f;
- intensity = p.intensity;
- intensity_variance = p.intensity_variance;
- height_variance = p.height_variance;
- }
-
- inline PointDEM (): PointDEM (0.f, 0.f, 0.f) {}
-
- inline PointDEM (float _x, float _y, float _z): PointDEM (_x, _y, _z, 0.f, 0.f, 0.f) {}
+ inline constexpr PointDEM (const _PointDEM &p) :
+ PointDEM{p.x, p.y, p.z, p.intensity, p.intensity_variance, p.height_variance} {}
+
+ inline constexpr PointDEM (): PointDEM (0.f, 0.f, 0.f) {}
- inline PointDEM (float _x, float _y, float _z, float _intensity,
- float _intensity_variance, float _height_variance)
- {
- x = _x; y = _y; z = _z;
- data[3] = 1.0f;
- intensity = _intensity;
- intensity_variance = _intensity_variance;
- height_variance = _height_variance;
- }
+ inline constexpr PointDEM (float _x, float _y, float _z): PointDEM (_x, _y, _z, 0.f, 0.f, 0.f) {}
+ inline constexpr PointDEM (float _x, float _y, float _z, float _intensity,
+ float _intensity_variance, float _height_variance) :
+ _PointDEM{{{_x, _y, _z, 1.0f}}, _intensity, _intensity_variance, _height_variance} {}
+
friend std::ostream& operator << (std::ostream& os, const PointDEM& p);
};
#pragma once
-PCL_DEPRECATED_HEADER(1, 13, "Use <pcl/memory.h> instead.")
+PCL_DEPRECATED_HEADER(1, 15, "Use <pcl/memory.h> instead.")
#include <pcl/memory.h>
// Macro for emitting pragma warning for deprecated headers
#if (defined (__GNUC__) || defined(__clang__))
- #define _PCL_DEPRECATED_HEADER_IMPL(Message) PCL_PRAGMA (GCC warning Message)
+ #define _PCL_DEPRECATED_HEADER_IMPL(Message) PCL_PRAGMA (message Message)
#elif _MSC_VER
#define _PCL_DEPRECATED_HEADER_IMPL(Message) PCL_PRAGMA (warning (Message))
#else
#else
#define PCL_IF_CONSTEXPR(x) if (x)
#endif
+
+// [[unlikely]] can be used on any conditional branch, but __builtin_expect is restricted to the evaluation point
+// This makes it quite difficult to create a single macro for switch and while/if
+/**
+ * @def PCL_CONDITION_UNLIKELY
+ * @brief Tries to inform the compiler to optimize codegen assuming that the condition will probably evaluate to false
+ * @note Prefer using `PCL_{IF,WHILE}_UNLIKELY`
+ * @warning This can't be used with switch statements
+ * @details This tries to help the compiler optimize for the unlikely case.
+ * Most compilers assume that the condition would evaluate to true in if and while loops (reference needed)
+ * As such the opposite of this macro (PCL_CONDITION_LIKELY) will not result in significant performance improvement
+ *
+ * Some sample usage:
+ * @code{.cpp}
+ * if PCL_CONDITION_UNLIKELY(x == 0) { return; } else { throw std::runtime_error("some error"); }
+ * //
+ * while PCL_CONDITION_UNLIKELY(wait_for_result) { sleep(1); } // busy wait, with minimal chances of waiting
+ * @endcode
+ */
+#if __has_cpp_attribute(unlikely)
+ #define PCL_CONDITION_UNLIKELY(x) (static_cast<bool>(x)) [[unlikely]]
+#elif defined(__GNUC__)
+ #define PCL_CONDITION_UNLIKELY(x) (__builtin_expect(static_cast<bool>(x), 0))
+#elif defined(__clang__) && (PCL_LINEAR_VERSION(__clang_major__, __clang_minor__, 0) >= PCL_LINEAR_VERSION(3, 9, 0))
+ #define PCL_CONDITION_UNLIKELY(x) (__builtin_expect(static_cast<bool>(x), 0))
+#else // MSVC has no such alternative
+ #define PCL_CONDITION_UNLIKELY(x) (x)
+#endif
+
+#define PCL_IF_UNLIKELY(x) if PCL_CONDITION_UNLIKELY(x)
+#define PCL_WHILE_UNLIKELY(x) while PCL_CONDITION_UNLIKELY(x)
{
SCOPED_TRACE("EXPECT_EQ_VECTORS failed");
EXPECT_EQ (v1.size (), v2.size ());
- std::size_t length = v1.size ();
+ std::size_t length = std::min<std::size_t> (v1.size (), v2.size ());
for (std::size_t i = 0; i < length; ++i)
EXPECT_EQ (v1[i], v2[i]);
}
{
SCOPED_TRACE("EXPECT_NEAR_VECTORS failed");
EXPECT_EQ (v1.size (), v2.size ());
- std::size_t length = v1.size ();
+ std::size_t length = std::min<std::size_t> (v1.size (), v2.size());
for (std::size_t i = 0; i < length; ++i)
EXPECT_NEAR (v1[i], v2[i], epsilon);
}
inline void
assign(InputIterator first, InputIterator last, index_t new_width)
{
+ if (new_width == 0) {
+ PCL_WARN("Assignment with new_width equal to 0,"
+ "setting width to size of the cloud and height to 1\n");
+ return assign(std::move(first), std::move(last));
+ }
+
points.assign(std::move(first), std::move(last));
width = new_width;
height = size() / width;
void
inline assign(std::initializer_list<PointT> ilist, index_t new_width)
{
+ if (new_width == 0) {
+ PCL_WARN("Assignment with new_width equal to 0,"
+ "setting width to size of the cloud and height to 1\n");
+ return assign(std::move(ilist));
+ }
points.assign(std::move(ilist));
width = new_width;
height = size() / width;
setRescaleValues (const float *rescale_array)
{
alpha_.resize (nr_dimensions_);
- std::copy_n(rescale_array, nr_dimensions_, alpha_.begin());
+ std::copy(rescale_array, rescale_array + nr_dimensions_, alpha_.begin());
}
/** \brief Return the number of dimensions in the point's vector representation. */
trivial_ = true;
}
- ~DefaultPointRepresentation () {}
+ ~DefaultPointRepresentation () override = default;
inline Ptr
makeShared () const
{
// If point type is unknown, treat it as a struct/array of floats
const float* ptr = reinterpret_cast<const float*> (&p);
- std::copy_n(ptr, nr_dimensions_, out);
+ std::copy(ptr, ptr + nr_dimensions_, out);
}
};
* \param[in] p the input point
* \param[out] out the resultant output array
*/
- virtual void
- copyToFloatArray (const PointDefault &p, float *out) const
+ void
+ copyToFloatArray (const PointDefault &p, float *out) const override
{
// If point type is unknown, treat it as a struct/array of floats
const float *ptr = (reinterpret_cast<const float*> (&p)) + start_dim_;
- std::copy_n(ptr, nr_dimensions_, out);
+ std::copy(ptr, ptr + nr_dimensions_, out);
}
protected:
#pragma once
-PCL_DEPRECATED_HEADER(1, 13, "Use <pcl/type_traits.h> instead.")
+PCL_DEPRECATED_HEADER(1, 15, "Use <pcl/type_traits.h> instead.")
#include <pcl/type_traits.h>
{
out.width = in.width;
out.height = in.height;
- for (const auto &point : in.points)
+ for (const auto &point : in)
{
Intensity p;
PointRGBtoI (point, p);
{
out.width = in.width;
out.height = in.height;
- for (const auto &point : in.points)
+ for (const auto &point : in)
{
Intensity8u p;
PointRGBtoI (point, p);
{
out.width = in.width;
out.height = in.height;
- for (const auto &point : in.points)
+ for (const auto &point : in)
{
Intensity32u p;
PointRGBtoI (point, p);
{
out.width = in.width;
out.height = in.height;
- for (const auto &point : in.points)
+ for (const auto &point : in)
{
PointXYZHSV p;
PointXYZRGBtoXYZHSV (point, p);
out.push_back (p);
}
}
+
+ /** \brief Convert a XYZHSV point cloud to a XYZRGB
+ * \param[in] in the input XYZHSV point cloud
+ * \param[out] out the output XYZRGB point cloud
+ */
+ inline void
+ PointCloudXYZHSVtoXYZRGB (const PointCloud<PointXYZHSV>& in,
+ PointCloud<PointXYZRGB>& out)
+ {
+ out.width = in.width;
+ out.height = in.height;
+ for (const auto &point : in)
+ {
+ PointXYZRGB p;
+ PointXYZHSVtoXYZRGB (point, p);
+ out.push_back (p);
+ }
+ }
/** \brief Convert a XYZRGB point cloud to a XYZHSV
* \param[in] in the input XYZRGB point cloud
{
out.width = in.width;
out.height = in.height;
- for (const auto &point : in.points)
+ for (const auto &point : in)
{
PointXYZHSV p;
PointXYZRGBAtoXYZHSV (point, p);
{
out.width = in.width;
out.height = in.height;
- for (const auto &point : in.points)
+ for (const auto &point : in)
{
PointXYZI p;
PointXYZRGBtoXYZI (point, p);
#include <pcl/common/distances.h>
#include <pcl/common/point_tests.h> // for pcl::isFinite
#include <pcl/common/vector_average.h> // for VectorAverage3f
+#include <vector>
namespace pcl
{
int top=height, right=-1, bottom=-1, left=width;
doZBuffer (point_cloud, noise_level, min_range, top, right, bottom, left);
- cropImage (border_size, top, right, bottom, left);
+ if (border_size != std::numeric_limits<int>::min()) {
+ cropImage (border_size, top, right, bottom, left);
- recalculate3DPointPositions ();
+ recalculate3DPointPositions ();
+ }
}
/////////////////////////////////////////////////////////////////////////
int top=height, right=-1, bottom=-1, left=width;
doZBuffer (point_cloud, noise_level, min_range, top, right, bottom, left);
- cropImage (border_size, top, right, bottom, left);
+ if (border_size != std::numeric_limits<int>::min()) {
+ cropImage (border_size, top, right, bottom, left);
- recalculate3DPointPositions ();
+ recalculate3DPointPositions ();
+ }
}
/////////////////////////////////////////////////////////////////////////
const typename pcl::PointCloud<PointType2>::VectorType &points2 = point_cloud.points;
unsigned int size = width*height;
- int* counters = new int[size];
- ERASE_ARRAY (counters, size);
-
+ std::vector<int> counters(size, 0);
+
top=height; right=-1; bottom=-1; left=width;
float x_real, y_real, range_of_current_point;
if (isInImage (n_x, n_y))
{
int neighbor_array_pos = n_y*width + n_x;
- if (counters[neighbor_array_pos]==0)
+ if (counters[neighbor_array_pos] == 0)
{
float& neighbor_range = points[neighbor_array_pos].range;
neighbor_range = (std::isinf (neighbor_range) ? range_of_current_point : (std::min) (neighbor_range, range_of_current_point));
range_at_image_point += (range_of_current_point-range_at_image_point)/counter;
}
}
-
- delete[] counters;
}
/////////////////////////////////////////////////////////////////////////
{
Eigen::Vector3f transformedPoint = to_range_image_system_ * point;
range = transformedPoint.norm ();
+ if (range < std::numeric_limits<float>::epsilon()) {
+ PCL_DEBUG ("[pcl::RangeImage::getImagePoint] Transformed point is (0,0,0), cannot project it.\n");
+ image_x = image_y = 0.0f;
+ return;
+ }
float angle_x = atan2LookUp (transformedPoint[0], transformedPoint[2]),
angle_y = asinLookUp (transformedPoint[1]/range);
getImagePointFromAngles (angle_x, angle_y, image_x, image_y);
* but the mean of the points. If 0.0 it is equivalent to a normal z-buffer and
* will always take the minimum per cell.
* \param min_range the minimum visible range (defaults to 0)
- * \param border_size the border size (defaults to 0)
+ * \param border_size the border size (defaults to 0). Set to `std::numeric_limits<int>::min()` to turn cropping off.
*/
template <typename PointCloudType> void
createFromPointCloud (const PointCloudType& point_cloud, float angular_resolution=pcl::deg2rad (0.5f),
* but the mean of the points. If 0.0 it is equivalent to a normal z-buffer and
* will always take the minimum per cell.
* \param min_range the minimum visible range (defaults to 0)
- * \param border_size the border size (defaults to 0)
+ * \param border_size the border size (defaults to 0). Set to `std::numeric_limits<int>::min()` to turn cropping off.
*/
template <typename PointCloudType> void
createFromPointCloud (const PointCloudType& point_cloud,
* but the mean of the points. If 0.0 it is equivalent to a normal z-buffer and
* will always take the minimum per cell.
* \param min_range the minimum visible range (defaults to 0)
- * \param border_size the border size (defaults to 0)
+ * \param border_size the border size (defaults to 0). Set to `std::numeric_limits<int>::min()` to turn cropping off.
*/
template <typename PointCloudType> void
createFromPointCloudWithKnownSize (const PointCloudType& point_cloud, float angular_resolution,
* but the mean of the points. If 0.0 it is equivalent to a normal z-buffer and
* will always take the minimum per cell.
* \param min_range the minimum visible range (defaults to 0)
- * \param border_size the border size (defaults to 0)
+ * \param border_size the border size (defaults to 0). Set to `std::numeric_limits<int>::min()` to turn cropping off.
*/
template <typename PointCloudType> void
createFromPointCloudWithKnownSize (const PointCloudType& point_cloud,
* but the mean of the points. If 0.0 it is equivalent to a normal z-buffer and
* will always take the minimum per cell.
* \param min_range the minimum visible range (defaults to 0)
- * \param border_size the border size (defaults to 0)
+ * \param border_size the border size (defaults to 0). Set to `std::numeric_limits<int>::min()` to turn cropping off.
* \note If wrong_coordinate_system is true, the sensor pose will be rotated to change from a coordinate frame
* with x to the front, y to the left and z to the top to the coordinate frame we use here (x to the right, y
* to the bottom and z to the front) */
* but the mean of the points. If 0.0 it is equivalent to a normal z-buffer and
* will always take the minimum per cell.
* \param min_range the minimum visible range (defaults to 0)
- * \param border_size the border size (defaults to 0)
+ * \param border_size the border size (defaults to 0). Set to `std::numeric_limits<int>::min()` to turn cropping off.
* \note If wrong_coordinate_system is true, the sensor pose will be rotated to change from a coordinate frame
* with x to the front, y to the left and z to the top to the coordinate frame we use here (x to the right, y
* to the bottom and z to the front) */
/** Constructor */
PCL_EXPORTS RangeImagePlanar ();
/** Destructor */
- PCL_EXPORTS ~RangeImagePlanar ();
+ PCL_EXPORTS ~RangeImagePlanar () override;
/** Return a newly created RangeImagePlanar.
* Reimplementation to return an image of the same type. */
/** Constructor */
PCL_EXPORTS RangeImageSpherical () {}
/** Destructor */
- PCL_EXPORTS virtual ~RangeImageSpherical () {}
+ PCL_EXPORTS virtual ~RangeImageSpherical () = default;
/** Return a newly created RangeImagePlanar.
* Reimplementation to return an image of the same type. */
for (std::uint32_t i = 0; i < count; ++i)
p[i] /= scalar;
}
+
+ template<typename NoArrayT, typename ScalarT> inline
+ std::enable_if_t<!std::is_array<NoArrayT>::value>
+ divscalar2 (NoArrayT &p, const ScalarT &scalar)
+ {
+ p = scalar / p;
+ }
+
+ template<typename ArrayT, typename ScalarT> inline
+ std::enable_if_t<std::is_array<ArrayT>::value>
+ divscalar2 (ArrayT &p, const ScalarT &scalar)
+ {
+ using type = std::remove_all_extents_t<ArrayT>;
+ static const std::uint32_t count = sizeof (ArrayT) / sizeof (type);
+ for (std::uint32_t i = 0; i < count; ++i)
+ p[i] = scalar / p[i];
+ }
}
}
scalar);
/***/
+#define PCL_DIVEQSC2_POINT_TAG(r, data, elem) \
+ pcl::traits::divscalar2 (p.BOOST_PP_TUPLE_ELEM(3, 1, elem), \
+ scalar);
+ /***/
+
// Construct type traits given full sequence of (type, name, tag) triples
// BOOST_MPL_ASSERT_MSG(std::is_pod<name>::value,
// REGISTERED_POINT_TYPE_MUST_BE_PLAIN_OLD_DATA, (name));
inline const name operator+ (const name& p, const float& scalar) \
{ name result = p; result += scalar; return (result); } \
inline const name& \
+ operator*= (name& p, const float& scalar) \
+ { \
+ BOOST_PP_SEQ_FOR_EACH(PCL_MULEQSC_POINT_TAG, _, seq) \
+ return (p); \
+ } \
+ inline const name operator* (const float& scalar, const name& p) \
+ { name result = p; result *= scalar; return (result); } \
+ inline const name operator* (const name& p, const float& scalar) \
+ { name result = p; result *= scalar; return (result); } \
+ inline const name& \
operator-= (name& lhs, const name& rhs) \
{ \
BOOST_PP_SEQ_FOR_EACH(PCL_MINUSEQ_POINT_TAG, _, seq) \
inline const name operator- (const name& lhs, const name& rhs) \
{ name result = lhs; result -= rhs; return (result); } \
inline const name operator- (const float& scalar, const name& p) \
- { name result = p; result -= scalar; return (result); } \
+ { name result = p; result *= -1.0f; result += scalar; return (result); } \
inline const name operator- (const name& p, const float& scalar) \
{ name result = p; result -= scalar; return (result); } \
inline const name& \
- operator*= (name& p, const float& scalar) \
- { \
- BOOST_PP_SEQ_FOR_EACH(PCL_MULEQSC_POINT_TAG, _, seq) \
- return (p); \
- } \
- inline const name operator* (const float& scalar, const name& p) \
- { name result = p; result *= scalar; return (result); } \
- inline const name operator* (const name& p, const float& scalar) \
- { name result = p; result *= scalar; return (result); } \
- inline const name& \
operator/= (name& p, const float& scalar) \
{ \
BOOST_PP_SEQ_FOR_EACH(PCL_DIVEQSC_POINT_TAG, _, seq) \
return (p); \
} \
- inline const name operator/ (const float& scalar, const name& p) \
- { name result = p; result /= scalar; return (result); } \
+ inline const name operator/ (const float& scalar, const name& p_in) \
+ { name p = p_in; BOOST_PP_SEQ_FOR_EACH(PCL_DIVEQSC2_POINT_TAG, _, seq) \
+ return (p); } \
inline const name operator/ (const name& p, const float& scalar) \
{ name result = p; result /= scalar; return (result); } \
} \
static const std::uint8_t INT8 = 1, UINT8 = 2,
INT16 = 3, UINT16 = 4,
INT32 = 5, UINT32 = 6,
- FLOAT32 = 7, FLOAT64 = 8;
+ FLOAT32 = 7, FLOAT64 = 8,
+ INT64 = 9, UINT64 = 10,
+ BOOL = 11;
};
- }
+ } // namespace detail
// Metafunction to return enum value representing a type
template<typename T> struct asEnum {};
+ template<> struct asEnum<bool> { static const std::uint8_t value = detail::PointFieldTypes::BOOL; };
template<> struct asEnum<std::int8_t> { static const std::uint8_t value = detail::PointFieldTypes::INT8; };
template<> struct asEnum<std::uint8_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT8; };
template<> struct asEnum<std::int16_t> { static const std::uint8_t value = detail::PointFieldTypes::INT16; };
template<> struct asEnum<std::uint16_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT16; };
template<> struct asEnum<std::int32_t> { static const std::uint8_t value = detail::PointFieldTypes::INT32; };
template<> struct asEnum<std::uint32_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT32; };
- template<> struct asEnum<float> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT32; };
- template<> struct asEnum<double> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT64; };
+ template<> struct asEnum<std::int64_t> { static const std::uint8_t value = detail::PointFieldTypes::INT64; };
+ template<> struct asEnum<std::uint64_t> { static const std::uint8_t value = detail::PointFieldTypes::UINT64; };
+ template<> struct asEnum<float> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT32; };
+ template<> struct asEnum<double> { static const std::uint8_t value = detail::PointFieldTypes::FLOAT64; };
template<typename T>
static constexpr std::uint8_t asEnum_v = asEnum<T>::value;
// Metafunction to return type of enum value
template<int> struct asType {};
+ template<> struct asType<detail::PointFieldTypes::BOOL> { using type = bool; };
template<> struct asType<detail::PointFieldTypes::INT8> { using type = std::int8_t; };
template<> struct asType<detail::PointFieldTypes::UINT8> { using type = std::uint8_t; };
template<> struct asType<detail::PointFieldTypes::INT16> { using type = std::int16_t; };
template<> struct asType<detail::PointFieldTypes::UINT16> { using type = std::uint16_t; };
template<> struct asType<detail::PointFieldTypes::INT32> { using type = std::int32_t; };
template<> struct asType<detail::PointFieldTypes::UINT32> { using type = std::uint32_t; };
+ template<> struct asType<detail::PointFieldTypes::INT64> { using type = std::int64_t; };
+ template<> struct asType<detail::PointFieldTypes::UINT64> { using type = std::uint64_t; };
template<> struct asType<detail::PointFieldTypes::FLOAT32> { using type = float; };
template<> struct asType<detail::PointFieldTypes::FLOAT64> { using type = double; };
number_of_bins_ = number_of_bins;
}
-pcl::FeatureHistogram::~FeatureHistogram ()
-{
-
-}
+pcl::FeatureHistogram::~FeatureHistogram () = default;
float
pcl::FeatureHistogram::getThresholdMin () const
++number_of_elements_;
// Increase the bin.
- std::size_t bin_number = static_cast<std::size_t> ((value - threshold_min_) / step_);
+ auto bin_number = static_cast<std::size_t> ((value - threshold_min_) / step_);
++histogram_[bin_number];
}
}
#if (defined _OPENMP && (_OPENMP <= 201307)) || (defined __GNUC__ && (__GNUC__ >= 6 && __GNUC__ < 9))
#pragma omp parallel for \
default(none) \
- shared(f, factors, Fout, in_stride)
+ shared(f, factors, Fout, in_stride) \
+ private(k)
#else
#pragma omp parallel for \
default(none) \
- shared(f, factors, Fout, fstride, in_stride, m, p, st)
+ shared(f, factors, Fout, fstride, in_stride, m, p, st) \
+ private(k)
#endif
for (k=0;k<p;++k)
kf_work( Fout +k*m, f+ fstride*in_stride*k,fstride*p,in_stride,factors,st);
const pcl::PCLPointField& f = *cloud1_unique_fields[i];
int local_data_size = f.count * pcl::getFieldSize (f.datatype);
int padding_size = field_sizes[i] - local_data_size;
-
+
memcpy (&cloud_out.data[point_offset + field_offset], &cloud1.data[cp * cloud1.point_step + f.offset], local_data_size);
field_offset += local_data_size;
//make sure that we add padding when its needed
- if (padding_size > 0)
- memset (&cloud_out.data[point_offset + field_offset], 0, padding_size);
+ if (padding_size > 0) {
+ std::fill_n(&cloud_out.data[point_offset + field_offset], padding_size, 0);
+ }
field_offset += padding_size;
}
point_offset += field_offset;
int
parse_argument (int argc, const char * const * argv, const char * str, unsigned long long int &val) noexcept
{
- long long int dummy;
+ long long int dummy = -1;
const auto ret = parse_argument (argc, argv, str, dummy);
if ((ret == -1) || dummy < 0)
{
#include <numeric>
#include <pcl/impl/pcl_base.hpp>
+#include <pcl/common/io.h> // for getFieldSize
///////////////////////////////////////////////////////////////////////////////////////////
pcl::PCLBase<pcl::PCLPointCloud2>::PCLBase ()
// Obtain the size of datatype
const auto sizeofDatatype = [](const auto& datatype) -> int
{
- switch (datatype)
- {
- case pcl::PCLPointField::INT8:
- case pcl::PCLPointField::UINT8: return 1;
-
- case pcl::PCLPointField::INT16:
- case pcl::PCLPointField::UINT16: return 2;
-
- case pcl::PCLPointField::INT32:
- case pcl::PCLPointField::UINT32:
- case pcl::PCLPointField::FLOAT32: return 4;
-
- case pcl::PCLPointField::FLOAT64: return 8;
-
- default:
+ const auto size = getFieldSize(datatype);
+ if (size == 0) {
PCL_ERROR("[PCLBase::setInputCloud] Invalid field type (%d)!\n", datatype);
- return 0;
}
+ return size;
};
- // Restrict size of a field to be at-max sizeof(FLOAT32) for now
+ // Restrict size of a field to be at-max sizeof(FLOAT64) now to support {U}INT64
field_sizes_.resize(input_->fields.size());
std::transform(input_->fields.begin(), input_->fields.end(), field_sizes_.begin(),
[&sizeofDatatype](const auto& field)
{
- return std::min(sizeofDatatype(field.datatype), static_cast<int>(sizeof(float)));
+ return std::min(sizeofDatatype(field.datatype), static_cast<int>(sizeof(double)));
});
}
Eigen::Matrix3f cam = KR_KRT / KR_KRT.coeff (8);
- memset (&(camera_matrix.coeffRef (0)), 0, sizeof (Eigen::Matrix3f::Scalar) * 9);
+ camera_matrix.setZero();
camera_matrix.coeffRef (8) = 1.0;
if (camera_matrix.Flags & Eigen::RowMajorBit)
#include <pcl/common/time.h> // for MEASURE_FUNCTION_TIME
#include <pcl/range_image/range_image.h>
+#include <algorithm>
+
namespace pcl
{
int no_of_pixels = pixel_size*pixel_size;
float* surface_patch = new float[no_of_pixels];
- SET_ARRAY (surface_patch, -std::numeric_limits<float>::infinity (), no_of_pixels);
-
+ std::fill_n(surface_patch, no_of_pixels, -std::numeric_limits<float>::infinity ());
+
Eigen::Vector3f position = inverse_pose.translation ();
int middle_x, middle_y;
getImagePoint (position, middle_x, middle_y);
}
/////////////////////////////////////////////////////////////////////////
- RangeImagePlanar::~RangeImagePlanar ()
- {
- }
+ RangeImagePlanar::~RangeImagePlanar () = default;
/////////////////////////////////////////////////////////////////////////
void
std::cerr << __PRETTY_FUNCTION__<<": Given range image is not a RangeImagePlanar!\n";
return;
}
- RangeImagePlanar& ret = * (static_cast<RangeImagePlanar*> (&half_image));
+ RangeImagePlanar& ret = * (dynamic_cast<RangeImagePlanar*> (&half_image));
ret.focal_length_x_ = focal_length_x_/2;
ret.focal_length_x_reciprocal_ = 1.0f/ret.focal_length_x_;
std::cerr << __PRETTY_FUNCTION__<<": Given range image is not a RangeImagePlanar!\n";
return;
}
- RangeImagePlanar& ret = * (static_cast<RangeImagePlanar*> (&sub_image));
+ RangeImagePlanar& ret = * (dynamic_cast<RangeImagePlanar*> (&sub_image));
ret.focal_length_x_ = focal_length_x_ / static_cast<float> (combine_pixels);
ret.focal_length_x_reciprocal_ = 1.0f / ret.focal_length_x_;
std::cerr << PVARC(typeid (*this).name())<<PVARN(typeid (other).name());
}
assert (ERROR_GIVEN_RANGE_IMAGE_IS_NOT_A_RangeImagePlanar);
- *static_cast<RangeImagePlanar*> (&other) = *this;
+ *dynamic_cast<RangeImagePlanar*> (&other) = *this;
}
} // namespace end
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
if(NOT build)
return()
typename Storage<int>::type region_mask;
markInliers<Storage> (data, region_mask, planes);
thrust::host_vector<int> regions_host;
- std::copy (regions_host.begin (), regions_host.end(), std::ostream_iterator<int>(std::cerr, " "));
+ std::copy (regions_host.cbegin (), regions_host.cend(), std::ostream_iterator<int>(std::cerr, " "));
{
ScopeTimeCPU t ("retrieving inliers");
planes = sac.getAllInliers ();
typename Storage<int>::type region_mask;
markInliers<Storage> (data, region_mask, planes);
thrust::host_vector<int> regions_host;
- std::copy (regions_host.begin (), regions_host.end(), std::ostream_iterator<int>(std::cerr, " "));
+ std::copy (regions_host.cbegin (), regions_host.cend(), std::ostream_iterator<int>(std::cerr, " "));
{
ScopeTimeCPU t ("retrieving inliers");
planes = sac.getAllInliers ();
set(build TRUE)
PCL_SUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSYS_DESC} ON)
mark_as_advanced("BUILD_${SUBSYS_NAME}")
-PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR(${SUBSYS_NAME} ${SUBSYS_PATH})
## ---[ Point Cloud Library - pcl/cuda/common
#include <pcl/cuda/cutil_math.h>
#include <limits>
-#include <float.h>
namespace pcl
{
inline __host__ __device__ bool isMuchSmallerThan (float x, float y)
{
- float prec_sqr = FLT_EPSILON * FLT_EPSILON; // copied from <eigen>/include/Eigen/src/Core/NumTraits.h
+ // inspired by Eigen's implementation
+ float prec_sqr =
+ std::numeric_limits<float>::epsilon() * std::numeric_limits<float>::epsilon();
return x * x <= prec_sqr * y * y;
}
float c2 = m.data[0].x + m.data[1].y + m.data[2].z;
- if (std::abs(c0) < FLT_EPSILON) // one root is 0 -> quadratic equation
+ if (std::abs(c0) < std::numeric_limits<float>::epsilon()) // one root is 0 -> quadratic equation
computeRoots2 (c2, c1, roots);
else
{
//Scalar scale = mat.cwiseAbs ().maxCoeff ();
float3 scale_tmp = fmaxf (fmaxf (fabs (mat.data[0]), fabs (mat.data[1])), fabs (mat.data[2]));
float scale = fmaxf (fmaxf (scale_tmp.x, scale_tmp.y), scale_tmp.z);
- if (scale <= FLT_MIN)
+ if (scale <= std::numeric_limits<float>::min())
scale = 1.0f;
CovarianceMatrix scaledMat;
// Compute the eigenvalues
computeRoots (scaledMat, evals);
- if ((evals.z-evals.x) <= FLT_EPSILON)
+ if ((evals.z - evals.x) <= std::numeric_limits<float>::epsilon())
{
// all three equal
evecs.data[0] = make_float3 (1.0f, 0.0f, 0.0f);
evecs.data[1] = make_float3 (0.0f, 1.0f, 0.0f);
evecs.data[2] = make_float3 (0.0f, 0.0f, 1.0f);
}
- else if ((evals.y-evals.x) <= FLT_EPSILON)
+ else if ((evals.y - evals.x) <= std::numeric_limits<float>::epsilon())
{
// first and second equal
CovarianceMatrix tmp;
evecs.data[1] = unitOrthogonal (evecs.data[2]);
evecs.data[0] = cross (evecs.data[1], evecs.data[2]);
}
- else if ((evals.z-evals.y) <= FLT_EPSILON)
+ else if ((evals.z - evals.y) <= std::numeric_limits<float>::epsilon())
{
// second and third equal
CovarianceMatrix tmp;
return (r == rhs.r && g == rhs.g && b == rhs.b && alpha == rhs.alpha);
}
- inline __host__ __device__ RGB& operator - (RGB &rhs)
+ inline __host__ __device__ RGB operator - (RGB &rhs)
{
- r = -r;
- g = -g;
- b = -b;
- alpha = -alpha;
- return (*this);
+ RGB res = *this;
+ res -= rhs;
+ return (res);
}
inline __host__ __device__ RGB& operator += (const RGB &rhs)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
mark_as_advanced("BUILD_${SUBSYS_NAME}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
if(NOT build)
#pragma once
#include <pcl_cuda/pcl_cuda_base.h>
-#include <float.h>
+#include <limits>
namespace pcl_cuda
{
/** \brief Empty constructor. */
Filter () : filter_field_name_ (""),
- filter_limit_min_ (-FLT_MAX), filter_limit_max_ (FLT_MAX),
+ filter_limit_min_ (std::numeric_limits<float>::lowest()),
+ filter_limit_max_ (std::numeric_limits<float>::max()),
filter_limit_negative_ (false)
{};
}
/** \brief Get the field filter limits (min/max) set by the user.
- * The default values are -FLT_MAX, FLT_MAX.
+ * The default values are std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max().
* \param limit_min the minimum limit
* \param limit_max the maximum limit
*/
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" OFF)
mark_as_advanced("BUILD_${SUBSYS_NAME}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS ${SUBSYS_EXT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS ${SUBSYS_EXT_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
if(NOT build)
// if (!output)
// output.reset (new PointCloudAOS<Device>);
//
-// using namespace thrust;
-//
// // Prepare the output
// output->height = depth_image->height;
// output->width = depth_image->width;
//
// // Send the data to the device
// transform (
-// make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), counting_iterator<int>(0))),
-// make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), counting_iterator<int>(0))) +
+// thrust::make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), thrust::counting_iterator<int>(0))),
+// thrust::make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), thrust::counting_iterator<int>(0))) +
// depth_image->width * depth_image->height,
// output->points.begin (),
// ComputeXYZRGB (depth_image->width, depth_image->height,
// {
// // Send the data to the device
// transform (
-// make_zip_iterator (make_tuple (depth.begin (), counting_iterator<int>(0))),
-// make_zip_iterator (make_tuple (depth.begin (), counting_iterator<int>(0))) +
+// thrust::make_zip_iterator (make_tuple (depth.begin (), thrust::counting_iterator<int>(0))),
+// thrust::make_zip_iterator (make_tuple (depth.begin (), thrust::counting_iterator<int>(0))) +
// depth_image->width * depth_image->height,
// output->points.begin (),
// ComputeXYZ (depth_image->width, depth_image->height,
typename PointCloudAOS<Storage>::Ptr &output,
int smoothing_nr_iterations, int smoothing_filter_size)
{
- using namespace thrust;
if (!output)
output.reset (new PointCloudAOS<Storage>);
{
typename Storage<float3>::type disp_helper_map (output_size);
- float* depth_ptr = raw_pointer_cast(&depth[0]);
+ float* depth_ptr = thrust::raw_pointer_cast(&depth[0]);
- transform (counting_iterator<int>(0),
- counting_iterator<int>(0) + output_size,
+ transform (thrust::counting_iterator<int>(0),
+ thrust::counting_iterator<int>(0) + output_size,
disp_helper_map.begin (),
DisparityHelperMap (depth_ptr, width, height, smoothing_filter_size, baseline, 1.0f/constant, disp_thresh));
for (int iter = 0; iter < smoothing_nr_iterations; iter++)
{
transform (
- make_zip_iterator (make_tuple (depth.begin (), counting_iterator<int>(0))),
- make_zip_iterator (make_tuple (depth.begin (), counting_iterator<int>(0))) + output_size,
- depth.begin (), DisparityClampedSmoothing (raw_pointer_cast(&depth[0]), raw_pointer_cast(&disp_helper_map[0]), width, height, smoothing_filter_size));
+ thrust::make_zip_iterator (make_tuple (depth.begin (), thrust::counting_iterator<int>(0))),
+ thrust::make_zip_iterator (make_tuple (depth.begin (), thrust::counting_iterator<int>(0))) + output_size,
+ depth.begin (), DisparityClampedSmoothing (thrust::raw_pointer_cast(&depth[0]), thrust::raw_pointer_cast(&disp_helper_map[0]), width, height, smoothing_filter_size));
}
// Send the data to the device
transform (
- make_zip_iterator (make_tuple (depth.begin (), rgb.begin(), counting_iterator<int>(0))),
- make_zip_iterator (make_tuple (depth.begin (), rgb.begin(), counting_iterator<int>(0))) + output_size,
+ thrust::make_zip_iterator (make_tuple (depth.begin (), rgb.begin(), thrust::counting_iterator<int>(0))),
+ thrust::make_zip_iterator (make_tuple (depth.begin (), rgb.begin(), thrust::counting_iterator<int>(0))) + output_size,
output->points.begin (),
ComputeXYZRGB (width, height,
width >> 1, height >> 1, constant));
else
{
transform (
- make_zip_iterator (make_tuple (depth.begin(), rgb.begin(), counting_iterator<int>(0))),
- make_zip_iterator (make_tuple (depth.begin(), rgb.begin(), counting_iterator<int>(0))) + output_size,
+ thrust::make_zip_iterator (make_tuple (depth.begin(), rgb.begin(), thrust::counting_iterator<int>(0))),
+ thrust::make_zip_iterator (make_tuple (depth.begin(), rgb.begin(), thrust::counting_iterator<int>(0))) + output_size,
output->points.begin (),
ComputeXYZRGB (width, height,
width >> 1, height >> 1, constant));
if (!output)
output.reset (new PointCloudAOS<Storage>);
- using namespace thrust;
-
int depth_width = depth_image->getWidth ();
int depth_height = depth_image->getHeight ();
thrust::counting_iterator<int> counter (0);
//typename Storage<int>::type downsampled_indices;
//downsampled_indices.resize ((output->width/2) * (output->height/2));
- //thrust::copy_if (counting_iterator<int>(0), counting_iterator<int>(0)+depth_width*depth_height, downsampled_indices.begin (), downsampleIndices (output->width, output->height, 2));
+ //thrust::copy_if (thrust::counting_iterator<int>(0), thrust::counting_iterator<int>(0)+depth_width*depth_height, downsampled_indices.begin (), downsampleIndices (output->width, output->height, 2));
thrust::copy_if (depth_device.begin (),
depth_device.end (),
//thrust::make_constant_iterator (12), thrust::make_constant_iterator (12) + depth_width * depth_height,
#if 1
typename Storage<float3>::type disp_helper_map (output_size);
- transform (counting_iterator<int>(0),
- counting_iterator<int>(0) + output_size,
+ transform (thrust::counting_iterator<int>(0),
+ thrust::counting_iterator<int>(0) + output_size,
disp_helper_map.begin (),
DisparityHelperMap (thrust::raw_pointer_cast(&depth[0]), output->width, output->height, smoothing_filter_size, baseline, 1.0f/constant, disp_thresh));
for (int iter = 0; iter < smoothing_nr_iterations; iter++)
{
transform (
- make_zip_iterator (make_tuple (depth.begin (), counting_iterator<int>(0))),
- make_zip_iterator (make_tuple (depth.begin (), counting_iterator<int>(0))) + output_size,
- depth.begin (), DisparityClampedSmoothing (raw_pointer_cast(&depth[0]), raw_pointer_cast(&disp_helper_map[0]), output->width, output->height, smoothing_filter_size));
+ thrust::make_zip_iterator (make_tuple (depth.begin (), thrust::counting_iterator<int>(0))),
+ thrust::make_zip_iterator (make_tuple (depth.begin (), thrust::counting_iterator<int>(0))) + output_size,
+ depth.begin (), DisparityClampedSmoothing (thrust::raw_pointer_cast(&depth[0]), thrust::raw_pointer_cast(&disp_helper_map[0]), output->width, output->height, smoothing_filter_size));
}
// Send the data to the device
transform (
- make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), counting_iterator<int>(0))),
- make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), counting_iterator<int>(0))) + output_size,
+ thrust::make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), thrust::counting_iterator<int>(0))),
+ thrust::make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), thrust::counting_iterator<int>(0))) + output_size,
output->points.begin (),
ComputeXYZRGB (output->width, output->height,
output->width >> 1, output->height >> 1, constant));
// typename Storage<float>::type smooth_depth1 (output_size);
// typename Storage<float>::type smooth_depth2 (output_size);
//
-// transform (counting_iterator<int>(0),
-// counting_iterator<int>(0) + output_size,
+// transform (thrust::counting_iterator<int>(0),
+// thrust::counting_iterator<int>(0) + output_size,
// smooth_depth1.begin (),
// DisparityBoundSmoothing (output->width, output->height, smoothing_filter_size, 1.0f/constant, baseline, disp_thresh, thrust::raw_pointer_cast<float>(&depth[0]), thrust::raw_pointer_cast<float>(&depth[0])));
//
// for (int iter = 0; iter < (smoothing_nr_iterations-1)/2; iter++)
// {
-// transform (counting_iterator<int>(0),
-// counting_iterator<int>(0) + output_size,
+// transform (thrust::counting_iterator<int>(0),
+// thrust::counting_iterator<int>(0) + output_size,
// smooth_depth2.begin (),
// DisparityBoundSmoothing (output->width, output->height, smoothing_filter_size, 1.0f/constant, baseline, disp_thresh, thrust::raw_pointer_cast<float>(&smooth_depth1[0]), thrust::raw_pointer_cast<float>(&depth[0])));
-// transform (counting_iterator<int>(0),
-// counting_iterator<int>(0) + output_size,
+// transform (thrust::counting_iterator<int>(0),
+// thrust::counting_iterator<int>(0) + output_size,
// smooth_depth1.begin (),
// DisparityBoundSmoothing (output->width, output->height, smoothing_filter_size, 1.0f/constant, baseline, disp_thresh, thrust::raw_pointer_cast<float>(&smooth_depth2[0]), thrust::raw_pointer_cast<float>(&depth[0])));
// }
//
// // Send the data to the device
// transform (
-// make_zip_iterator (make_tuple (smooth_depth1.begin (), rgb.begin (), counting_iterator<int>(0))),
-// make_zip_iterator (make_tuple (smooth_depth1.begin (), rgb.begin (), counting_iterator<int>(0))) + output_size,
+// thrust::make_zip_iterator (make_tuple (smooth_depth1.begin (), rgb.begin (), thrust::counting_iterator<int>(0))),
+// thrust::make_zip_iterator (make_tuple (smooth_depth1.begin (), rgb.begin (), thrust::counting_iterator<int>(0))) + output_size,
// output->points.begin (),
// ComputeXYZRGB (output->width, output->height,
// output->width >> 1, output->height >> 1, constant));
{
// Send the data to the device
transform (
- make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), counting_iterator<int>(0))),
- make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), counting_iterator<int>(0))) + output_size,
+ thrust::make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), thrust::counting_iterator<int>(0))),
+ thrust::make_zip_iterator (make_tuple (depth.begin (), rgb.begin (), thrust::counting_iterator<int>(0))) + output_size,
output->points.begin (),
ComputeXYZRGB (output->width, output->height,
output->width >> 1, output->height >> 1, constant));
{
// Send the data to the device
transform (
- make_zip_iterator (make_tuple (depth.begin (), counting_iterator<int>(0))),
- make_zip_iterator (make_tuple (depth.begin (), counting_iterator<int>(0))) +
+ thrust::make_zip_iterator (make_tuple (depth.begin (), thrust::counting_iterator<int>(0))),
+ thrust::make_zip_iterator (make_tuple (depth.begin (), thrust::counting_iterator<int>(0))) +
output->width * output->height,
output->points.begin (),
ComputeXYZ (output->width, output->height,
// if (!output)
// output.reset (new PointCloudAOS<Device>);
//
- // using namespace thrust;
- //
// // Prepare the output
// output->height = depth_image->height;
// output->width = depth_image->width;
if (!output)
output.reset (new PointCloudAOS<Storage>);
- using namespace thrust;
-
int depth_width = depth_image->getWidth ();
int depth_height = depth_image->getHeight ();
#include <pcl/point_types.h>
#include <algorithm>
+#include <limits>
#include <queue>
#include <vector>
/** \brief Empty deconstructor. */
virtual
- ~OrganizedNeighborSearch ()
- {
- }
+ ~OrganizedNeighborSearch() = default;
// public typedefs
using PointCloud = pcl::PointCloud<PointT>;
int
radiusSearch (const PointCloudConstPtr &cloud_arg, int index_arg, double radius_arg,
std::vector<int> &k_indices_arg, std::vector<float> &k_sqr_distances_arg,
- int max_nn_arg = INT_MAX);
+ int max_nn_arg = std::numeric_limits<int>::max());
/** \brief Search for all neighbors of query point that are within a given radius.
* \param index_arg index representing the query point in the dataset given by \a setInputCloud.
*/
int
radiusSearch (int index_arg, const double radius_arg, std::vector<int> &k_indices_arg,
- std::vector<float> &k_sqr_distances_arg, int max_nn_arg = INT_MAX) const;
+ std::vector<float> &k_sqr_distances_arg, int max_nn_arg = std::numeric_limits<int>::max()) const;
/** \brief Search for all neighbors of query point that are within a given radius.
* \param p_q_arg the given query point
*/
int
radiusSearch (const PointT &p_q_arg, const double radius_arg, std::vector<int> &k_indices_arg,
- std::vector<float> &k_sqr_distances_arg, int max_nn_arg = INT_MAX) const;
+ std::vector<float> &k_sqr_distances_arg, int max_nn_arg = std::numeric_limits<int>::max()) const;
/** \brief Search for k-nearest neighbors at the query point.
* \param cloud_arg the point cloud data
{
}
- /** \brief Empty deconstructor */
- ~radiusSearchLoopkupEntry ()
- {
- }
-
/** \brief Define search point and calculate squared distance
* @param x_shift shift in x dimension
* @param y_shift shift in y dimension
{
}
- /** \brief Empty deconstructor */
- ~nearestNeighborCandidate ()
- {
- }
-
/** \brief Operator< for comparing nearestNeighborCandidate instances with each other. */
bool
operator< (const nearestNeighborCandidate& rhs_arg) const
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
mark_as_advanced("BUILD_${SUBSYS_NAME}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
if(NOT build)
#include <pcl/cuda/sample_consensus/sac_model.h>
#include <pcl/cuda/point_cloud.h>
-#include <cfloat>
+#include <limits>
//#include <set>
namespace pcl
* \param model a Sample Consensus model
*/
SampleConsensus (const SampleConsensusModelPtr &model) :
- sac_model_(model), probability_ (0.99), iterations_ (0), threshold_ (DBL_MAX),
- max_iterations_ (1000)
+ sac_model_(model), probability_(0.99), iterations_(0),
+ threshold_(std::numeric_limits<double>::max()), max_iterations_(1000)
{};
/** \brief Constructor for base SAC.
{};
/** \brief Destructor for base SAC. */
- virtual ~SampleConsensus () {};
+ virtual ~SampleConsensus() = default;
/** \brief Set the distance to model threshold.
* \param threshold distance to model threshold
#pragma once
-#include <float.h>
+#include <limits>
#include <thrust/sequence.h>
#include <thrust/count.h>
#include <thrust/remove.h>
private:
/** \brief Empty constructor for base SampleConsensusModel. */
- SampleConsensusModel () : radius_min_ (-FLT_MAX), radius_max_ (FLT_MAX)
+ SampleConsensusModel() :
+ radius_min_(std::numeric_limits<float>::lowest()),
+ radius_max_(std::numeric_limits<float>::max())
{};
public:
* \param cloud the input point cloud dataset
*/
SampleConsensusModel (const PointCloudConstPtr &cloud) :
- radius_min_ (-FLT_MAX), radius_max_ (FLT_MAX)
+ radius_min_(std::numeric_limits<float>::lowest()),
+ radius_max_(std::numeric_limits<float>::max())
{
// Sets the input cloud and creates a vector of "fake" indices
setInputCloud (cloud);
/* SampleConsensusModel (const PointCloudConstPtr &cloud, const std::vector<int> &indices) :
input_ (cloud),
indices_ (boost::make_shared <std::vector<int> > (indices)),
- radius_min_ (-DBL_MAX), radius_max_ (DBL_MAX)
+ radius_min_ (std::numeric_limits<double>::lowest()),
+ radius_max_ (std::numeric_limits<double>::max())
{
if (indices_->size () > input_->points.size ())
};*/
/** \brief Destructor for base SampleConsensusModel. */
- virtual ~SampleConsensusModel () {};
+ virtual ~SampleConsensusModel() = default;
/** \brief Get a set of random data samples and return them as point
* indices. Pure virtual.
#include <pcl_cuda/sample_consensus/multi_ransac.h>
#include <pcl_cuda/time_gpu.h>
#include <stdio.h>
+#include <limits>
//CUPRINTF #include "cuPrintf.cu"
int min_nr_in_shape = 5000;
pcl_cuda::MultiRandomSampleConsensus<Storage>::computeModel (int debug_verbosity_level)
{
// Warn and exit if no threshold was set
- if (threshold_ == DBL_MAX)
+ if (threshold_ == std::numeric_limits<double>::max())
{
std::cerr << "[pcl_cuda::MultiRandomSampleConsensus::computeModel] No threshold set!" << std::endl;
return (false);
# include <windows.h>
#endif
-#include <pcl/pcl_exports.h>
-
-#include "pcl/cuda/sample_consensus/multi_ransac.h"
-#include "pcl/cuda/time_gpu.h"
#include <stdio.h>
+#include <limits>
+
+#include <pcl/pcl_exports.h>
+#include <pcl/cuda/sample_consensus/multi_ransac.h>
+#include <pcl/cuda/time_gpu.h>
#include <pcl/cuda/time_cpu.h>
//CUPRINTF #include "cuPrintf.cu"
double starttime = pcl::cuda::getTime ();
int counter = 0;
// Warn and exit if no threshold was set
- if (threshold_ == DBL_MAX)
+ if (threshold_ == std::numeric_limits<double>::max())
{
std::cerr << "[pcl::cuda::MultiRandomSampleConsensus::computeModel] No threshold set!" << std::endl;
return (false);
#include "pcl/cuda/sample_consensus/ransac.h"
#include "pcl/cuda/time_gpu.h"
#include <stdio.h>
+#include <limits>
namespace pcl
{
RandomSampleConsensus<Storage>::computeModel (int debug_verbosity_level)
{
// Warn and exit if no threshold was set
- if (threshold_ == DBL_MAX)
+ if (threshold_ == std::numeric_limits<double>::max())
{
std::cerr << "[pcl::cuda::RandomSampleConsensus::computeModel] No threshold set!" << std::endl;
return (false);
}
iterations_ = 0;
- int n_best_inliers_count = -INT_MAX;
+ int n_best_inliers_count = std::numeric_limits<int>::lowest();
float k = 1.0;
Indices inliers;
SampleConsensusModel1PointPlane<Storage>::generateModelHypotheses (
Hypotheses &h, int max_iterations)
{
- using namespace thrust;
-
// Create a vector of how many samples/coefficients do we want to get
h.resize (max_iterations);
SampleConsensusModel1PointPlane<Storage>::generateModelHypotheses (
Hypotheses &h, Samples &samples, int max_iterations)
{
- using namespace thrust;
-
// Create a vector of how many samples/coefficients do we want to get
h.resize (max_iterations);
samples.resize (max_iterations);
SampleConsensusModel1PointPlane<Storage>::countWithinDistance (
const Coefficients &model_coefficients, float threshold)
{
- using namespace thrust;
-
// Needs a valid set of model coefficients
if (model_coefficients.size () != 4)
{
SampleConsensusModel1PointPlane<Storage>::selectWithinDistance (
const Coefficients &model_coefficients, float threshold, IndicesPtr &inliers, IndicesPtr &inliers_stencil)
{
- using namespace thrust;
-
// Needs a valid set of model coefficients
if (model_coefficients.size () != 4)
{
SampleConsensusModel1PointPlane<Storage>::selectWithinDistance (
const Hypotheses &h, int idx, float threshold, IndicesPtr &inliers, IndicesPtr &inliers_stencil)
{
- using namespace thrust;
-
// Needs a valid set of model coefficients
/* if (model_coefficients.size () != 4)
{
Hypotheses &h, int idx, float threshold, IndicesPtr &inliers_stencil, float3 &c)
{
float angle_threshold = 0.26f;
- using namespace thrust;
int nr_points = (int) indices_stencil_->size ();
float bad_point = std::numeric_limits<float>::quiet_NaN ();
SampleConsensusModelPlane<Storage>::generateModelHypotheses (
Hypotheses &h, int max_iterations)
{
- using namespace thrust;
-
// Create a vector of how many samples/coefficients do we want to get
h.resize (max_iterations);
SampleConsensusModelPlane<Storage>::countWithinDistance (
const Coefficients &model_coefficients, float threshold)
{
- using namespace thrust;
-
// Needs a valid set of model coefficients
if (model_coefficients.size () != 4)
{
SampleConsensusModelPlane<Storage>::selectWithinDistance (
const Coefficients &model_coefficients, float threshold, IndicesPtr &inliers, IndicesPtr &inliers_stencil)
{
- using namespace thrust;
-
// Needs a valid set of model coefficients
if (model_coefficients.size () != 4)
{
SampleConsensusModelPlane<Storage>::selectWithinDistance (
const Hypotheses &h, int idx, float threshold, IndicesPtr &inliers, IndicesPtr &inliers_stencil)
{
- using namespace thrust;
-
// Needs a valid set of model coefficients
/* if (model_coefficients.size () != 4)
{
SampleConsensusModelPlane<Storage>::selectWithinDistance (
Hypotheses &h, int idx, float threshold, IndicesPtr &inliers_stencil, float3 & centroid)
{
- using namespace thrust;
-
// Needs a valid set of model coefficients
/* if (model_coefficients.size () != 4)
{
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
mark_as_advanced("BUILD_${SUBSYS_NAME}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
Boost::Iostreams.
* Given the experience on `libpointmatcher <https://github.com/ethz-asl/libpointmatcher>`_,
we (François Pomerleau and Stéphane Magnenat) propose the following data structures::
+
cloud = map<space_identifier, space>
space = tuple<type, components_identifiers, data_matrix>
components_identifiers = vector<component_identifier>
space_identifier = string with standardised naming (pos, normals, color, etc.)
component_identifier = string with standardised naming (x, y, r, g, b, etc.)
type = type of space, underlying scalar type + distance definition (float with euclidean 2-norm distance, float representing gaussians with Mahalanobis distance, binary with manhattan distance, float with euclidean infinity norm distance, etc.)
+
For instance, a simple point + color scenario could be::
+
cloud = { "pos" => pos_space, "color" => color_space }
pos_space = ( "float with euclidean 2-norm distance", { "x", "y", "z" }, [[(0.3,0,1.3) , ... , (1.2,3.1,2)], ... , [(1,0.3,1) , ... , (2,0,3.5)] )
color_space = ( "uint8 with rgb distance", { "r", "g", "b" }, [[(0,255,0), ... , (128,255,32)] ... [(12,54,31) ... (255,0,192)]] )
class LoopDetection
{
public:
- virtual ~LoopDetection () {}
+ virtual ~LoopDetection() = default;
virtual list<std::pair<PointCloud*, PointCloud*> > detectLoop(list<PosedPointCloud*> poses, list<PosedPointCloud*> query) {} = 0;
}
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
+OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
STRIP_FROM_INC_PATH = @STRIPPED_HEADERS@
SHORT_NAMES = @SHORT_NAMES@
JAVADOC_AUTOBRIEF = YES
+JAVADOC_BANNER = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
+PYTHON_DOCSTRING = YES
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 2
ALIASES =
-TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
+OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 5
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
+NUM_PROC_THREADS = 1
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
+EXTRACT_PRIV_VIRTUAL = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = NO
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
+RESOLVE_UNNAMED_PARAMS = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
-COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
HTML_COLORSTYLE_SAT = 46
HTML_COLORSTYLE_GAMMA = 73
HTML_TIMESTAMP = YES
+HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = YES
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = YES
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
+HTML_FORMULA_FORMAT = png
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
+FORMULA_MACROFILE =
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
+LATEX_MAKEINDEX_CMD = makeindex
COMPACT_LATEX = NO
-PAPER_TYPE = a4wide
-EXTRA_PACKAGES = amsmath amssymb
+PAPER_TYPE = a4
+EXTRA_PACKAGES = amsmath \
+ amssymb
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
+LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
+XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS = *.h
-#PREDEFINED = protected=private \
-PREDEFINED = = "HAVE_QHULL=1" \
+PREDEFINED = "HAVE_QHULL=1" \
"HAVE_OPENNI=1" \
"HAVE_ENSENSO=1" \
"HAVE_DAVIDSDK=1" \
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
-#TAGFILES = qtools_docs/qtools.tag=../../qtools_docs/html
GENERATE_TAGFILE = pcl.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
+DOT_UML_DETAILS = NO
+DOT_WRAP_THRESHOLD = 17
TEMPLATE_RELATIONS = YES
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
DOT_TRANSPARENT = YES
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
-DOT_CLEANUP = YES
+DOT_CLEANUP = YES
\ No newline at end of file
.. note::
Starting with PCL-1.7 you need to define PCL_NO_PRECOMPILE before you include
any PCL headers to include the templated algorithms as well.
+
+.. note::
+ The invocation of `POINT_CLOUD_REGISTER_POINT_STRUCT` must be in the global
+ namespace and the name of the new point type must be fully qualified.
Example
-------
.. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp
:language: cpp
- :lines: 16-22
+ :lines: 15-21
Then we instantiate the necessary data containers, check the input arguments and load the object and scene point clouds. Although we have defined the basic point type to contain normals, we only have those in advance for the object (which is often the case). We will estimate the normal information for the scene below.
.. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp
:language: cpp
- :lines: 28-49
+ :lines: 27-49
To speed up processing, we use PCL's :pcl:`VoxelGrid <pcl::VoxelGrid>` class to downsample both the object and the scene point clouds to a resolution of 5 mm.
.. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp
:language: cpp
- :lines: 61-66
+ :lines: 61-67
For each point in the downsampled point clouds, we now use PCL's :pcl:`FPFHEstimationOMP <pcl::FPFHEstimationOMP>` class to compute *Fast Point Feature Histogram* (FPFH) descriptors used for matching during the alignment process.
.. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp
:language: cpp
- :lines: 68-77
+ :lines: 69-78
We are now ready to setup the alignment process. We use the class :pcl:`SampleConsensusPrerejective <pcl::SampleConsensusPrerejective>`, which implements an efficient RANSAC pose estimation loop. This is achieved by early elimination of bad pose hypothesis using the class :pcl:`CorrespondenceRejectorPoly <pcl::registration::CorrespondenceRejectorPoly>`.
.. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp
:language: cpp
- :lines: 79-91
+ :lines: 80-92
.. note:: Apart from the usual input point clouds and features, this class takes some additional runtime parameters which have great influence on the performance of the alignment algorithm. The first two have the same meaning as in the alignment class :pcl:`SampleConsensusInitialAlignment <pcl::SampleConsensusInitialAlignment>`:
- Number of samples - *setNumberOfSamples ()*: The number of point correspondences to sample between the object and the scene. At minimum, 3 points are required to calculate a pose.
- Correspondence randomness - *setCorrespondenceRandomness ()*: Instead of matching each object FPFH descriptor to its nearest matching feature in the scene, we can choose between the *N* best matches at random. This increases the iterations necessary, but also makes the algorithm robust towards outlier matches.
- Polygonal similarity threshold - *setSimilarityThreshold ()*: The alignment class uses the :pcl:`CorrespondenceRejectorPoly <pcl::registration::CorrespondenceRejectorPoly>` class for early elimination of bad poses based on pose-invariant geometric consistencies of the inter-distances between sampled points on the object and the scene. The closer this value is set to 1, the more greedy and thereby fast the algorithm becomes. However, this also increases the risk of eliminating good poses when noise is present.
- - Inlier threshold - *setMaxCorrespondenceDistance ()*: This is the Euclidean distance threshold used for determining whether a transformed object point is correctly aligned to the nearest scene point or not. In this example, we have used a heuristic value of 1.5 times the point cloud resolution.
+ - Inlier threshold - *setMaxCorrespondenceDistance ()*: This is the Euclidean distance threshold used for determining whether a transformed object point is correctly aligned to the nearest scene point or not. In this example, we have used a heuristic value of 2.5 times the point cloud resolution.
- Inlier fraction - *setInlierFraction ()*: In many practical scenarios, large parts of the observed object in the scene are not visible, either due to clutter, occlusions or both. In such cases, we need to allow for pose hypotheses that do not align all object points to the scene. The absolute number of correctly aligned points is determined using the inlier threshold, and if the ratio of this number to the total number of points in the object is higher than the specified inlier fraction, we accept a pose hypothesis as valid.
Finally, we are ready to execute the alignment process.
.. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp
:language: cpp
- :lines: 92-95
+ :lines: 93-96
The aligned object is stored in the point cloud *object_aligned*. If a pose with enough inliers was found (more than 25 % of the total number of object points), the algorithm is said to converge, and we can print and visualize the results.
.. literalinclude:: sources/alignment_prerejective/alignment_prerejective.cpp
:language: cpp
- :lines: 99-114
+ :lines: 100-115
Compiling and running the program
R = | -0.999 -0.035 -0.020 |
| 0.006 0.369 -0.929 |
- t = < -0.287, 0.045, 0.126 >
+ t = < -0.120, 0.055, 0.076 >
- Inliers: 987/3432
+ Inliers: 1422/3432
The visualization window should look something like the below figures. The scene is shown with green color, and the aligned object model is shown with blue color. Note the high number of non-visible object points.
used as the matrix backend for SSE optimized math. **mandatory**
- - **FLANN** version >= 1.6.8 (http://www.cs.ubc.ca/research/flann/)
+ - **FLANN** version >= 1.6.8 (https://github.com/flann-lib/flann)
used in `kdtree` for fast approximate nearest neighbors search. **mandatory**
used to grab point clouds from OpenNI compliant devices. **optional**
- - **Qt** version >= 4.6 (http://qt.digia.com/)
+ - **Qt** version >= 4.6 (https://www.qt.io/)
used for developing applications with a graphical user interface (GUI) **optional**
--- /dev/null
+.. _compiling_pcl_docker:
+
+Compiling PCL from source using Docker
+======================================
+
+This tutorial explains how to build the Point Cloud Library **from source** using docker.
+
+.. note::
+
+ The walkthrough was done using Ubuntu as hosting OS of docker. The reason is that docker
+ can be much easier set up in linux OSs compared to Windows. Other possible alternatives
+ in case your main host is Windows could be WSL and or using virtual machine where some
+ linux OS is installed.
+
+Advantages - Disadvantages
+--------------------------
+Selecting to use docker to build PCL from source offers the following benefits:
+* Docker container provides some sort of isolated development environment. For someone familiar
+to python it is quite similar concept to virtual environment.
+* There is no need to install pcl dependencies standalone.
+* Installing, updating and maintaining different compilers (clang, g++) or version of other related
+programs is easier in docker container.
+* Once setting up docker the setup is pretty stable and there is no need to spend time for
+troubleshooting issues. Therefore the focus can be only in programming.
+
+Only disadvantage that i would think is the need to have a basic knowledge of linux OS and
+commands since it is much easier to setup docker in linux OSs compared to Windows.
+
+Requirements
+-------------
+Open a terminal in Ubuntu and run the corresponding commands from each
+installation section
+
+* Curl installation
+
+ Check if curl is already installed::
+
+ $ curl --version
+
+ If it is not already installed, run in terminal the relative command for your OS::
+ `<https://www.tecmint.com/install-curl-in-linux>`_
+
+* Git installation
+
+ Check if git is already installed::
+
+ $ git --version
+
+ If it is not already installed, run in terminal the relative command for your OS::
+ `<https://git-scm.com/download/linux>`_
+
+* Docker installation
+
+ Check if docker is already installed::
+
+ $ docker --version
+
+ If it is not already installed, follow the instructions from
+ `<https://github.com/docker/docker-install>`_ and run in terminal::
+
+ $ curl -fsSL https://get.docker.com -o get-docker.sh
+ $ sh get-docker.sh
+
+ Other useful commands are::
+
+ $ docker ps
+ $ service docker status
+
+ The first one shows the running containers while the latter shows the docker status.
+ If everything is fine it will be active (running).
+ You can start/stop docker if needed by running::
+
+ $ service docker start/stop
+
+
+.. note::
+
+ It might be required to add sudo in docker commands if permissions are not set properly.
+ See part **run docker commands without sudo** on how to set them correctly so the sudo command is not required.
+
+Downloading PCL source code
+----------------------------
+Download the pcl source code in Ubuntu::
+
+ $ git clone https://github.com/PointCloudLibrary/pcl.git
+
+Docker container configuration
+------------------------------
+* To run docker commands without sudo::
+
+ $ sudo groupadd docker
+ $ sudo usermod -aG docker $USER
+ $ newgrp docker
+
+ Verify you can run docker without sudo::
+
+ $ docker run hello-world
+
+* Pull the docker image by running::
+
+ $ docker pull pointcloudlibrary/env:20.04
+
+ The docker image above will have OS Ubuntu 20.04.
+ Other possible available images can be found under 'https://hub.docker.com/r/pointcloudlibrary/env/tags'
+
+.. note::
+
+ It is also possible to use the Dockerfile under .dev folder to set up your docker
+ image. The method of pulling the official docker image is considered more
+ stable option though.
+
+* Run the container::
+
+ $ docker run --user $(id -u):$(id -g) -v $PWD/pcl:/home --rm -it pointcloudlibrary/env:20.04 bash
+
+ where $PWD:/pcl:/home represents the pcl source code in Ubuntu while home represents the pcl source
+ code inside the docker container. Option --rm tells docker to remove the container when it exits
+ automatically. By default, when the container exits, its file system persists on the host system.
+ The -it option is used when dealing with the interactive processes like bash and tells Docker to
+ keep the standard input attached to the terminal.
+
+ Using volumes, actions performed on a file in Ubuntu such as creating new files are directly mapped
+ to the selected path location inside docker container.
+
+ To exit the container simply run in terminal exit.
+
+Building PCL
+--------------
+After running the container, we need to navigate to pcl source code and create a build folder in that directory.
+
+ $ cd home && mkdir build && cd build
+
+In case you prefer to use a specific compiler like clang instead of gcc run::
+
+ $ export CC=/usr/bin/clang
+ $ export CXX=/usr/bin/clang++
+
+Last step is the cmake configuration which is done by running this inside the build folder::
+
+ $ cmake ..
+
+Other cmake variables can be passed in this step for example cmake -DCMAKE_BUILD_TYPE=Release ..
+which will change the build target to “Release”. More details about cmake variables can be found
+in :ref:`building_pcl`.
+
+Finally compile everything by running::
+
+ $ make -j2
+
+Installing PCL
+--------------
+Install the result on docker::
+
+ $ make -j2 install
+
+To get root access for just install command::
+
+ $ docker exec -it <container_name>
+
+Next steps
+----------
+All the steps mentioned in this tutorial should be performed at least once and
+after that just running the container command and building or installing is
+enough. Periodically though it is recommended to pull the latest image to have
+possible updates that are incorporated in the meantime.
+
:target: _images/pcl_hdl_viewer.png
-So let's look at the code. The following represents a simplified version of *visualization/tools/hdl_viewer_simple.cpp*
+So let's look at the code. The following represents a simplified version of *tools/hdl_viewer_simple.cpp*
.. code-block:: cpp
:linenos:
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/console/parse.h>
+ using namespace std::chrono_literals;
using namespace pcl::console;
using namespace pcl::visualization;
typedef pcl::PointCloud<pcl::PointXYZI> Cloud;
typedef Cloud::ConstPtr CloudConstPtr;
- SimpleHDLViewer (Grabber& grabber,
+ SimpleHDLViewer (pcl::Grabber& grabber,
pcl::visualization::PointCloudColorHandler<pcl::PointXYZI> &handler) :
cloud_viewer_ (new pcl::visualization::PCLVisualizer ("PCL HDL Cloud")),
grabber_ (grabber),
if (!grabber_.isRunning ())
cloud_viewer_->spin ();
- boost::this_thread::sleep (boost::posix_time::microseconds (100));
+ std::this_thread::sleep_for(100us);
}
grabber_.stop ();
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZI> color_handler ("intensity");
- SimpleHDLViewer<PointXYZI> v (grabber, color_handler);
+ SimpleHDLViewer v (grabber, color_handler);
v.run ();
return (0);
}
.. |mi_6| image:: images/macosx_logo.png
:height: 100px
+ * :ref:`compiling_pcl_docker`
+
+ ======= ======
+ |mi_13| Title: **Compiling PCL using docker**
+
+ Author: *Theodoros Nikolaou*
+
+ Compatibility: > PCL 1.12
+
+ This tutorial explains how to build and install PCL from source using docker
+ ======= ======
+
+ .. |mi_13| image:: images/pcl_logo.png
+ :height: 100px
+
* :ref:`installing_homebrew`
====== ======
\sigma = \frac{\lambda_0}{\lambda_0 + \lambda_1 + \lambda_2}
+For a detailed description of this property, see M. Pauly, M. Gross and L. P. Kobbelt, "Efficient simplification of point-sampled surfaces".
+
Speeding Normal Estimation with OpenMP
--------------------------------------
.. note::
If your dataset is organized (e.g., acquired using a TOF camera, stereo camera, etc -- that is, it has a width and a height), for even faster results see the :ref:`normal_estimation_using_integral_images`.
-
-
:language: cpp
:lines: 215-235
-| This is the core function of the application. We are going to color the cloud following a color scheme.
+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
(the minimum & maximum point values along the chosen axis). We first set the initial minimal value to the first point value
(this is safe because we removed NaN points from the point clouds). The switch case allows us to deal with the 3 different axes.
project(alignment_prerejective)
-find_package(PCL 1.7 REQUIRED REQUIRED COMPONENTS io registration segmentation visualization)
+find_package(PCL 1.7 REQUIRED COMPONENTS io registration segmentation visualization)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
#include <pcl/filters/filter.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/io/pcd_io.h>
-#include <pcl/registration/icp.h>
#include <pcl/registration/sample_consensus_prerejective.h>
#include <pcl/visualization/pcl_visualizer.h>
// Point clouds
PointCloudT::Ptr object (new PointCloudT);
PointCloudT::Ptr object_aligned (new PointCloudT);
+ PointCloudT::Ptr scene_before_downsampling (new PointCloudT);
PointCloudT::Ptr scene (new PointCloudT);
FeatureCloudT::Ptr object_features (new FeatureCloudT);
FeatureCloudT::Ptr scene_features (new FeatureCloudT);
// Load object and scene
pcl::console::print_highlight ("Loading point clouds...\n");
if (pcl::io::loadPCDFile<PointNT> (argv[1], *object) < 0 ||
- pcl::io::loadPCDFile<PointNT> (argv[2], *scene) < 0)
+ pcl::io::loadPCDFile<PointNT> (argv[2], *scene_before_downsampling) < 0)
{
pcl::console::print_error ("Error loading object/scene file!\n");
return (1);
grid.setLeafSize (leaf, leaf, leaf);
grid.setInputCloud (object);
grid.filter (*object);
- grid.setInputCloud (scene);
+ grid.setInputCloud (scene_before_downsampling);
grid.filter (*scene);
// Estimate normals for scene
pcl::console::print_highlight ("Estimating scene normals...\n");
pcl::NormalEstimationOMP<PointNT,PointNT> nest;
- nest.setRadiusSearch (0.01);
+ nest.setRadiusSearch (0.005);
nest.setInputCloud (scene);
+ nest.setSearchSurface (scene_before_downsampling);
nest.compute (*scene);
// Estimate features
align.setMaximumIterations (50000); // Number of RANSAC iterations
align.setNumberOfSamples (3); // Number of points to sample for generating/prerejecting a pose
align.setCorrespondenceRandomness (5); // Number of nearest features to use
- align.setSimilarityThreshold (0.9f); // Polygonal edge length similarity threshold
+ align.setSimilarityThreshold (0.95f); // Polygonal edge length similarity threshold
align.setMaxCorrespondenceDistance (2.5f * leaf); // Inlier threshold
align.setInlierFraction (0.25f); // Required inlier fraction for accepting a pose hypothesis
{
ec.extract (cluster_indices);
int j = 0;
- for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
+ for (const auto& cluster : cluster_indices)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
- for (const auto& idx : it->indices)
- cloud_cluster->push_back ((*cloud_filtered)[idx]); //*
+ for (const auto& idx : cluster.indices) {
+ cloud_cluster->push_back((*cloud_filtered)[idx]);
+ } //*
cloud_cluster->width = cloud_cluster->size ();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(correspondence_grouping)
ec.extract (cluster_indices);
int j = 0;
- for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it, j++)
+ for (const auto& cluster : cluster_indices)
{
pcl::PointCloud<PointNormal>::Ptr cloud_cluster_don (new pcl::PointCloud<PointNormal>);
- for (const auto& idx : it->indices)
+ for (const auto& idx : cluster.indices)
{
cloud_cluster_don->points.push_back ((*doncloud)[idx]);
}
std::stringstream ss;
ss << "don_cluster_" << j << ".pcd";
writer.write<pcl::PointNormal> (ss.str (), *cloud_cluster_don, false);
+ ++j;
}
}
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(global_hypothesis_verification)
pcl::visualization::PointCloudColorHandlerRGBField<PointT> rgb(cloud);
viewer.addPointCloud<PointT> (cloud, rgb, "input_cloud");
unsigned int k = 0;
- for(std::vector<pcl::people::PersonCluster<PointT> >::iterator it = clusters.begin(); it != clusters.end(); ++it)
+ for(auto& cluster : clusters)
{
- if(it->getPersonConfidence() > min_confidence) // draw only people with confidence above a threshold
+ if(cluster.getPersonConfidence() > min_confidence) // draw only people with confidence above a threshold
{
// draw theoretical person bounding box in the PCL viewer:
- it->drawTBoundingBox(viewer, k);
- k++;
+ cluster.drawTBoundingBox(viewer, k);
+ ++k;
}
}
std::cout << k << " people found" << std::endl;
std::string start = "";
getModelsInDirectory (dir_path, start, files);
- for(std::size_t i=0; i < files.size(); i++) {
+ for(const auto& file : files) {
// Load input file
std::string filename = directory;
filename.append("/");
- filename.append(files[i]);
+ filename.append(file);
PointCloudPtr input (new PointCloud);
pcl::io::loadPCDFile (filename, *input);
pcl::console::print_info ("Loaded %s (%lu points)\n", filename.c_str(), input->size ());
- std::cout << files[i] << std::endl;
+ std::cout << file << std::endl;
// Construct the object model
ObjectRecognition obj_rec (params);
ObjectModel model;
//get directory name
std::vector < std::string > strs;
- boost::split (strs, files[i], boost::is_any_of ("/\\"));
+ boost::split (strs, file, boost::is_any_of ("/\\"));
std::string id = strs[0];
std::string raw_file = strs[1];
if ( pcl::io::loadPCDFile <pcl::PointXYZ> (argv[i_cloud * 2 + 1], *tr_cloud) == -1 )
return (-1);
- pcl::PointCloud<pcl::Normal>::Ptr tr_normals = (new pcl::PointCloud<pcl::Normal>)->makeShared ();
+ pcl::PointCloud<pcl::Normal>::Ptr tr_normals (new pcl::PointCloud<pcl::Normal>);
normal_estimator.setInputCloud (tr_cloud);
normal_estimator.compute (*tr_normals);
if ( pcl::io::loadPCDFile <pcl::PointXYZ> (argv[argc - 2], *testing_cloud) == -1 )
return (-1);
- pcl::PointCloud<pcl::Normal>::Ptr testing_normals = (new pcl::PointCloud<pcl::Normal>)->makeShared ();
+ pcl::PointCloud<pcl::Normal>::Ptr testing_normals (new pcl::PointCloud<pcl::Normal>);
normal_estimator.setInputCloud (testing_cloud);
normal_estimator.compute (*testing_normals);
std::vector<pcl::ISMPeak, Eigen::aligned_allocator<pcl::ISMPeak> > strongest_peaks;
vote_list->findStrongestPeaks (strongest_peaks, testing_class, radius, sigma);
- pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
+ pcl::PointCloud <pcl::PointXYZRGB>::Ptr colored_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
colored_cloud->height = 0;
colored_cloud->width = 1;
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)\r
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)\r
\r
project(pcl-interactive_icp)\r
\r
}
ObjectRecognitionParameters params;
- ifstream params_stream;
+ std::ifstream params_stream;
//Parse filter parameters
std::string filter_parameters_file;
std::string start = "";
getModelsInDirectory (dir_path, start, files);
- for(std::size_t i=0; i < files.size(); i++) {
+ for(const auto& file : files) {
// Load input file
std::string filename = directory;
filename.append("/");
- filename.append(files[i]);
+ filename.append(file);
PointCloudPtr input (new PointCloud);
pcl::io::loadPCDFile (filename, *input);
pcl::console::print_info ("Loaded %s (%lu points)\n", filename.c_str(), input->size ());
- std::cout << files[i] << std::endl;
+ std::cout << file << std::endl;
// Construct the object model
ObjectRecognition obj_rec (params);
ObjectModel model;
//get directory name
std::vector < std::string > strs;
- boost::split (strs, files[i], boost::is_any_of ("/\\"));
+ boost::split (strs, file, boost::is_any_of ("/\\"));
std::string id = strs[0];
std::string raw_file = strs[1];
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(pcl-matrix_transform)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(narf_descriptor_visualization)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(narf_feature_extraction)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(narf_keypoint_extraction)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(normal_estimation_using_integral_images)
-#include <pcl/visualization/cloud_viewer.h>
+#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
// Output points
std::cout << "Output from getPointIndicesFromNewVoxels:" << std::endl;
- for (std::size_t i = 0; i < newPointIdxVector.size (); ++i)
+ for (std::size_t i = 0; i < newPointIdxVector.size (); ++i){
std::cout << i << "# Index:" << newPointIdxVector[i]
<< " Point:" << (*cloudB)[newPointIdxVector[i]].x << " "
<< (*cloudB)[newPointIdxVector[i]].y << " "
<< (*cloudB)[newPointIdxVector[i]].z << std::endl;
-
+ }
}
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(openni_narf_keypoint_extraction)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(openni_range_image_visualization)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(tuto-pairwise)
pass.setInputCloud (cloud);
pass.setFilterFieldName ("z");
pass.setFilterLimits (0.0, 1.0);
- //pass.setFilterLimitsNegative (true);
+ //pass.setNegative (true);
pass.filter (*cloud_filtered);
std::cerr << "Cloud after filtering: " << std::endl;
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(pcl_painter2D_demo)
find_package(PCL 1.7)
include_directories(${PCL_INCLUDE_DIRS})
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(pcl_visualizer_viewports)
point.x = basic_point.x;
point.y = basic_point.y;
point.z = basic_point.z;
- std::uint32_t rgb = (static_cast<std::uint32_t>(r) << 16 |
- static_cast<std::uint32_t>(g) << 8 | static_cast<std::uint32_t>(b));
- point.rgb = *reinterpret_cast<float*>(&rgb);
+ point.r = r;
+ point.g = g;
+ point.b = b;
point_cloud_ptr->points.push_back (point);
}
if (z < 0.0)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(range_image_border_extraction)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(range_image_creation)
-cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(range_image_visualization)
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
-#include <pcl/kdtree/kdtree_flann.h>
+#include <pcl/search/kdtree.h>
#include <pcl/surface/mls.h>
int
feature_radius_ (0.02f)
{}
- ~FeatureCloud () {}
-
// Process the given cloud
void
setInputCloud (PointCloud::Ptr xyz)
sac_ia_.setMaximumIterations (nr_iterations_);
}
- ~TemplateAlignment () {}
-
// Set the given cloud as the target to which the templates will be aligned
void
setTargetCloud (FeatureCloud &target_cloud)
#include <pcl/console/print.h>
#include <pcl/io/pcd_io.h>
#include <iostream>
+#include <limits>
#include <flann/flann.h>
#include <flann/io/hdf5.h>
#include <boost/filesystem.hpp>
{
int k = 6;
- double thresh = DBL_MAX; // No threshold, disabled by default
+ double thresh = std::numeric_limits<double>::max(); // No threshold, disabled by default
if (argc < 2)
{
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 24-28
+ :lines: 26-30
-Then we define methods for setting the input cloud, either by passing a shared pointer to a PointCloud or by providing the name of a PCD file to load. In either case, after setting the input, *processInput* is called, which will compute the local feature descriptors as described later.
+Then we define methods for setting the input cloud, either by passing a shared pointer to a PointCloud or by providing the name of a PCD file to load. In either case, after setting the input, *processInput* is called, which will compute the local feature descriptors as described later.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 143-150
+ :lines: 141-148
We then define a method for specifying which template or templates to attempt to align. Each call to this method will add the given template cloud to an internal vector of FeatureClouds and store them for future use.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 152-157
+ :lines: 150-155
Next we define our alignment method. This method takes a template as input and aligns it to the target cloud that was specified by calling :pcl:`setInputTarget <pcl::Registration::setInputTarget>`. It works by setting the given template as the SAC-IA algorithm's source cloud and then calling its :pcl:`align <pcl::Registration::align>` method to align the source to the target. Note that the :pcl:`align <pcl::Registration::align>` method requires us to pass in a point cloud that will store the newly aligned source cloud, but we can ignore this output for our application. Instead, we call SAC-IA's accessor methods to get the alignment's fitness score and final transformation matrix (the rigid transformation from the source cloud to the target), and we output them as a Result struct.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 159-171
+ :lines: 157-169
Because this class is designed to work with multiple templates, we also define a method for aligning all of the templates to the target cloud and storing the results in a vector of Result structs.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 173-182
+ :lines: 171-180
Finally, we define a method that will align all of the templates to the target cloud and return the index of the best match and its corresponding Result struct.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 184-208
+ :lines: 182-206
Now that we have a class that handles aligning object templates, we'll apply it to the the problem of face alignment. In the supplied data files, we've included six template point clouds that we created from different views of a person's face. Each one was downsampled to a spacing of 5mm and manually cropped to include only points from the face. In the following code, we show how to use our *TemplateAlignment* class to locate the position and orientation of the person's face in a new cloud.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 232-247
+ :lines: 230-245
Next we load the target cloud (from the filename supplied on the command line).
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 249-251
+ :lines: 247-249
We then perform a little pre-processing on the data to get it ready for alignment. The first step is to filter out any background points. In this example we assume the person we're trying to align to will be less than 1 meter away, so we apply a pass-through filter, filtering on the "z" field (i.e., depth) with limits of 0 to 1.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 253-260
+ :lines: 251-258
We also downsample the point cloud with a spacing of 5mm, which reduces the amount of computation that's required.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 262-267
+ :lines: 260-268
And after the pre-processing is finished, we create our target FeatureCloud.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 269-271
+ :lines: 270-272
Next, we initialize our *TemplateAlignment* object. For this, we need to add each of our template clouds and set the target cloud.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 273-279
+ :lines: 274-280
Now that our *TemplateAlignment* object is initialized, we're ready call the *findBestAlignment* method to determine which template best fits the given target cloud. We store the alignment results in *best_alignment*.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 281-284
+ :lines: 282-285
-Next we output the results. Looking at the fitness score (*best_alignment.fitness_score*) gives us an idea of how successful the alignment was, and looking at the transformation matrix (*best_alignment.final_transformation*) tells us the position and orientation of the object we aligned to in the target cloud. Specifically, because it's a rigid transformation, it can be decomposed into a 3-dimensional translation vector :math:`(t_x, t_y, t_z)` and a 3 x 3 rotation matrix :math:`R` as follows:
+Next we output the results. Looking at the fitness score (*best_alignment.fitness_score*) gives us an idea of how successful the alignment was, and looking at the transformation matrix (*best_alignment.final_transformation*) tells us the position and orientation of the object we aligned to in the target cloud. Specifically, because it's a rigid transformation, it can be decomposed into a 3-dimensional translation vector :math:`(t_x, t_y, t_z)` and a 3 x 3 rotation matrix :math:`R` as follows:
.. math::
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 286-298
+ :lines: 287-299
Finally, we take the best fitting template, apply the transform that aligns it to the target cloud, and save the aligned template out as a .PCD file so that we can visualize it later to see how well the alignment worked.
.. literalinclude:: sources/template_alignment/template_alignment.cpp
:language: cpp
- :lines: 300-303
+ :lines: 301-304
Compiling and running the program
---------------------------------
set(DEFAULT FALSE)
set(REASON "Code examples are disabled by default.")
PCL_SUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSYS_DESC} ${DEFAULT} ${REASON})
-PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
if(NOT build)
return()
{
total += static_cast<float> (i);
}
+ std::cout << "total = " << total << std::endl;
}
std::cout << "Done." << std::endl;
ec.extract (cluster_indices);
int j = 0;
- for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it, j++)
+ for (const auto& cluster : cluster_indices)
{
pcl::PointCloud<PointOutT>::Ptr cloud_cluster_don (new pcl::PointCloud<PointOutT>);
- for (const auto &index : it->indices){
+ for (const auto &index : cluster.indices){
cloud_cluster_don->points.push_back ((*doncloud)[index]);
}
std::stringstream ss;
ss << outfile.substr(0,outfile.length()-4) << "_threshold_"<< threshold << "_cluster_" << j << ".pcd";
writer.write<PointOutT> (ss.str (), *cloud_cluster_don, false);
+ ++j;
}
}
return()
endif()
-PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS geometry)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS geometry)
PCL_ADD_EXAMPLE(pcl_example_half_edge_mesh FILES example_half_edge_mesh.cpp LINK_WITH pcl_common)
return()
endif()
-PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS visualization)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS visualization)
## Find VTK
if(NOT VTK_FOUND)
set(REASON)
endif()
-PCL_SUBSYS_DEPEND (build ${SUBSYS_NAME} DEPS outofcore io common octree filters visualization EXT_DEPS vtk)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS outofcore io common octree filters visualization EXT_DEPS vtk)
PCL_ADD_EXAMPLE (pcl_example_outofcore_with_lod FILES example_outofcore_with_lod.cpp LINK_WITH pcl_outofcore pcl_common pcl_io pcl_octree pcl_filters)
PCL_ADD_EXAMPLE (pcl_example_outofcore FILES example_outofcore.cpp LINK_WITH pcl_outofcore pcl_common pcl_io pcl_octree pcl_filters)
return()
endif()
-PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS visualization segmentation)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS visualization segmentation)
PCL_ADD_EXAMPLE(pcl_example_extract_clusters_normals FILES example_extract_clusters_normals.cpp
LINK_WITH pcl_common pcl_keypoints pcl_io pcl_segmentation)
// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New ();
- for (VertexIterator itr = vertex_iterator_range.first; itr != vertex_iterator_range.second; ++itr)
+ for (auto itr = vertex_iterator_range.first; itr != vertex_iterator_range.second; ++itr)
{
const std::uint32_t sv_label = sv_adjacency_list[*itr];
std::pair<AdjacencyIterator, AdjacencyIterator> neighbors = boost::adjacent_vertices (*itr, sv_adjacency_list);
#include <pcl/segmentation/extract_clusters.h>
int
-main (int, char **argv)
+main (int argc, char **argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_ptr (new pcl::PointCloud<pcl::PointXYZ> ());
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal> ());
pcl::PCDWriter writer;
+ if (argc < 2)
+ {
+ std::cout<<"No PCD file given!"<<std::endl;
+ return (-1);
+ }
if (pcl::io::loadPCDFile<pcl::PointXYZ> (argv[1], *cloud_ptr) == -1)
{
std::cout<<"Couldn't read the file "<<argv[1]<<std::endl;
// Saving the clusters in separate pcd files
int j = 0;
- for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
+ for (const auto& cluster : cluster_indices)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
- for (const auto &index : it->indices)
- cloud_cluster->push_back ((*cloud_ptr)[index]);
+ for (const auto &index : cluster.indices) {
+ cloud_cluster->push_back((*cloud_ptr)[index]);
+ }
cloud_cluster->width = cloud_cluster->size ();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
std::stringstream ss;
ss << "./cloud_cluster_" << j << ".pcd";
writer.write<pcl::PointXYZ> (ss.str (), *cloud_cluster, false);
- j++;
+ ++j;
}
return (0);
// Create a polydata to store everything in
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New ();
- for (VertexIterator itr = vertex_iterator_range.first; itr != vertex_iterator_range.second; ++itr)
+ for (auto itr = vertex_iterator_range.first; itr != vertex_iterator_range.second; ++itr)
{
const std::uint32_t sv_label = sv_adjacency_list[*itr];
std::pair<AdjacencyIterator, AdjacencyIterator> neighbors = boost::adjacent_vertices (*itr, sv_adjacency_list);
return()
endif()
-PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS visualization)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS visualization)
## Find VTK
if(NOT VTK_FOUND)
return()
endif()
-PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS visualization geometry surface)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS visualization geometry surface)
## Find VTK
if(NOT VTK_FOUND)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
rng_.seed (12345u);
}
- ~ShapeContext3DEstimation() {}
+ ~ShapeContext3DEstimation() override = default;
//inline void
//setAzimuthBins (std::size_t bins) { azimuth_bins_ = bins; }
}
/** \brief Empty destructor */
- ~BOARDLocalReferenceFrameEstimation () {}
+ ~BOARDLocalReferenceFrameEstimation () override = default;
//Getters/Setters
feature_name_ = "DifferenceOfNormalsEstimation";
}
- ~DifferenceOfNormalsEstimation ()
- {
- //
- }
+ ~DifferenceOfNormalsEstimation () override = default;
/**
* Set the normals calculated using a smaller search radius (scale) for the DoN operator.
fake_surface_(false)
{}
- /** \brief Empty destructor */
- virtual ~Feature () {}
-
/** \brief Provide a pointer to a dataset to add additional information
* to estimate the features for every point in the input dataset. This
* is optional, if this is not set, it will only use the data in the
/** \brief Empty constructor. */
FeatureFromNormals () : normals_ () {}
- /** \brief Empty destructor */
- virtual ~FeatureFromNormals () {}
-
/** \brief Provide a pointer to the input dataset that contains the point normals of
* the XYZ dataset.
* In case of search surface is set to be different from the input cloud,
k_ = 1; // Search tree is not always used here.
}
- /** \brief Empty destructor */
- virtual ~FeatureFromLabels () {}
-
/** \brief Provide a pointer to the input dataset that contains the point labels of
* the XYZ dataset.
* In case of search surface is set to be different from the input cloud,
/** \brief Empty constructor. */
FeatureWithLocalReferenceFrames () : frames_ (), frames_never_defined_ (true) {}
- /** \brief Empty destructor. */
- virtual ~FeatureWithLocalReferenceFrames () {}
+ /** \brief Default virtual destructor. */
+ virtual
+ ~FeatureWithLocalReferenceFrames() = default;
/** \brief Provide a pointer to the input dataset that contains the local
* reference frames of the XYZ dataset.
*
* \author Radu B. Rusu
* \ingroup features
+ * \tparam PointOutT Suggested type is `pcl::GFPFHSignature16`
*/
template <typename PointInT, typename PointLT, typename PointOutT>
class GFPFHEstimation : public FeatureFromLabels<PointInT, PointLT, PointOutT>
* \ref FPFHEstimationOMP for examples on parallel implementations of the FPFH (Fast Point Feature Histogram).
* \author Zoltan Csaba Marton
* \ingroup features
+ * \tparam PointOutT Suggested type is `pcl::GRSDSignature21`
*/
template <typename PointInT, typename PointNT, typename PointOutT>
using PointCloudInPtr = typename Feature<PointInT, PointOutT>::PointCloudInPtr;
/** \brief Constructor. */
- GRSDEstimation () : additive_ (true)
+ GRSDEstimation ()
{
feature_name_ = "GRSDEstimation";
relative_coordinates_all_ = getAllNeighborCellIndices ();
*/
inline double
getRadiusSearch () const { return (search_radius_); }
-
+
+ /** \brief Set the number of subdivisions for the considered distance interval.
+ * This function configures the underlying RSDEstimation. For more info, see
+ * there. If this function is not called, the default from RSDEstimation is used.
+ * \param[in] nr_subdiv the number of subdivisions
+ */
+ inline void
+ setNrSubdivisions (int nr_subdiv) { rsd_nr_subdiv_ = nr_subdiv; }
+
+ /** \brief Set the maximum radius, above which everything can be considered planar.
+ * This function configures the underlying RSDEstimation. For more info, see
+ * there. If this function is not called, the default from RSDEstimation is used.
+ * \param[in] plane_radius the new plane radius
+ */
+ inline void
+ setPlaneRadius (double plane_radius) { rsd_plane_radius_ = plane_radius; }
+
/** \brief Get the type of the local surface based on the min and max radius computed.
* \return the integer that represents the type of the local surface with values as
* Plane (1), Cylinder (2), Noise or corner (0), Sphere (3) and Edge (4)
private:
/** \brief Defines if an additive feature is computed or ray-casting is used to get a more descriptive feature. */
- bool additive_;
+ bool additive_ = true;
/** \brief Defines the voxel size to be used. */
- double width_;
+ double width_ = 0.0;
+
+ /** \brief For the underlying RSDEstimation. The number of subdivisions for the considered distance interval. */
+ int rsd_nr_subdiv_ = 0;
+
+ /** \brief For the underlying RSDEstimation. The maximum radius, above which everything can be considered planar. */
+ double rsd_plane_radius_ = 0.0;
/** \brief Pre-computed the relative cell indices of all the 26 neighbors. */
Eigen::MatrixXi relative_coordinates_all_;
if (neighb_cnt == 0)
{
std::fill (desc.begin (), desc.end (), std::numeric_limits<float>::quiet_NaN ());
- std::fill (rf, rf + 9, 0.f);
+ std::fill_n (rf, 9, 0.f);
return (false);
}
} // end for each neighbour
// 3DSC does not define a repeatable local RF, we set it to zero to signal it to the user
- std::fill (rf, rf + 9, 0);
+ std::fill_n (rf, 9, 0);
return (true);
}
// If the point is not finite, set the descriptor to NaN and continue
if (!isFinite ((*input_)[(*indices_)[point_index]]))
{
- std::fill (output[point_index].descriptor, output[point_index].descriptor + descriptor_length_,
- std::numeric_limits<float>::quiet_NaN ());
- std::fill (output[point_index].rf, output[point_index].rf + 9, 0);
+ std::fill_n (output[point_index].descriptor, descriptor_length_,
+ std::numeric_limits<float>::quiet_NaN ());
+ std::fill_n (output[point_index].rf, 9, 0);
output.is_dense = false;
continue;
}
std::vector<float> descriptor (descriptor_length_);
if (!computePoint (point_index, *normals_, output[point_index].rf, descriptor))
output.is_dense = false;
- std::copy (descriptor.begin (), descriptor.end (), output[point_index].descriptor);
+ std::copy (descriptor.cbegin (), descriptor.cend (), output[point_index].descriptor);
}
}
// Compute the angles between each neighboring point and the query point itself
std::vector<float> angles (indices.size ());
- float max_dif = FLT_MIN, dif;
+ float max_dif = 0, dif;
int cp = 0;
for (const auto &index : indices)
pattern_iterator->sigma = static_cast<float> (sigma_scale * scale_list_[scale] * (double (radius_list[ring])) * sin (M_PI / double (number_list[ring])));
// adapt the sizeList if necessary
- const unsigned int size = static_cast<unsigned int> (std::ceil (((scale_list_[scale] * radius_list[ring]) + pattern_iterator->sigma)) + 1);
+ const auto size = static_cast<unsigned int> (std::ceil (((scale_list_[scale] * radius_list[ring]) + pattern_iterator->sigma)) + 1);
if (size_list_[scale] < size)
size_list_[scale] = size;
}
// image size
- const index_t width = static_cast<index_t>(input_cloud_->width);
- const index_t height = static_cast<index_t>(input_cloud_->height);
+ const auto width = static_cast<index_t>(input_cloud_->width);
+ const auto height = static_cast<index_t>(input_cloud_->height);
// destination for intensity data; will be forwarded to BRISK
std::vector<unsigned char> image_data (width*height);
// initialize constants
static const float lb_scalerange = std::log2 (scalerange_);
- typename std::vector<KeypointT, Eigen::aligned_allocator<KeypointT> >::iterator beginning = keypoints_->points.begin ();
- std::vector<int>::iterator beginningkscales = kscales.begin ();
+ auto beginning = keypoints_->points.begin ();
+ auto beginningkscales = kscales.begin ();
static const float basic_size_06 = basic_size_ * 0.6f;
unsigned int basicscale = 0;
#endif
// now iterate through all the pairings
- UINT32_ALIAS* ptr2 = reinterpret_cast<UINT32_ALIAS*> (ptr);
+ auto* ptr2 = reinterpret_cast<UINT32_ALIAS*> (ptr);
const BriskShortPair* max = short_pairs_ + no_short_pairs_;
for (BriskShortPair* iter = short_pairs_; iter < max; ++iter)
int err_2 = dz2 - l;
for (int i = 1; i<l; i++)
{
- voxelcount++;;
+ voxelcount++;
voxel_in += static_cast<int>(lut_[act_voxel[0]][act_voxel[1]][act_voxel[2]] == 1);
if (err_1 > 0)
{
{
const std::size_t idx = ( (i + 1) * (grid_size + 2) + (j + 1)) * (grid_size + 2) + (k + 1);
- std::copy (hists[idx].data () + 1, hists[idx].data () + hists_size + 1, output[0].histogram + pos);
+ std::copy (hists[idx].data () + 1, hists[idx].data () + 1 + hists_size, output[0].histogram + pos);
pos += hists_size;
}
}
hists[idx][1] += hists[idx][hists_size + 1];
hists[idx][hists_size] += hists[idx][0];
- std::copy (hists[idx].data () + 1, hists[idx].data () + hists_size + 1, output[0].histogram + pos);
+ std::copy (hists[idx].data () + 1, hists[idx].data () + 1 + hists_size, output[0].histogram + pos);
pos += hists_size;
}
}
pcl::GRSDEstimation<PointInT, PointNT, PointOutT>::computeFeature (PointCloudOut &output)
{
// Check if search_radius_ was set
- if (width_ < 0)
+ if (width_ <= 0.0)
{
PCL_ERROR ("[pcl::%s::computeFeature] A voxel cell width needs to be set!\n", getClassName ().c_str ());
output.width = output.height = 0;
rsd.setInputCloud (cloud_downsampled);
rsd.setSearchSurface (input_);
rsd.setInputNormals (normals_);
- rsd.setRadiusSearch (std::max (search_radius_, std::sqrt (3.0) * width_ / 2));
+ rsd.setRadiusSearch (search_radius_);
+ if (rsd_nr_subdiv_ != 0) // if not set, use default from RSDEstimation
+ rsd.setNrSubdivisions (rsd_nr_subdiv_);
+ if (rsd_plane_radius_ != 0.0)
+ rsd.setPlaneRadius (rsd_plane_radius_);
rsd.compute (*radii);
// Save the type of each point
{
ElementType* previous_row = &first_order_integral_image_[0];
ElementType* current_row = previous_row + (width_ + 1);
- *previous_row = ElementType::Zero(width_ + 1);
+ for (unsigned int i = 0; i < (width_ + 1); ++i)
+ previous_row[i].setZero();
unsigned* count_previous_row = &finite_values_integral_image_[0];
unsigned* count_current_row = count_previous_row + (width_ + 1);
- memset (count_previous_row, 0, sizeof (unsigned) * (width_ + 1));
+ std::fill_n(count_previous_row, width_ + 1, 0);
if (!compute_second_order_integral_images_)
{
{
current_row [colIdx + 1] = previous_row [colIdx + 1] + current_row [colIdx] - previous_row [colIdx];
count_current_row [colIdx + 1] = count_previous_row [colIdx + 1] + count_current_row [colIdx] - count_previous_row [colIdx];
- const InputType* element = reinterpret_cast <const InputType*> (&data [valIdx]);
+ const auto* element = reinterpret_cast <const InputType*> (&data [valIdx]);
if (std::isfinite (element->sum ()))
{
current_row [colIdx + 1] += element->template cast<typename IntegralImageTypeTraits<DataType>::IntegralType>();
{
SecondOrderType* so_previous_row = &second_order_integral_image_[0];
SecondOrderType* so_current_row = so_previous_row + (width_ + 1);
- *so_previous_row = SecondOrderType::Zero(width_ + 1);
+ for (unsigned int i = 0; i < (width_ + 1); ++i)
+ so_previous_row[i].setZero();
SecondOrderType so_element;
for (unsigned rowIdx = 0; rowIdx < height_; ++rowIdx, data += row_stride,
so_current_row [colIdx + 1] = so_previous_row [colIdx + 1] + so_current_row [colIdx] - so_previous_row [colIdx];
count_current_row [colIdx + 1] = count_previous_row [colIdx + 1] + count_current_row [colIdx] - count_previous_row [colIdx];
- const InputType* element = reinterpret_cast <const InputType*> (&data [valIdx]);
+ const auto* element = reinterpret_cast <const InputType*> (&data [valIdx]);
if (std::isfinite (element->sum ()))
{
current_row [colIdx + 1] += element->template cast<typename IntegralImageTypeTraits<DataType>::IntegralType>();
{
ElementType* previous_row = &first_order_integral_image_[0];
ElementType* current_row = previous_row + (width_ + 1);
- memset (previous_row, 0, sizeof (ElementType) * (width_ + 1));
+ std::fill_n(previous_row, width_ + 1, 0);
unsigned* count_previous_row = &finite_values_integral_image_[0];
unsigned* count_current_row = count_previous_row + (width_ + 1);
- memset (count_previous_row, 0, sizeof (unsigned) * (width_ + 1));
+ std::fill_n(count_previous_row, width_ + 1, 0);
if (!compute_second_order_integral_images_)
{
{
SecondOrderType* so_previous_row = &second_order_integral_image_[0];
SecondOrderType* so_current_row = so_previous_row + (width_ + 1);
- memset (so_previous_row, 0, sizeof (SecondOrderType) * (width_ + 1));
+ std::fill_n(so_previous_row, width_ + 1, 0);
for (unsigned rowIdx = 0; rowIdx < height_; ++rowIdx, data += row_stride,
previous_row = current_row, current_row += (width_ + 1),
* POSSIBILITY OF SUCH DAMAGE.
*
*/
-
-#ifndef PCL_FEATURES_INTEGRALIMAGE_BASED_IMPL_NORMAL_ESTIMATOR_H_
-#define PCL_FEATURES_INTEGRALIMAGE_BASED_IMPL_NORMAL_ESTIMATOR_H_
-
+#pragma once
#include <pcl/features/integral_image_normal.h>
+#include <algorithm>
+
//////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointOutT>
pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::~IntegralImageNormalEstimation ()
template <typename PointInT, typename PointOutT> void
pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::initAverage3DGradientMethod ()
{
+ delete[] diff_x_;
+ delete[] diff_y_;
std::size_t data_size = (input_->size () << 2);
- diff_x_ = new float[data_size];
- diff_y_ = new float[data_size];
-
- memset (diff_x_, 0, sizeof(float) * data_size);
- memset (diff_y_, 0, sizeof(float) * data_size);
+ diff_x_ = new float[data_size]{};
+ diff_y_ = new float[data_size]{};
// x u x
// l x r
float bad_point = std::numeric_limits<float>::quiet_NaN ();
// compute depth-change map
- unsigned char * depthChangeMap = new unsigned char[input_->size ()];
- memset (depthChangeMap, 255, input_->size ());
+ auto depthChangeMap = new unsigned char[input_->size ()];
+ std::fill_n(depthChangeMap, input_->size(), 255);
unsigned index = 0;
for (unsigned int ri = 0; ri < input_->height-1; ++ri)
#define PCL_INSTANTIATE_IntegralImageNormalEstimation(T,NT) template class PCL_EXPORTS pcl::IntegralImageNormalEstimation<T,NT>;
-#endif
-
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointOutT>
-pcl::LinearLeastSquaresNormalEstimation<PointInT, PointOutT>::~LinearLeastSquaresNormalEstimation ()
-{
-}
+pcl::LinearLeastSquaresNormalEstimation<PointInT, PointOutT>::~LinearLeastSquaresNormalEstimation () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointOutT> void
obb_max_point_.y = std::numeric_limits <float>::min ();
obb_max_point_.z = std::numeric_limits <float>::min ();
- unsigned int number_of_points = static_cast <unsigned int> (indices_->size ());
+ auto number_of_points = static_cast <unsigned int> (indices_->size ());
for (unsigned int i_point = 0; i_point < number_of_points; i_point++)
{
float x = ((*input_)[(*indices_)[i_point]].x - mean_value_ (0)) * major_axis_ (0) +
pcl::MomentOfInertiaEstimation<PointT>::getMomentOfInertia (std::vector <float>& moment_of_inertia) const
{
moment_of_inertia.resize (moment_of_inertia_.size (), 0.0f);
- std::copy (moment_of_inertia_.begin (), moment_of_inertia_.end (), moment_of_inertia.begin ());
+ std::copy (moment_of_inertia_.cbegin (), moment_of_inertia_.cend (), moment_of_inertia.begin ());
return (is_valid_);
}
pcl::MomentOfInertiaEstimation<PointT>::getEccentricity (std::vector <float>& eccentricity) const
{
eccentricity.resize (eccentricity_.size (), 0.0f);
- std::copy (eccentricity_.begin (), eccentricity_.end (), eccentricity.begin ());
+ std::copy (eccentricity_.cbegin (), eccentricity_.cend (), eccentricity.begin ());
return (is_valid_);
}
aabb_max_point_.y = -std::numeric_limits <float>::max ();
aabb_max_point_.z = -std::numeric_limits <float>::max ();
- unsigned int number_of_points = static_cast <unsigned int> (indices_->size ());
+ auto number_of_points = static_cast <unsigned int> (indices_->size ());
for (unsigned int i_point = 0; i_point < number_of_points; i_point++)
{
mean_value_ (0) += (*input_)[(*indices_)[i_point]].x;
{
covariance_matrix.setZero ();
- unsigned int number_of_points = static_cast <unsigned int> (indices_->size ());
+ auto number_of_points = static_cast <unsigned int> (indices_->size ());
float factor = 1.0f / static_cast <float> ((number_of_points - 1 > 0)?(number_of_points - 1):1);
for (unsigned int i_point = 0; i_point < number_of_points; i_point++)
{
pcl::MomentOfInertiaEstimation<PointT>::calculateMomentOfInertia (const Eigen::Vector3f& current_axis, const Eigen::Vector3f& mean_value) const
{
float moment_of_inertia = 0.0f;
- unsigned int number_of_points = static_cast <unsigned int> (indices_->size ());
+ auto number_of_points = static_cast <unsigned int> (indices_->size ());
for (unsigned int i_point = 0; i_point < number_of_points; i_point++)
{
Eigen::Vector3f vector;
{
const float D = - normal_vector.dot (point);
- unsigned int number_of_points = static_cast <unsigned int> (indices_->size ());
+ auto number_of_points = static_cast <unsigned int> (indices_->size ());
projected_cloud->points.resize (number_of_points, PointT ());
for (unsigned int i_point = 0; i_point < number_of_points; i_point++)
{
FeatureCloudPtr feature_cloud (new FeatureCloud ());
computeFeatureAtScale (scale_values_[scale_i], feature_cloud);
- features_at_scale_[scale_i] = feature_cloud;
+ features_at_scale_.push_back(feature_cloud);
// Vectorize each feature and insert it into the vectorized feature storage
std::vector<std::vector<float> > feature_cloud_vectorized;
feature.cbegin (), mean_feature_.begin (), std::plus<>{});
}
- const float factor = std::min<float>(1, normalization_factor);
+ const float factor = std::max<float>(1, normalization_factor);
std::transform(mean_feature_.cbegin(),
mean_feature_.cend(),
mean_feature_.begin(),
unique_features_indices_.reserve (scale_values_.size ());
unique_features_table_.reserve (scale_values_.size ());
+ std::vector<float> diff_vector;
+ std::size_t size = 0;
+ for (const auto& feature : features_at_scale_vectorized_)
+ {
+ size = std::max(size, feature.size());
+ }
+ diff_vector.reserve(size);
for (std::size_t scale_i = 0; scale_i < features_at_scale_vectorized_.size (); ++scale_i)
{
// Calculate standard deviation within the scale
float standard_dev = 0.0;
- std::vector<float> diff_vector (features_at_scale_vectorized_[scale_i].size ());
diff_vector.clear();
for (const auto& feature: features_at_scale_vectorized_[scale_i])
// Select only points outside (mean +/- alpha * standard_dev)
std::list<std::size_t> indices_per_scale;
- std::vector<bool> indices_table_per_scale (features_at_scale_[scale_i]->size (), false);
- for (std::size_t point_i = 0; point_i < features_at_scale_[scale_i]->size (); ++point_i)
+ std::vector<bool> indices_table_per_scale (features_at_scale_vectorized_[scale_i].size (), false);
+ for (std::size_t point_i = 0; point_i < features_at_scale_vectorized_[scale_i].size (); ++point_i)
{
if (diff_vector[point_i] > alpha_ * standard_dev)
{
return;
}
getTranslationAndEulerAngles(transformation_.inverse (), narf36.x, narf36.y, narf36.z, narf36.roll, narf36.pitch, narf36.yaw);
- memcpy(narf36.descriptor, descriptor_, 36*sizeof(*descriptor_));
+ std::copy(descriptor_, descriptor_ + 36, narf36.descriptor);
}
//inline float Narf::getDescriptorDistance(const Narf& other) const
template<typename PointT, typename PointLT> void
pcl::OrganizedEdgeBase<PointT, PointLT>::assignLabelIndices (pcl::PointCloud<PointLT>& labels, std::vector<pcl::PointIndices>& label_indices) const
{
- const unsigned invalid_label = unsigned (0);
+ const auto invalid_label = unsigned (0);
label_indices.resize (num_of_edgetype_);
for (std::size_t idx = 0; idx < input_->size (); idx++)
{
key = std::pair<int, int> (p1, p2);
// Check to see if we already estimated this pair in the global hashmap
- std::map<std::pair<int, int>, Eigen::Vector4f, std::less<>, Eigen::aligned_allocator<std::pair<const std::pair<int, int>, Eigen::Vector4f> > >::iterator fm_it = feature_map_.find (key);
+ auto fm_it = feature_map_.find (key);
if (fm_it != feature_map_.end ())
{
pfh_tuple_ = fm_it->second;
// Estimate the PFH signature at each patch
computePointPFHRGBSignature (*surface_, *normals_, nn_indices, nr_subdiv_, pfhrgb_histogram_);
- std::copy_n (pfhrgb_histogram_.data (), pfhrgb_histogram_.size (),
+ std::copy (pfhrgb_histogram_.data (), pfhrgb_histogram_.data () + pfhrgb_histogram_.size (),
output[idx].histogram);
}
}
computeRIFT (*surface_, *gradient_, (*indices_)[idx], static_cast<float> (search_radius_), nn_indices, nn_dist_sqr, rift_descriptor);
// Default layout is column major, copy elementwise
- std::copy_n (rift_descriptor.data (), rift_descriptor.size (), output[idx].histogram);
+ std::copy (rift_descriptor.data (), rift_descriptor.data () + rift_descriptor.size (), output[idx].histogram);
}
}
const float v_length = point (coord[projection][1]) - min[coord[projection][1]];
const float u_ratio = u_length / u_bin_length;
- unsigned int row = static_cast <unsigned int> (u_ratio);
+ auto row = static_cast <unsigned int> (u_ratio);
if (row == number_of_bins_) row--;
const float v_ratio = v_length / v_bin_length;
- unsigned int col = static_cast <unsigned int> (v_ratio);
+ auto col = static_cast <unsigned int> (v_ratio);
if (col == number_of_bins_) col--;
matrix (row, col) += 1.0f;
#ifndef PCL_FEATURES_IMPL_RSD_H_
#define PCL_FEATURES_IMPL_RSD_H_
-#include <cfloat>
+#include <limits>
#include <pcl/features/rsd.h>
//////////////////////////////////////////////////////////////////////////////////////////////
for (int di=1; di<nr_subdiv; di++)
{
min_max_angle_by_dist[di].resize (2);
- min_max_angle_by_dist[di][0] = +DBL_MAX;
- min_max_angle_by_dist[di][1] = -DBL_MAX;
+ min_max_angle_by_dist[di][0] = std::numeric_limits<double>::max();
+ min_max_angle_by_dist[di][1] = std::numeric_limits<double>::lowest();
}
// Compute distance by normal angle distribution for points
unsigned char bit4 = ((yInFeatRef > 0) || ((yInFeatRef == 0.0) && (xInFeatRef < 0))) ? 1 : 0;
- unsigned char bit3 = static_cast<unsigned char> (((xInFeatRef > 0) || ((xInFeatRef == 0.0) && (yInFeatRef > 0))) ? !bit4 : bit4);
+ auto bit3 = static_cast<unsigned char> (((xInFeatRef > 0) || ((xInFeatRef == 0.0) && (yInFeatRef > 0))) ? !bit4 : bit4);
assert (bit3 == 0 || bit3 == 1);
zInFeatRef = 0;
unsigned char bit4 = ((yInFeatRef > 0) || ((yInFeatRef == 0.0) && (xInFeatRef < 0))) ? 1 : 0;
- unsigned char bit3 = static_cast<unsigned char> (((xInFeatRef > 0) || ((xInFeatRef == 0.0) && (yInFeatRef > 0))) ? !bit4 : bit4);
+ auto bit3 = static_cast<unsigned char> (((xInFeatRef > 0) || ((xInFeatRef == 0.0) && (yInFeatRef > 0))) ? !bit4 : bit4);
assert (bit3 == 0 || bit3 == 1);
assert(descLength_ == 352);
- shot_.setZero (descLength_);
+ Eigen::VectorXf shot;
+ shot.setZero (descLength_);
// Allocate enough space to hold the results
// \note This resize is irrelevant for a radiusSearch ().
}
// Estimate the SHOT descriptor at each patch
- computePointSHOT (static_cast<int> (idx), nn_indices, nn_dists, shot_);
+ computePointSHOT (static_cast<int> (idx), nn_indices, nn_dists, shot);
// Copy into the resultant cloud
for (int d = 0; d < descLength_; ++d)
- output[idx].descriptor[d] = shot_[d];
+ output[idx].descriptor[d] = shot[d];
for (int d = 0; d < 3; ++d)
{
output[idx].rf[d + 0] = (*frames_)[idx].x_axis[d];
radius1_4_ = search_radius_ / 4;
radius1_2_ = search_radius_ / 2;
- shot_.setZero (descLength_);
+ Eigen::VectorXf shot;
+ shot.setZero (descLength_);
// Allocate enough space to hold the results
// \note This resize is irrelevant for a radiusSearch ().
}
// Compute the SHOT descriptor for the current 3D feature
- computePointSHOT (static_cast<int> (idx), nn_indices, nn_dists, shot_);
+ computePointSHOT (static_cast<int> (idx), nn_indices, nn_dists, shot);
// Copy into the resultant cloud
for (int d = 0; d < descLength_; ++d)
- output[idx].descriptor[d] = shot_[d];
+ output[idx].descriptor[d] = shot[d];
for (int d = 0; d < 3; ++d)
{
output[idx].rf[d + 0] = (*frames_)[idx].x_axis[d];
!std::isfinite (current_frame.y_axis[0]) ||
!std::isfinite (current_frame.z_axis[0]) )
{
- std::fill (output[point_index].descriptor, output[point_index].descriptor + descriptor_length_,
- std::numeric_limits<float>::quiet_NaN ());
- std::fill (output[point_index].rf, output[point_index].rf + 9, 0);
+ std::fill_n (output[point_index].descriptor, descriptor_length_,
+ std::numeric_limits<float>::quiet_NaN ());
+ std::fill_n (output[point_index].rf, 9, 0);
output.is_dense = false;
continue;
}
std::vector<float> descriptor (descriptor_length_);
computePointDescriptor (point_index, descriptor);
- std::copy (descriptor.begin (), descriptor.end (), output[point_index].descriptor);
+ std::copy (descriptor.cbegin (), descriptor.cend (), output[point_index].descriptor);
}
}
if (normalize_bins_)
hist_incr = 100.0f / static_cast<float> (indices.size () - 1);
- float hist_incr_size_component = 0;;
+ float hist_incr_size_component = 0;
if (size_component_)
hist_incr_size_component = hist_incr;
(*normals_)[index].normal[2], 0);
// Normalize
double alpha = (normal.dot (d_vp_p) + 1.0) * 0.5;
- std::size_t fi = static_cast<std::size_t> (std::floor (alpha * hist_vp_.size ()));
+ auto fi = static_cast<std::size_t> (std::floor (alpha * hist_vp_.size ()));
fi = std::max<std::size_t> (0u, fi);
fi = std::min<std::size_t> (hist_vp_.size () - 1, fi);
// Bin into the histogram
for (int i = 0; i < 4; ++i)
{
- outPtr = std::copy_n (hist_f_[i].data (), hist_f_[i].size (), outPtr);
+ outPtr = std::copy (hist_f_[i].data (), hist_f_[i].data () + hist_f_[i].size (), outPtr);
}
- outPtr = std::copy_n (hist_vp_.data (), hist_vp_.size (), outPtr);
+ outPtr = std::copy (hist_vp_.data (), hist_vp_.data () + hist_vp_.size (), outPtr);
}
#define PCL_INSTANTIATE_VFHEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::VFHEstimation<T,NT,OutT>;
/** \brief Destructor */
virtual
- ~IntegralImage2D () { }
+ ~IntegralImage2D () = default;
/** \brief sets the computation for second order integral images on or off.
* \param compute_second_order_integral_images
/** \brief Destructor */
virtual
- ~IntegralImage2D () { }
+ ~IntegralImage2D () = default;
/** \brief Set the input data to compute the integral image for
* \param[in] data the input data
}
/** \brief Destructor **/
- ~IntegralImageNormalEstimation ();
+ ~IntegralImageNormalEstimation () override;
/** \brief Set the regions size which is considered for normal estimation.
* \param[in] width the width of the search rectangle
};
/** \brief Destructor */
- ~LinearLeastSquaresNormalEstimation ();
+ ~LinearLeastSquaresNormalEstimation () override;
/** \brief Computes the normal at the specified position.
* \param[in] pos_x x position (pixel)
* \ref NormalEstimationOMP for an example on how to extend this to parallel implementations.
* \author Radu B. Rusu
* \ingroup features
+ * \tparam PointOutT Suggested type is `pcl::MomentInvariants`
*/
template <typename PointInT, typename PointOutT>
class MomentInvariantsEstimation: public Feature<PointInT, PointOutT>
/** \brief Virtual destructor which frees the memory. */
- ~MomentOfInertiaEstimation ();
+ ~MomentOfInertiaEstimation () override;
/** \brief This method allows to set the angle step. It is used for the rotation
* of the axis which is used for moment of inertia/eccentricity calculation.
MultiscaleFeaturePersistence ();
/** \brief Empty destructor */
- ~MultiscaleFeaturePersistence () {}
+ ~MultiscaleFeaturePersistence () override = default;
/** \brief Method that calls computeFeatureAtScale () for each scale parameter */
void
#include <pcl/point_cloud.h>
#include <pcl/point_representation.h>
+#include <algorithm>
+
namespace pcl
{
// Forward declarations
using PointT = Narf *;
FeaturePointRepresentation(int nr_dimensions) { this->nr_dimensions_ = nr_dimensions; }
/** \brief Empty destructor */
- ~FeaturePointRepresentation () {}
- void copyToFloatArray (const PointT& p, float* out) const override { memcpy(out, p->getDescriptor(), sizeof(*p->getDescriptor())*this->nr_dimensions_); }
+ ~FeaturePointRepresentation () override = default;
+ void copyToFloatArray (const PointT& p, float* out) const override {
+ auto descriptor = p->getDescriptor();
+ std::copy(descriptor, descriptor + this->nr_dimensions_, out);
+ }
};
protected:
/** Constructor */
NarfDescriptor (const RangeImage* range_image=nullptr, const pcl::Indices* indices=nullptr);
/** Destructor */
- ~NarfDescriptor();
+ ~NarfDescriptor() override;
// =====METHODS=====
//! Set input data
};
/** \brief Empty destructor */
- ~NormalEstimation () {}
+ ~NormalEstimation () override = default;
/** \brief Compute the Least-Squares plane fit for a given set of points, using their indices,
* and return the estimated plane parameters together with the surface curvature.
/** \brief Destructor for OrganizedEdgeBase */
- ~OrganizedEdgeBase ()
- {
- }
+ ~OrganizedEdgeBase () override = default;
/** \brief Perform the 3D edge detection (edges from depth discontinuities)
* \param[out] labels a PointCloud of edge labels
/** \brief Destructor for OrganizedEdgeFromRGB */
- ~OrganizedEdgeFromRGB ()
- {
- }
+ ~OrganizedEdgeFromRGB () override = default;
/** \brief Perform the 3D edge detection (edges from depth discontinuities and RGB Canny edge) and assign point indices for each edge label
* \param[out] labels a PointCloud of edge labels
/** \brief Destructor for OrganizedEdgeFromNormals */
- ~OrganizedEdgeFromNormals ()
- {
- }
+ ~OrganizedEdgeFromNormals () override = default;
/** \brief Perform the 3D edge detection (edges from depth discontinuities and high curvature regions) and assign point indices for each edge label
* \param[out] labels a PointCloud of edge labels
/** \brief Destructor for OrganizedEdgeFromRGBNormals */
- ~OrganizedEdgeFromRGBNormals ()
- {
- }
+ ~OrganizedEdgeFromRGBNormals () override = default;
/** \brief Perform the 3D edge detection (edges from depth discontinuities, RGB Canny edge, and high curvature regions) and assign point indices for each edge label
* \param[out] labels a PointCloud of edge labels
/** Constructor */
RangeImageBorderExtractor (const RangeImage* range_image=nullptr);
/** Destructor */
- ~RangeImageBorderExtractor ();
+ ~RangeImageBorderExtractor () override;
// =====METHODS=====
/** \brief Provide a pointer to the range image
/** \brief Virtual destructor. */
- ~ROPSEstimation ();
+ ~ROPSEstimation () override;
/** \brief Allows to set the number of partition bins that is used for distribution matrix calculation.
* \param[in] number_of_bins number of partition bins
* @note The code is stateful as we do not expect this class to be multicore parallelized.
* \author Zoltan-Csaba Marton
* \ingroup features
+ * \tparam PointOutT Suggested type is `pcl::PrincipalRadiiRSD`
*/
template <typename PointInT, typename PointNT, typename PointOutT>
class RSDEstimation : public FeatureFromNormals<PointInT, PointNT, PointOutT>
/** \brief Set the maximum radius, above which everything can be considered planar.
* \note the order of magnitude should be around 10-20 times the search radius (0.2 works well for typical datasets).
- * \note on accurate 3D data (e.g. openni sernsors) a search radius as low as 0.01 still gives good results.
+ * \note on accurate 3D data (e.g. openni sensors) a search radius as low as 0.01 still gives good results.
* \param[in] plane_radius the new plane radius
*/
inline void
public:
/** \brief Empty destructor */
- ~SHOTEstimationBase () {}
+ ~SHOTEstimationBase () override = default;
/** \brief Estimate the SHOT descriptor for a given point based on its spatial neighborhood of 3D points with normals
* \param[in] index the index of the point in indices_
/** \brief The number of bins in each shape histogram. */
int nr_shape_bins_;
- /** \brief Placeholder for a point's SHOT. */
- Eigen::VectorXf shot_;
-
/** \brief The radius used for the LRF computation */
float lrf_radius_;
using SHOTEstimationBase<PointInT, PointNT, PointOutT, PointRFT>::radius1_2_;
using SHOTEstimationBase<PointInT, PointNT, PointOutT, PointRFT>::maxAngularSectors_;
using SHOTEstimationBase<PointInT, PointNT, PointOutT, PointRFT>::interpolateSingleChannel;
- using SHOTEstimationBase<PointInT, PointNT, PointOutT, PointRFT>::shot_;
using FeatureWithLocalReferenceFrames<PointInT, PointRFT>::frames_;
using PointCloudIn = typename Feature<PointInT, PointOutT>::PointCloudIn;
};
/** \brief Empty destructor */
- ~SHOTEstimation () {}
+ ~SHOTEstimation () override = default;
/** \brief Estimate the SHOT descriptor for a given point based on its spatial neighborhood of 3D points with normals
* \param[in] index the index of the point in indices_
using SHOTEstimationBase<PointInT, PointNT, PointOutT, PointRFT>::radius1_2_;
using SHOTEstimationBase<PointInT, PointNT, PointOutT, PointRFT>::maxAngularSectors_;
using SHOTEstimationBase<PointInT, PointNT, PointOutT, PointRFT>::interpolateSingleChannel;
- using SHOTEstimationBase<PointInT, PointNT, PointOutT, PointRFT>::shot_;
using FeatureWithLocalReferenceFrames<PointInT, PointRFT>::frames_;
using PointCloudIn = typename Feature<PointInT, PointOutT>::PointCloudIn;
};
/** \brief Empty destructor */
- ~SHOTColorEstimation () {}
+ ~SHOTColorEstimation () override = default;
/** \brief Estimate the SHOT descriptor for a given point based on its spatial neighborhood of 3D points with normals
* \param[in] index the index of the point in indices_
}
/** \brief Empty destructor */
- ~SHOTLocalReferenceFrameEstimation () {}
+ ~SHOTLocalReferenceFrameEstimation () override = default;
protected:
using Feature<PointInT, PointOutT>::feature_name_;
}
/** \brief Empty destructor */
- ~SHOTLocalReferenceFrameEstimationOMP () {}
+ ~SHOTLocalReferenceFrameEstimationOMP () override = default;
/** \brief Initialize the scheduler and set the number of threads to use.
* \param nr_threads the number of hardware threads to use (0 sets the value back to automatic)
unsigned int min_pts_neighb = 0);
/** \brief Empty destructor */
- ~SpinImageEstimation () {}
+ ~SpinImageEstimation () override = default;
/** \brief Sets spin-image resolution.
*
/** \brief Empty constructor */
- StatisticalMultiscaleInterestRegionExtraction ()
- {};
+ StatisticalMultiscaleInterestRegionExtraction () = default;
/** \brief Method that generates the underlying nearest neighbor graph based on the
* input point cloud
search_radius_ = 2.0;
}
- ~UniqueShapeContext() { }
+ ~UniqueShapeContext() override = default;
/** \return The number of bins along the azimuth. */
inline std::size_t
#include <iostream>
#include <fstream>
#include <cmath>
+#include <map> // for std::multimap
using std::cout;
using std::cerr;
using std::vector;
delete[] surface_patch_;
surface_patch_ = new float[surface_patch_pixel_size_*surface_patch_pixel_size_];
}
- memcpy(surface_patch_, other.surface_patch_, sizeof(*surface_patch_)*surface_patch_pixel_size_*surface_patch_pixel_size_);
+ std::copy(other.surface_patch_, other.surface_patch_ + surface_patch_pixel_size_*surface_patch_pixel_size_, surface_patch_);
surface_patch_world_size_ = other.surface_patch_world_size_;
surface_patch_rotation_ = other.surface_patch_rotation_;
delete[] descriptor_;
descriptor_ = new float[descriptor_size_];
}
- memcpy(descriptor_, other.descriptor_, sizeof(*descriptor_)*descriptor_size_);
+ std::copy(other.descriptor_, other.descriptor_ + descriptor_size_, descriptor_);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
while (!scored_orientations.empty())
{
- std::multimap<float, float>::iterator best_remaining_orientation_it = scored_orientations.end();
+ auto best_remaining_orientation_it = scored_orientations.end();
--best_remaining_orientation_it;
rotations.push_back(best_remaining_orientation_it->second);
strengths.push_back(best_remaining_orientation_it->first);
scored_orientations.erase(best_remaining_orientation_it);
- for (std::multimap<float, float>::iterator it = scored_orientations.begin(); it!=scored_orientations.end();)
+ for (auto it = scored_orientations.begin(); it!=scored_orientations.end();)
{
- std::multimap<float, float>::iterator current_it = it++;
+ auto current_it = it++;
if (normAngle(current_it->second - rotations.back()) < min_angle_dist_between_rotations)
scored_orientations.erase(current_it);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-NarfDescriptor::~NarfDescriptor ()
-{
-}
+NarfDescriptor::~NarfDescriptor () = default;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
}
}
- Eigen::Vector3f** average_border_directions = new Eigen::Vector3f*[size];
+ auto** average_border_directions = new Eigen::Vector3f*[size];
int radius = parameters_.pixel_radius_border_direction;
int minimum_weight = radius+1;
float min_cos_angle=std::cos(deg2rad(120.0f));
const RangeImage& range_image = *range_image_;
- Eigen::Vector3f* blurred_directions = new Eigen::Vector3f[range_image.width*range_image.height];
+ auto* blurred_directions = new Eigen::Vector3f[range_image.width*range_image.height];
float* blurred_scores = new float[range_image.width*range_image.height];
for (int y=0; y<int(range_image.height); ++y)
{
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
src/passthrough.cpp
src/shadowpoints.cpp
src/project_inliers.cpp
+ src/pyramid.cpp
src/radius_outlier_removal.cpp
src/random_sample.cpp
src/normal_space.cpp
src/morphological_filter.cpp
src/local_maximum.cpp
src/model_outlier_removal.cpp
+ src/farthest_point_sampling.cpp
)
set(incs
"include/pcl/${SUBSYS_NAME}/morphological_filter.h"
"include/pcl/${SUBSYS_NAME}/local_maximum.h"
"include/pcl/${SUBSYS_NAME}/model_outlier_removal.h"
+ "include/pcl/${SUBSYS_NAME}/farthest_point_sampling.h"
)
set(experimental_incs
"include/pcl/${SUBSYS_NAME}/experimental/functor_filter.h"
"include/pcl/${SUBSYS_NAME}/impl/morphological_filter.hpp"
"include/pcl/${SUBSYS_NAME}/impl/local_maximum.hpp"
"include/pcl/${SUBSYS_NAME}/impl/model_outlier_removal.hpp"
+ "include/pcl/${SUBSYS_NAME}/impl/farthest_point_sampling.hpp"
)
set(LIB_NAME "pcl_${SUBSYS_NAME}")
/** \brief Destructor.
*/
- ~ApproximateVoxelGrid ()
+ ~ApproximateVoxelGrid () override
{
delete [] history_;
}
using Ptr = shared_ptr<BilateralFilter<PointT> >;
using ConstPtr = shared_ptr<const BilateralFilter<PointT> >;
-
/** \brief Constructor.
* Sets sigma_s_ to 0 and sigma_r_ to MAXDBL
tree_ ()
{
}
-
-
- /** \brief Filter the input data and store the results into output
- * \param[out] output the resultant point cloud message
- */
- void
- applyFilter (PointCloud &output) override;
-
/** \brief Compute the intensity average for a single point
* \param[in] pid the point index to compute the weight for
* \param[in] indices the set of nearest neighor indices
setSearchMethod (const KdTreePtr &tree)
{ tree_ = tree; }
- private:
+ protected:
+ /** \brief Filter the input data and store the results into output
+ * \param[out] output the resultant point cloud message
+ */
+ void
+ applyFilter (PointCloud &output) override;
+ private:
/** \brief The bilateral filter Gaussian distance kernel.
* \param[in] x the spatial distance (distance or intensity)
* \param[in] sigma standard deviation
/**
* \brief virtual destructor
*/
- ~BoxClipper3D () noexcept;
+ ~BoxClipper3D () noexcept override;
bool
clipPoint3D (const PointT& point) const override;
/**
* \brief virtual destructor. Never throws an exception.
*/
- virtual ~Clipper3D () noexcept {}
+ virtual ~Clipper3D () noexcept = default;
/**
* \brief interface to clip a single point
ComparisonBase () : capable_ (false), offset_ (), op_ () {}
/** \brief Destructor. */
- virtual ~ComparisonBase () {}
+ virtual ~ComparisonBase () = default;
/** \brief Return if the comparison is capable. */
inline bool
}
/** \brief Destructor. */
- ~FieldComparison ();
+ ~FieldComparison () override;
/** \brief Determine the result of this comparison.
* \param point the point to evaluate
PackedRGBComparison (const std::string &component_name, ComparisonOps::CompareOp op, double compare_val);
/** \brief Destructor. */
- ~PackedRGBComparison () {}
+ ~PackedRGBComparison () override = default;
/** \brief Determine the result of this comparison.
* \param point the point to evaluate
PackedHSIComparison (const std::string &component_name, ComparisonOps::CompareOp op, double compare_val);
/** \brief Destructor. */
- ~PackedHSIComparison () {}
+ ~PackedHSIComparison () override = default;
/** \brief Determine the result of this comparison.
* \param point the point to evaluate
* One can also use TfQuadraticXYZComparison for simpler geometric shapes by defining the
* quadratic parts (i.e. the matrix A) to be zero. By combining different instances of
* TfQuadraticXYZComparison one can get more complex shapes. For example, to have a simple
- * cylinder (along the x-axis) of specific length one needs three comparisons combined as AND condition:
- * 1. The cylinder: A = [0 0 0, 0 1 0, 0 0 1]; v = [0, 0, 0]; c = radius²; OP = LT (meaning "<")
- * 2. X-min limit: A = 0; v = [1, 0, 0]; c = x_min; OP = GT
- * 3. X-max ...
+ * cylinder (along the x-axis) of specific radius and length, three comparisons need to be
+ * combined as AND condition:
+ * 1. side: A = [0 0 0, 0 1 0, 0 0 1]; v = [0, 0, 0]; c = -radius²; OP = LT (meaning "<")
+ * 2. bottom base: A = 0; v = [0.5, 0, 0]; c = -x_min; OP = GT
+ * 3. top base: A = 0; v = [0.5, 0, 0]; c = -x_max; OP = LT
*
* \author Julian Löchner
*/
TfQuadraticXYZComparison ();
/** \brief Empty destructor */
- ~TfQuadraticXYZComparison () {}
+ ~TfQuadraticXYZComparison () override = default;
/** \brief Constructor.
* \param op the operator "[OP]" of the comparison "p'Ap + 2v'p + c [OP] 0".
using ConditionBase = pcl::ConditionBase<PointT>;
using ConditionBasePtr = typename ConditionBase::Ptr;
using ConditionBaseConstPtr = typename ConditionBase::ConstPtr;
+
+ using Ptr = shared_ptr<ConditionalRemoval<PointT> >;
+ using ConstPtr = shared_ptr<const ConditionalRemoval<PointT> >;
+
/** \brief the default constructor.
*
/// Constructor
Convolution ();
/// Empty destructor
- ~Convolution () {}
+ ~Convolution () = default;
/** \brief Provide a pointer to the input dataset
* \param cloud the const boost shared pointer to a PointCloud message
* \remark Will perform a deep copy
#pragma once
#include <pcl/pcl_base.h>
+#include <boost/optional.hpp>
namespace pcl
{
ConvolvingKernel () {}
/// \brief empty destructor
- virtual ~ConvolvingKernel () {}
+ virtual ~ConvolvingKernel() = default;
/** \brief Set input cloud
* \param[in] input source point cloud
, threshold_ (std::numeric_limits<float>::infinity ())
{}
- virtual ~GaussianKernel () {}
-
/** Set the sigma parameter of the Gaussian
* \param[in] sigma
*/
: GaussianKernel <PointInT, PointOutT> ()
{}
- ~GaussianKernelRGB () {}
-
PointOutT
operator() (const Indices& indices, const std::vector<float>& distances);
};
/** \brief Constructor */
Convolution3D ();
- /** \brief Empty destructor */
- ~Convolution3D () {}
-
/** \brief Initialize the scheduler and set the number of threads to use.
* \param nr_threads the number of hardware threads to use (0 sets the value back to automatic)
*/
using PointCloudConstPtr = typename PointCloud::ConstPtr;
public:
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
using Ptr = shared_ptr<CropBox<PointT> >;
using ConstPtr = shared_ptr<const CropBox<PointT> >;
using PCLPointCloud2ConstPtr = PCLPointCloud2::ConstPtr;
public:
+ PCL_MAKE_ALIGNED_OPERATOR_NEW
+
/** \brief Constructor.
* \param[in] extract_removed_indices Set to true if you want to be able to extract the indices of points being removed (default = false).
*/
}
protected:
- /** \brief Filter the input points using the 2D or 3D polygon hull.
- * \param[out] output The set of points that passed the filter
- */
- void
- applyFilter (PointCloud &output) override;
/** \brief Filter the input points using the 2D or 3D polygon hull.
* \param[out] indices the indices of the set of points that passed the filter.
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2020-, Open Perception, Inc.
+ *
+ * All rights reserved
+ */
+
+#pragma once
+
+#include <pcl/filters/filter_indices.h>
+
+#include <climits>
+#include <random>
+
+namespace pcl
+ {
+ /** \brief @b FarthestPointSampling applies farthest point sampling using euclidean
+ * distance, starting with a random point, utilizing a naive method.
+ * \author Haritha Jayasinghe
+ * \ingroup filters
+ * \todo add support to export/import distance metric
+ */
+ template<typename PointT>
+ class FarthestPointSampling : public FilterIndices<PointT>
+ {
+ using PCLBase<PointT>::input_;
+ using PCLBase<PointT>::indices_;
+ using Filter<PointT>::filter_name_;
+ using FilterIndices<PointT>::keep_organized_;
+ using FilterIndices<PointT>::user_filter_value_;
+ using FilterIndices<PointT>::extract_removed_indices_;
+ using FilterIndices<PointT>::removed_indices_;
+
+ using typename FilterIndices<PointT>::PointCloud;
+
+ public:
+ /** \brief Empty constructor. */
+ FarthestPointSampling (bool extract_removed_indices = false) :
+ FilterIndices<PointT> (extract_removed_indices),
+ sample_size_ (std::numeric_limits<int>::max ()),
+ seed_ (std::random_device()())
+ {
+ filter_name_ = "FarthestPointSamping";
+ }
+
+ /** \brief Set number of points to be sampled.
+ * \param sample_size the number of points to sample
+ */
+ inline void
+ setSample (std::size_t sample_size)
+ {
+ sample_size_ = sample_size;
+ }
+
+ /** \brief Get the value of the internal \a sample_size parameter.
+ */
+ inline std::size_t
+ getSample () const
+ {
+ return (sample_size_);
+ }
+
+ /** \brief Set seed of random function.
+ * \param seed for the random number generator, to choose the first sample point
+ */
+ inline void
+ setSeed (unsigned int seed)
+ {
+ seed_ = seed;
+ }
+
+ /** \brief Get the value of the internal \a seed_ parameter.
+ */
+ inline unsigned int
+ getSeed () const
+ {
+ return (seed_);
+ }
+
+ protected:
+
+ /** \brief Number of points that will be returned. */
+ std::size_t sample_size_;
+ /** \brief Random number seed. */
+ unsigned int seed_;
+
+ /** \brief Sample of point indices
+ * \param indices indices of the filtered point cloud
+ */
+ void
+ applyFilter (pcl::Indices &indices) override;
+
+ };
+ }
+
+#ifdef PCL_NO_PRECOMPILE
+#include <pcl/filters/impl/farthest_point_sampling.hpp>
+#endif
{ }
/** \brief Empty destructor */
- ~FastBilateralFilter () {}
+ ~FastBilateralFilter () override = default;
/** \brief Set the standard deviation of the Gaussian used by the bilateral filter for
* the spatial neighborhood/window.
FrustumCulling (bool extract_removed_indices = false)
: FilterIndices<PointT> (extract_removed_indices)
, camera_pose_ (Eigen::Matrix4f::Identity ())
- , hfov_ (60.0f)
- , vfov_ (60.0f)
+ , fov_left_bound_ (-30.0f)
+ , fov_right_bound_ (30.0f)
+ , fov_lower_bound_ (-30.0f)
+ , fov_upper_bound_ (30.0f)
, np_dist_ (0.1f)
, fp_dist_ (5.0f)
+ , roi_x_ (0.5f)
+ , roi_y_ (0.5f)
+ , roi_w_ (1.0f)
+ , roi_h_ (1.0f)
{
filter_name_ = "FrustumCulling";
}
/** \brief Set the horizontal field of view for the camera in degrees
* \param[in] hfov the field of view
+ * Note: setHorizontalFOV(60.0) is equivalent to setHorizontalFOV(-30.0, 30.0).
*/
void
setHorizontalFOV (float hfov)
{
- hfov_ = hfov;
+ if (hfov <= 0 || hfov >= 180)
+ {
+ throw PCLException ("Horizontal field of view should be between 0 and 180(excluded).",
+ "frustum_culling.h", "setHorizontalFOV");
+ }
+ fov_left_bound_ = -hfov / 2;
+ fov_right_bound_ = hfov / 2;
+ }
+
+ /** \brief Set the horizontal field of view for the camera in degrees
+ * \param[in] fov_left_bound the left bound of horizontal field of view
+ * \param[in] fov_right_bound the right bound of horizontal field of view
+ * Note: Bounds can be either positive or negative values.
+ * Negative value means the camera would look to its left,
+ * and positive value means the camera would look to its right.
+ * In general cases, fov_left_bound should be set to a negative value,
+ * if it is set to a positive value, the camera would only look to its right.
+ * Also note that setHorizontalFOV(-30.0, 30.0) is equivalent to setHorizontalFOV(60.0).
+ */
+ void
+ setHorizontalFOV (float fov_left_bound, float fov_right_bound)
+ {
+ if (fov_left_bound <= -90 || fov_right_bound >= 90 || fov_left_bound >= fov_right_bound)
+ {
+ throw PCLException ("Horizontal field of view bounds should be between -90 and 90(excluded). "
+ "And left bound should be smaller than right bound.",
+ "frustum_culling.h", "setHorizontalFOV");
+ }
+ fov_left_bound_ = fov_left_bound;
+ fov_right_bound_ = fov_right_bound;
}
/** \brief Get the horizontal field of view for the camera in degrees */
- float
- getHorizontalFOV () const
+ float
+ getHorizontalFOV() const
{
- return (hfov_);
+ if (std::fabs(fov_right_bound_) != std::fabs(fov_left_bound_)) {
+ PCL_WARN("Your horizontal field of view is asymmetrical: "
+ "left bound's absolute value(%f) != right bound's absolute value(%f)! "
+ "Please use getHorizontalFOV (float& fov_left_bound, float& fov_right_bound) instead.\n",
+ std::fabs(fov_left_bound_), std::fabs(fov_right_bound_));
+ }
+ return (fov_right_bound_ - fov_left_bound_);
+ }
+
+ /** \brief Get the horizontal field of view for the camera in degrees */
+ void
+ getHorizontalFOV (float& fov_left_bound, float& fov_right_bound) const
+ {
+ fov_left_bound = fov_left_bound_;
+ fov_right_bound = fov_right_bound_;
}
/** \brief Set the vertical field of view for the camera in degrees
* \param[in] vfov the field of view
+ * Note: setVerticalFOV(60.0) is equivalent to setVerticalFOV(-30.0, 30.0).
*/
void
setVerticalFOV (float vfov)
{
- vfov_ = vfov;
+ if (vfov <= 0 || vfov >= 180)
+ {
+ throw PCLException ("Vertical field of view should be between 0 and 180(excluded).",
+ "frustum_culling.h", "setVerticalFOV");
+ }
+ fov_lower_bound_ = -vfov / 2;
+ fov_upper_bound_ = vfov / 2;
+ }
+
+ /** \brief Set the vertical field of view for the camera in degrees
+ * \param[in] fov_lower_bound the lower bound of vertical field of view
+ * \param[in] fov_upper_bound the upper bound of vertical field of view
+ * Note: Bounds can be either positive or negative values.
+ * Negative value means the camera would look down,
+ * and positive value means the camera would look up.
+ * In general cases, fov_lower_bound should be set to a negative value,
+ * if it is set to a positive value, the camera would only look up.
+ * Also note that setVerticalFOV(-30.0, 30.0) is equivalent to setVerticalFOV(60.0).
+ */
+ void
+ setVerticalFOV (float fov_lower_bound, float fov_upper_bound)
+ {
+ if (fov_lower_bound <= -90 || fov_upper_bound >= 90 || fov_lower_bound >= fov_upper_bound)
+ {
+ throw PCLException ("Vertical field of view bounds should be between -90 and 90(excluded). "
+ "And lower bound should be smaller than upper bound.",
+ "frustum_culling.h", "setVerticalFOV");
+ }
+ fov_lower_bound_ = fov_lower_bound;
+ fov_upper_bound_ = fov_upper_bound;
}
/** \brief Get the vertical field of view for the camera in degrees */
- float
- getVerticalFOV () const
+ float
+ getVerticalFOV() const
+ {
+ if (std::fabs(fov_upper_bound_) != std::fabs(fov_lower_bound_)) {
+ PCL_WARN("Your vertical field of view is asymmetrical: "
+ "lower bound's absolute value(%f) != upper bound's absolute value(%f)! "
+ "Please use getVerticalFOV (float& fov_lower_bound, float& fov_upper_bound) instead.\n",
+ std::fabs(fov_lower_bound_), std::fabs(fov_upper_bound_));
+ }
+ return (fov_upper_bound_ - fov_lower_bound_);
+ }
+
+ /** \brief Get the vertical field of view for the camera in degrees */
+ void
+ getVerticalFOV (float& fov_lower_bound, float& fov_upper_bound) const
{
- return (vfov_);
+ fov_lower_bound = fov_lower_bound_;
+ fov_upper_bound = fov_upper_bound_;
}
/** \brief Set the near plane distance
- * \param[in] np_dist the near plane distance
+ * \param[in] np_dist the near plane distance. You can set this to 0 to disable near-plane filtering and extract a rectangular pyramid instead of a frustum.
*/
void
setNearPlaneDistance (float np_dist)
{
+ if (np_dist < 0.0f)
+ {
+ throw PCLException ("Near plane distance should be greater than or equal to 0.",
+ "frustum_culling.h", "setNearPlaneDistance");
+ }
np_dist_ = np_dist;
}
}
/** \brief Set the far plane distance
- * \param[in] fp_dist the far plane distance
+ * \param[in] fp_dist the far plane distance.
+ * You can set this to std::numeric_limits<float>::max(), then points will not be filtered by the far plane.
*/
void
setFarPlaneDistance (float fp_dist)
{
+ if (fp_dist <= 0.0f)
+ {
+ throw PCLException ("Far plane distance should be greater than 0.",
+ "frustum_culling.h", "setFarPlaneDistance");
+ }
fp_dist_ = fp_dist;
}
{
return (fp_dist_);
}
+
+ /** \brief Set the region of interest (ROI) in normalized values
+ *
+ * Default value of ROI: roi_{x, y} = 0.5, roi_{w, h} = 1.0
+ * This corresponds to maximal FoV and returns all the points in the frustum
+ * Can be used to cut out objects based on 2D bounding boxes by object detection.
+ *
+ * \param[in] roi_x X center position of ROI
+ * \param[in] roi_y Y center position of ROI
+ * \param[in] roi_w Width of ROI
+ * \param[in] roi_h Height of ROI
+ */
+ void
+ setRegionOfInterest (float roi_x, float roi_y, float roi_w, float roi_h)
+ {
+ if ((roi_x > 1.0f) || (roi_x < 0.0f) ||
+ (roi_y > 1.0f) || (roi_y < 0.0f) ||
+ (roi_w <= 0.0f) || (roi_w > 1.0f) ||
+ (roi_h <= 0.0f) || (roi_h > 1.0f))
+ {
+ throw PCLException ("ROI X-Y values should be between 0 and 1. "
+ "Width and height must not be zero.",
+ "frustum_culling.h", "setRegionOfInterest");
+ }
+ roi_x_ = roi_x;
+ roi_y_ = roi_y;
+ roi_w_ = roi_w;
+ roi_h_ = roi_h;
+ }
+
+ /** \brief Get the region of interest (ROI) in normalized values
+ * \param[in] roi_x X center position of ROI
+ * \param[in] roi_y Y center position of ROI
+ * \param[in] roi_w Width of ROI
+ * \param[in] roi_h Height of ROI
+ */
+ void
+ getRegionOfInterest (float &roi_x, float &roi_y, float &roi_w, float &roi_h) const
+ {
+ roi_x = roi_x_;
+ roi_y = roi_y_;
+ roi_w = roi_w_;
+ roi_h = roi_h_;
+ }
protected:
using PCLBase<PointT>::input_;
/** \brief The camera pose */
Eigen::Matrix4f camera_pose_;
- /** \brief Horizontal field of view */
- float hfov_;
- /** \brief Vertical field of view */
- float vfov_;
+ /** \brief The left bound of horizontal field of view */
+ float fov_left_bound_;
+ /** \brief The right bound of horizontal field of view */
+ float fov_right_bound_;
+ /** \brief The lower bound of vertical field of view */
+ float fov_lower_bound_;
+ /** \brief The upper bound of vertical field of view */
+ float fov_upper_bound_;
/** \brief Near plane distance */
float np_dist_;
/** \brief Far plane distance */
float fp_dist_;
+ /** \brief Region of interest x center position (normalized)*/
+ float roi_x_;
+ /** \brief Region of interest y center position (normalized)*/
+ float roi_y_;
+ /** \brief Region of interest width (normalized)*/
+ float roi_w_;
+ /** \brief Region of interest height (normalized)*/
+ float roi_h_;
public:
PCL_MAKE_ALIGNED_OPERATOR_NEW
}
/** \brief Destructor. */
- ~GridMinimum ()
- {
- }
+ ~GridMinimum () override = default;
/** \brief Set the grid resolution.
* \param[in] resolution the grid resolution
int ix = static_cast<int> (std::floor (point.x * inverse_leaf_size_[0]));
int iy = static_cast<int> (std::floor (point.y * inverse_leaf_size_[1]));
int iz = static_cast<int> (std::floor (point.z * inverse_leaf_size_[2]));
- unsigned int hash = static_cast<unsigned int> ((ix * 7171 + iy * 3079 + iz * 4231) & (histsize_ - 1));
+ auto hash = static_cast<unsigned int> ((ix * 7171 + iy * 3079 + iz * 4231) & (histsize_ - 1));
he *hhe = &history_[hash];
if (hhe->count && ((ix != hhe->ix) || (iy != hhe->iy) || (iz != hhe->iz)))
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT>
pcl::BoxClipper3D<PointT>::~BoxClipper3D () noexcept
-{
-}
+= default;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> void
pcl::PackedRGBComparison<PointT>::evaluate (const PointT &point) const
{
// extract the component value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
std::uint8_t my_val = *(pt_data + component_offset_);
// now do the comparison
static std::uint8_t i_ = 0;
// We know that rgb data is 32 bit aligned (verified in the ctor) so...
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
- const std::uint32_t* rgb_data = reinterpret_cast<const std::uint32_t*> (pt_data + rgb_offset_);
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
+ const auto* rgb_data = reinterpret_cast<const std::uint32_t*> (pt_data + rgb_offset_);
std::uint32_t new_rgb_val = *rgb_data;
if (rgb_val_ != new_rgb_val)
// if p(data) == val return 0
// if p(data) < val return -1
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&p);
-
- switch (datatype_)
- {
- case pcl::PCLPointField::INT8 :
- {
- std::int8_t pt_val;
- memcpy (&pt_val, pt_data + this->offset_, sizeof (std::int8_t));
- return (pt_val > static_cast<std::int8_t>(val)) - (pt_val < static_cast<std::int8_t> (val));
- }
- case pcl::PCLPointField::UINT8 :
- {
- std::uint8_t pt_val;
- memcpy (&pt_val, pt_data + this->offset_, sizeof (std::uint8_t));
- return (pt_val > static_cast<std::uint8_t>(val)) - (pt_val < static_cast<std::uint8_t> (val));
- }
- case pcl::PCLPointField::INT16 :
- {
- std::int16_t pt_val;
- memcpy (&pt_val, pt_data + this->offset_, sizeof (std::int16_t));
- return (pt_val > static_cast<std::int16_t>(val)) - (pt_val < static_cast<std::int16_t> (val));
- }
- case pcl::PCLPointField::UINT16 :
- {
- std::uint16_t pt_val;
- memcpy (&pt_val, pt_data + this->offset_, sizeof (std::uint16_t));
- return (pt_val > static_cast<std::uint16_t> (val)) - (pt_val < static_cast<std::uint16_t> (val));
- }
- case pcl::PCLPointField::INT32 :
- {
- std::int32_t pt_val;
- memcpy (&pt_val, pt_data + this->offset_, sizeof (std::int32_t));
- return (pt_val > static_cast<std::int32_t> (val)) - (pt_val < static_cast<std::int32_t> (val));
- }
- case pcl::PCLPointField::UINT32 :
- {
- std::uint32_t pt_val;
- memcpy (&pt_val, pt_data + this->offset_, sizeof (std::uint32_t));
- return (pt_val > static_cast<std::uint32_t> (val)) - (pt_val < static_cast<std::uint32_t> (val));
- }
- case pcl::PCLPointField::FLOAT32 :
- {
- float pt_val;
- memcpy (&pt_val, pt_data + this->offset_, sizeof (float));
- return (pt_val > static_cast<float> (val)) - (pt_val < static_cast<float> (val));
- }
- case pcl::PCLPointField::FLOAT64 :
- {
- double pt_val;
- memcpy (&pt_val, pt_data + this->offset_, sizeof (double));
- return (pt_val > val) - (pt_val < val);
- }
- default :
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&p);
+
+#define SAFE_COMPARE(CASE_LABEL) \
+ case CASE_LABEL: { \
+ pcl::traits::asType_t<CASE_LABEL> pt_val; \
+ memcpy(&pt_val, pt_data + this->offset_, sizeof(pt_val)); \
+ return (pt_val > static_cast<pcl::traits::asType_t<CASE_LABEL>>(val)) - \
+ (pt_val < static_cast<pcl::traits::asType_t<CASE_LABEL>>(val)); \
+ }
+
+ switch (datatype_)
+ {
+ SAFE_COMPARE(pcl::PCLPointField::BOOL)
+ SAFE_COMPARE(pcl::PCLPointField::INT8)
+ SAFE_COMPARE(pcl::PCLPointField::UINT8)
+ SAFE_COMPARE(pcl::PCLPointField::INT16)
+ SAFE_COMPARE(pcl::PCLPointField::UINT16)
+ SAFE_COMPARE(pcl::PCLPointField::INT32)
+ SAFE_COMPARE(pcl::PCLPointField::UINT32)
+ SAFE_COMPARE(pcl::PCLPointField::INT64)
+ SAFE_COMPARE(pcl::PCLPointField::UINT64)
+ SAFE_COMPARE(pcl::PCLPointField::FLOAT32)
+ SAFE_COMPARE(pcl::PCLPointField::FLOAT64)
+
+ default :
PCL_WARN ("[pcl::PointDataAtOffset::compare] unknown data_type!\n");
return (0);
}
+#undef SAFE_COMPARE
}
//////////////////////////////////////////////////////////////////////////
#ifndef PCL_FILTERS_CONVOLUTION_3D_IMPL_HPP
#define PCL_FILTERS_CONVOLUTION_3D_IMPL_HPP
+#include <pcl/search/organized.h>
+#include <pcl/search/kdtree.h>
#include <pcl/pcl_config.h>
#include <pcl/point_types.h>
scaled_points_[p_i] = (*input_)[(*indices_)[p_i]].getVector3fMap () - centroid;
average_norm += scaled_points_[p_i].norm ();
}
+
average_norm /= double (scaled_points_.size ());
for (std::size_t p_i = 0; p_i < scaled_points_.size (); ++p_i)
scaled_points_[p_i] /= float (average_norm);
#include <pcl/filters/crop_hull.h>
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-template<typename PointT>
-PCL_DEPRECATED(1, 13, "This is a trivial call to base class method")
-void
-pcl::CropHull<PointT>::applyFilter (PointCloud &output)
-{
- FilterIndices<PointT>::applyFilter(output);
-}
-
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointT> void
pcl::CropHull<PointT>::applyFilter (Indices &indices)
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)
- indices.push_back ((*indices_)[index]);
- else if (!crop_outside_)
+ bool crosses = (crossings[0]&1) + (crossings[1]&1) + (crossings[2]&1) > 1;
+ if ((crop_outside_ && crosses) || (!crop_outside_ && !crosses))
indices.push_back ((*indices_)[index]);
else
removed_indices_->push_back ((*indices_)[index]);
pcl::for_each_type<FieldList> (pcl::detail::FieldAdder<PointT> (fields));
for (const auto& rii : (*removed_indices_)) // rii = removed indices iterator
{
- uindex_t pt_index = (uindex_t) rii;
+ auto pt_index = (uindex_t) rii;
if (pt_index >= input_->size ())
{
PCL_ERROR ("[pcl::%s::filterDirectly] The index exceeds the size of the input. Do nothing.\n",
*cloud = *input_;
return;
}
- std::uint8_t* pt_data = reinterpret_cast<std::uint8_t*> (&(*cloud)[pt_index]);
+ auto* pt_data = reinterpret_cast<std::uint8_t*> (&(*cloud)[pt_index]);
for (const auto &field : fields)
memcpy (pt_data + field.offset, &user_filter_value_, sizeof (float));
}
pcl::for_each_type<FieldList> (pcl::detail::FieldAdder<PointT> (fields));
for (const auto ri : *removed_indices_) // ri = removed index
{
- std::size_t pt_index = (std::size_t)ri;
+ auto pt_index = (std::size_t)ri;
if (pt_index >= input_->size ())
{
PCL_ERROR ("[pcl::%s::applyFilter] The index exceeds the size of the input. Do nothing.\n",
output = *input_;
return;
}
- std::uint8_t* pt_data = reinterpret_cast<std::uint8_t*> (&output[pt_index]);
+ auto* pt_data = reinterpret_cast<std::uint8_t*> (&output[pt_index]);
for (const auto &field : fields)
memcpy (pt_data + field.offset, &user_filter_value_, sizeof (float));
}
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2020-, Open Perception, Inc.
+ *
+ * All rights reserved.
+ */
+
+#pragma once
+
+#include <pcl/common/geometry.h>
+#include <pcl/filters/farthest_point_sampling.h>
+#include <pcl/point_cloud.h>
+#include <pcl/point_types.h>
+#include <algorithm>
+#include <limits>
+#include <random>
+
+template<typename PointT> void
+pcl::FarthestPointSampling<PointT>::applyFilter (Indices &indices)
+{
+ const std::size_t size = input_->size();
+ //if requested number of point is equal to the point cloud size, copy original cloud
+ if (sample_size_ == size)
+ {
+ indices = *indices_;
+ removed_indices_->clear ();
+ return;
+ }
+ //check if requested number of points is greater than the point cloud size
+ if (sample_size_ > size)
+ {
+ PCL_THROW_EXCEPTION (BadArgumentException,
+ "Requested number of points is greater than point cloud size!");
+ }
+
+ std::vector<float> distances_to_selected_points (size, std::numeric_limits<float>::max ());
+
+ //set random seed
+ std::mt19937 random_gen(seed_);
+ std::uniform_int_distribution<index_t> dis(0, size -1);
+
+ //pick the first point at random
+ index_t max_index = dis(random_gen);
+ distances_to_selected_points[max_index] = -1.0;
+ indices.push_back(max_index);
+
+ for (std::size_t j = 1; j < sample_size_; ++j)
+ {
+ index_t next_max_index = 0;
+
+ const PointT& max_index_point = (*input_)[max_index];
+ //recompute distances
+ for (std::size_t i = 0; i < size; ++i)
+ {
+ if (distances_to_selected_points[i] == -1.0)
+ continue;
+ distances_to_selected_points[i] = std::min(distances_to_selected_points[i], geometry::distance((*input_)[i], max_index_point));
+ if (distances_to_selected_points[i] > distances_to_selected_points[next_max_index])
+ next_max_index = i;
+ }
+
+ //select farthest point based on previously calculated distances
+ //since distance is set to -1 for all selected elements,previously selected
+ //elements are guaranteed to not be selected
+ max_index = next_max_index;
+ distances_to_selected_points[max_index] = -1.0;
+ indices.push_back(max_index);
+ //set distance to -1 to ignore during max element search
+ }
+
+ if (extract_removed_indices_)
+ {
+ for (std::size_t k = 0; k < distances_to_selected_points.size(); ++k)
+ {
+ if (distances_to_selected_points[k] != -1.0)
+ (*removed_indices_).push_back(k);
+ }
+ }
+}
+
+#define PCL_INSTANTIATE_FarthestPointSampling(T) template class PCL_EXPORTS pcl::FarthestPointSampling<T>;
if (early_division_)
{
- for (std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> >::iterator d = data.begin (); d != data.end (); ++d)
+ for (auto d = data.begin (); d != data.end (); ++d)
*d /= ((*d)[0] != 0) ? (*d)[1] : 1;
for (std::size_t x = 0; x < input_->width; x++)
#endif
for (long int i = 0; i < static_cast<long int> (small_width * small_height); ++i)
{
- std::size_t small_x = static_cast<std::size_t> (i % small_width);
- std::size_t small_y = static_cast<std::size_t> (i / small_width);
- std::size_t start_x = static_cast<std::size_t>(
+ auto small_x = static_cast<std::size_t> (i % small_width);
+ auto small_y = static_cast<std::size_t> (i / small_width);
+ auto start_x = static_cast<std::size_t>(
std::max ((static_cast<float> (small_x) - static_cast<float> (padding_xy) - 0.5f) * sigma_s_ + 1, 0.f));
- std::size_t end_x = static_cast<std::size_t>(
+ auto end_x = static_cast<std::size_t>(
std::max ((static_cast<float> (small_x) - static_cast<float> (padding_xy) + 0.5f) * sigma_s_ + 1, 0.f));
- std::size_t start_y = static_cast<std::size_t>(
+ auto start_y = static_cast<std::size_t>(
std::max ((static_cast<float> (small_y) - static_cast<float> (padding_xy) - 0.5f) * sigma_s_ + 1, 0.f));
- std::size_t end_y = static_cast<std::size_t>(
+ auto end_y = static_cast<std::size_t>(
std::max ((static_cast<float> (small_y) - static_cast<float> (padding_xy) + 0.5f) * sigma_s_ + 1, 0.f));
for (std::size_t x = start_x; x < end_x && x < input_->width; ++x)
{
#endif
for(long int i = 0; i < static_cast<long int> ((small_width - 2)*(small_height - 2)); ++i)
{
- std::size_t x = static_cast<std::size_t> (i % (small_width - 2) + 1);
- std::size_t y = static_cast<std::size_t> (i / (small_width - 2) + 1);
+ auto x = static_cast<std::size_t> (i % (small_width - 2) + 1);
+ auto y = static_cast<std::size_t> (i / (small_width - 2) + 1);
const long int off = offset[dim];
Eigen::Vector2f* d_ptr = &(current_data->operator() (x,y,1));
Eigen::Vector2f* b_ptr = &(current_buffer->operator() (x,y,1));
if (early_division_)
{
- for (std::vector<Eigen::Vector2f, Eigen::aligned_allocator<Eigen::Vector2f> >::iterator d = data.begin (); d != data.end (); ++d)
+ for (auto d = data.begin (); d != data.end (); ++d)
*d /= ((*d)[0] != 0) ? (*d)[1] : 1;
#pragma omp parallel for \
num_threads(threads_)
for (long int i = 0; i < static_cast<long int> (input_->size ()); ++i)
{
- std::size_t x = static_cast<std::size_t> (i % input_->width);
- std::size_t y = static_cast<std::size_t> (i / input_->width);
+ auto x = static_cast<std::size_t> (i % input_->width);
+ auto y = static_cast<std::size_t> (i / input_->width);
const float z = output (x,y).z - base_min;
const Eigen::Vector2f D = data.trilinear_interpolation (static_cast<float> (x) / sigma_s_ + padding_xy,
static_cast<float> (y) / sigma_s_ + padding_xy,
num_threads(threads_)
for (long i = 0; i < static_cast<long int> (input_->size ()); ++i)
{
- std::size_t x = static_cast<std::size_t> (i % input_->width);
- std::size_t y = static_cast<std::size_t> (i / input_->width);
+ auto x = static_cast<std::size_t> (i % input_->width);
+ auto y = static_cast<std::size_t> (i / input_->width);
const float z = output (x,y).z - base_min;
const Eigen::Vector2f D = data.trilinear_interpolation (static_cast<float> (x) / sigma_s_ + padding_xy,
static_cast<float> (y) / sigma_s_ + padding_xy,
template <typename PointT> void
pcl::FrustumCulling<PointT>::applyFilter (Indices &indices)
{
+ bool is_far_plane_infinite = (fp_dist_ == std::numeric_limits<float>::max());
+ if(is_far_plane_infinite) {
+ fp_dist_ = np_dist_ + 1.0f;
+ }
+
Eigen::Vector4f pl_n; // near plane
Eigen::Vector4f pl_f; // far plane
Eigen::Vector4f pl_t; // top plane
Eigen::Vector3f T = camera_pose_.block<3, 1> (0, 3); // The (X, Y, Z) position of the camera w.r.t origin
- float vfov_rad = float (vfov_ * M_PI / 180); // degrees to radians
- float hfov_rad = float (hfov_ * M_PI / 180); // degrees to radians
+ float fov_lower_bound_rad = float (fov_lower_bound_ * M_PI / 180); // degrees to radians
+ float fov_upper_bound_rad = float (fov_upper_bound_ * M_PI / 180); // degrees to radians
+ float fov_left_bound_rad = float (fov_left_bound_ * M_PI / 180); // degrees to radians
+ float fov_right_bound_rad = float (fov_right_bound_ * M_PI / 180); // degrees to radians
+
+ float roi_xmax = roi_x_ + (roi_w_ / 2); // roi max x
+ float roi_xmin = roi_x_ - (roi_w_ / 2); // roi min x
+ float roi_ymax = roi_y_ + (roi_h_ / 2); // roi max y
+ float roi_ymin = roi_y_ - (roi_h_ / 2); // roi min y
- float np_h = float (2 * tan (vfov_rad / 2) * np_dist_); // near plane height
- float np_w = float (2 * tan (hfov_rad / 2) * np_dist_); // near plane width
+ float np_h_u = float(2 * std::tan(fov_lower_bound_rad) * np_dist_ * (roi_ymin - 0.5)); // near plane upper height
+ float np_h_d = float(2 * std::tan(fov_upper_bound_rad) * np_dist_ * (roi_ymax - 0.5)); // near plane lower height
+ float np_w_l = float(2 * std::tan(fov_left_bound_rad) * np_dist_ * (roi_xmin - 0.5)); // near plane left width
+ float np_w_r = float(2 * std::tan(fov_right_bound_rad) * np_dist_ * (roi_xmax - 0.5)); // near plane right width
- float fp_h = float (2 * tan (vfov_rad / 2) * fp_dist_); // far plane height
- float fp_w = float (2 * tan (hfov_rad / 2) * fp_dist_); // far plane width
+ float fp_h_u = float(2 * std::tan(fov_lower_bound_rad) * fp_dist_ * (roi_ymin - 0.5)); // far plane upper height
+ float fp_h_d = float(2 * std::tan(fov_upper_bound_rad) * fp_dist_ * (roi_ymax - 0.5)); // far plane lower height
+ float fp_w_l = float(2 * std::tan(fov_left_bound_rad) * fp_dist_ * (roi_xmin - 0.5)); // far plane left width
+ float fp_w_r = float(2 * std::tan(fov_right_bound_rad) * fp_dist_ * (roi_xmax - 0.5)); // far plane right width
Eigen::Vector3f fp_c (T + view * fp_dist_); // far plane center
- Eigen::Vector3f fp_tl (fp_c + (up * fp_h / 2) - (right * fp_w / 2)); // Top left corner of the far plane
- Eigen::Vector3f fp_tr (fp_c + (up * fp_h / 2) + (right * fp_w / 2)); // Top right corner of the far plane
- Eigen::Vector3f fp_bl (fp_c - (up * fp_h / 2) - (right * fp_w / 2)); // Bottom left corner of the far plane
- Eigen::Vector3f fp_br (fp_c - (up * fp_h / 2) + (right * fp_w / 2)); // Bottom right corner of the far plane
+ Eigen::Vector3f fp_tl (fp_c + (up * fp_h_u) - (right * fp_w_l)); // Top left corner of the far plane
+ Eigen::Vector3f fp_tr (fp_c + (up * fp_h_u) + (right * fp_w_r)); // Top right corner of the far plane
+ Eigen::Vector3f fp_bl (fp_c - (up * fp_h_d) - (right * fp_w_l)); // Bottom left corner of the far plane
+ Eigen::Vector3f fp_br (fp_c - (up * fp_h_d) + (right * fp_w_r)); // Bottom right corner of the far plane
Eigen::Vector3f np_c (T + view * np_dist_); // near plane center
- //Eigen::Vector3f np_tl = np_c + (up * np_h/2) - (right * np_w/2); // Top left corner of the near plane
- Eigen::Vector3f np_tr (np_c + (up * np_h / 2) + (right * np_w / 2)); // Top right corner of the near plane
- Eigen::Vector3f np_bl (np_c - (up * np_h / 2) - (right * np_w / 2)); // Bottom left corner of the near plane
- Eigen::Vector3f np_br (np_c - (up * np_h / 2) + (right * np_w / 2)); // Bottom right corner of the near plane
+ //Eigen::Vector3f np_tl = np_c + (up * np_h_u) - (right * np_w_l); // Top left corner of the near plane
+ Eigen::Vector3f np_tr (np_c + (up * np_h_u) + (right * np_w_r)); // Top right corner of the near plane
+ Eigen::Vector3f np_bl (np_c - (up * np_h_d) - (right * np_w_l)); // Bottom left corner of the near plane
+ Eigen::Vector3f np_br (np_c - (up * np_h_d) + (right * np_w_r)); // Bottom right corner of the near plane
pl_f.head<3> () = (fp_bl - fp_br).cross (fp_tr - fp_br); // Far plane equation - cross product of the
pl_f (3) = -fp_c.dot (pl_f.head<3> ()); // perpendicular edges of the far plane
+ if(is_far_plane_infinite) {
+ pl_f.setZero();
+ fp_dist_ = std::numeric_limits<float>::max();
+ }
+
pl_n.head<3> () = (np_tr - np_br).cross (np_bl - np_br); // Near plane equation - cross product of the
- pl_n (3) = -np_c.dot (pl_n.head<3> ()); // perpendicular edges of the far plane
+ pl_n (3) = -np_c.dot (pl_n.head<3> ()); // perpendicular edges of the near plane
Eigen::Vector3f a (fp_bl - T); // Vector connecting the camera and far plane bottom left
Eigen::Vector3f b (fp_br - T); // Vector connecting the camera and far plane bottom right
using SACModelFromNormals = SampleConsensusModelFromNormals<PointT, pcl::Normal>;
// Returns NULL if cast isn't possible
- SACModelFromNormals *model_from_normals = dynamic_cast<SACModelFromNormals *> (& (*model_));
+ auto *model_from_normals = dynamic_cast<SACModelFromNormals *> (& (*model_));
if (model_from_normals)
{
template<typename PointT, typename NormalT> unsigned int
pcl::NormalSpaceSampling<PointT, NormalT>::findBin (const float *normal)
{
- const unsigned ix = static_cast<unsigned> (std::round (0.5f * (binsx_ - 1.f) * (normal[0] + 1.f)));
- const unsigned iy = static_cast<unsigned> (std::round (0.5f * (binsy_ - 1.f) * (normal[1] + 1.f)));
- const unsigned iz = static_cast<unsigned> (std::round (0.5f * (binsz_ - 1.f) * (normal[2] + 1.f)));
+ const auto ix = static_cast<unsigned> (std::round (0.5f * (binsx_ - 1.f) * (normal[0] + 1.f)));
+ const auto iy = static_cast<unsigned> (std::round (0.5f * (binsy_ - 1.f) * (normal[1] + 1.f)));
+ const auto iz = static_cast<unsigned> (std::round (0.5f * (binsz_ - 1.f) * (normal[2] + 1.f)));
return ix * (binsy_*binsz_) + iy * binsz_ + iz;
}
random_access[i].resize (normals_hg[i].size ());
std::size_t j = 0;
- for (std::list<int>::iterator itr = normals_hg[i].begin (); itr != normals_hg[i].end (); ++itr, ++j)
+ for (auto itr = normals_hg[i].begin (); itr != normals_hg[i].end (); ++itr, ++j)
random_access[i][j] = itr;
}
std::vector<std::size_t> start_index (normals_hg.size ());
// Iterating through every bin and picking one point at random, until the required number of points are sampled.
for (std::size_t j = 0; j < normals_hg.size (); j++)
{
- unsigned int M = static_cast<unsigned int> (normals_hg[j].size ());
+ auto M = static_cast<unsigned int> (normals_hg[j].size ());
if (M == 0 || bin_empty_flag.test (j)) // bin_empty_flag(i) is set if all points in that bin are sampled..
continue;
removed_indices_->clear ();
return;
}
+ if (fields[distance_idx].datatype != pcl::PCLPointField::PointFieldTypes::FLOAT32)
+ {
+ PCL_ERROR ("[pcl::%s::applyFilter] PassThrough currently only works with float32 fields. To filter fields of other types see ConditionalRemoval or FunctorFilter/FunctionFilter.\n", getClassName ().c_str ());
+ indices.clear ();
+ removed_indices_->clear ();
+ return;
+ }
+ if (filter_field_name_ == "rgb")
+ PCL_WARN ("[pcl::%s::applyFilter] You told PassThrough to operate on the 'rgb' field. This will likely not do what you expect. Consider using ConditionalRemoval or FunctorFilter/FunctionFilter.\n", getClassName ().c_str ());
+ const auto field_offset = fields[distance_idx].offset;
// Filter for non-finite entries and the specified field limits
for (const auto ii : *indices_) // ii = input index
}
// Get the field's value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&(*input_)[ii]);
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&(*input_)[ii]);
float field_value = 0;
- memcpy (&field_value, pt_data + fields[distance_idx].offset, sizeof (float));
+ memcpy (&field_value, pt_data + field_offset, sizeof (float));
// Remove NAN/INF/-INF values. We expect passthrough to output clean valid data.
if (!std::isfinite (field_value))
{
}
-template<typename PointT>
-pcl::PlaneClipper3D<PointT>::~PlaneClipper3D () noexcept
-{
-}
-
template<typename PointT> void
pcl::PlaneClipper3D<PointT>::setPlaneParameters (const Eigen::Vector4f& plane_params)
{
#ifndef PCL_FILTERS_IMPL_PYRAMID_HPP
#define PCL_FILTERS_IMPL_PYRAMID_HPP
+#include <pcl/common/distances.h>
+#include <pcl/filters/pyramid.h>
+#include <pcl/console/print.h>
+#include <pcl/point_types.h>
namespace pcl
{
-
namespace filters
{
-
template <typename PointT> bool
Pyramid<PointT>::initCompute ()
{
}
}
-
template <> void
-Pyramid<pcl::PointXYZRGB>::compute (std::vector<Pyramid<pcl::PointXYZRGB>::PointCloudPtr> &output)
-{
- std::cout << "PointXYZRGB" << std::endl;
- if (!initCompute ())
- {
- PCL_ERROR ("[pcl::%s::compute] initCompute failed!\n", getClassName ().c_str ());
- return;
- }
-
- int kernel_rows = static_cast<int> (kernel_.rows ());
- int kernel_cols = static_cast<int> (kernel_.cols ());
- int kernel_center_x = kernel_cols / 2;
- int kernel_center_y = kernel_rows / 2;
-
- output.resize (levels_ + 1);
- output[0].reset (new pcl::PointCloud<pcl::PointXYZRGB>);
- *(output[0]) = *input_;
-
- if (input_->is_dense)
- {
- for (int l = 1; l <= levels_; ++l)
- {
- output[l].reset (new pcl::PointCloud<pcl::PointXYZRGB> (output[l-1]->width/2, output[l-1]->height/2));
- const PointCloud<pcl::PointXYZRGB> &previous = *output[l-1];
- PointCloud<pcl::PointXYZRGB> &next = *output[l];
-#pragma omp parallel for \
- default(none) \
- shared(next) \
- num_threads(threads_)
- for(int i=0; i < next.height; ++i) // rows
- {
- for(int j=0; j < next.width; ++j) // columns
- {
- float r = 0, g = 0, b = 0;
- for(int m=0; m < kernel_rows; ++m) // kernel rows
- {
- int mm = kernel_rows - 1 - m; // row index of flipped kernel
- for(int n=0; n < kernel_cols; ++n) // kernel columns
- {
- int nn = kernel_cols - 1 - n; // column index of flipped kernel
- // index of input signal, used for checking boundary
- int ii = 2*i + (m - kernel_center_y);
- int jj = 2*j + (n - kernel_center_x);
-
- // ignore input samples which are out of bound
- if (ii < 0) ii = 0;
- if (ii >= previous.height) ii = previous.height - 1;
- if (jj < 0) jj = 0;
- if (jj >= previous.width) jj = previous.width - 1;
- next.at (j,i).x += previous.at (jj,ii).x * kernel_ (mm,nn);
- next.at (j,i).y += previous.at (jj,ii).y * kernel_ (mm,nn);
- next.at (j,i).z += previous.at (jj,ii).z * kernel_ (mm,nn);
- b += previous.at (jj,ii).b * kernel_ (mm,nn);
- g += previous.at (jj,ii).g * kernel_ (mm,nn);
- r += previous.at (jj,ii).r * kernel_ (mm,nn);
- }
- }
- next.at (j,i).b = static_cast<std::uint8_t> (b);
- next.at (j,i).g = static_cast<std::uint8_t> (g);
- next.at (j,i).r = static_cast<std::uint8_t> (r);
- }
- }
- }
- }
- else
- {
- for (int l = 1; l <= levels_; ++l)
- {
- output[l].reset (new pcl::PointCloud<pcl::PointXYZRGB> (output[l-1]->width/2, output[l-1]->height/2));
- const PointCloud<pcl::PointXYZRGB> &previous = *output[l-1];
- PointCloud<pcl::PointXYZRGB> &next = *output[l];
-#pragma omp parallel for \
- default(none) \
- shared(next) \
- num_threads(threads_)
- for(int i=0; i < next.height; ++i)
- {
- for(int j=0; j < next.width; ++j)
- {
- float weight = 0;
- float r = 0, g = 0, b = 0;
- for(int m=0; m < kernel_rows; ++m)
- {
- int mm = kernel_rows - 1 - m;
- for(int n=0; n < kernel_cols; ++n)
- {
- int nn = kernel_cols - 1 - n;
- int ii = 2*i + (m - kernel_center_y);
- int jj = 2*j + (n - kernel_center_x);
- if (ii < 0) ii = 0;
- if (ii >= previous.height) ii = previous.height - 1;
- if (jj < 0) jj = 0;
- if (jj >= previous.width) jj = previous.width - 1;
- if (!isFinite (previous.at (jj,ii)))
- continue;
- if (pcl::squaredEuclideanDistance (previous.at (2*j,2*i), previous.at (jj,ii)) < threshold_)
- {
- next.at (j,i).x += previous.at (jj,ii).x * kernel_ (mm,nn);
- next.at (j,i).y += previous.at (jj,ii).y * kernel_ (mm,nn);
- next.at (j,i).z += previous.at (jj,ii).z * kernel_ (mm,nn);
- b += previous.at (jj,ii).b * kernel_ (mm,nn);
- g += previous.at (jj,ii).g * kernel_ (mm,nn);
- r += previous.at (jj,ii).r * kernel_ (mm,nn);
- weight+= kernel_ (mm,nn);
- }
- }
- }
- if (weight == 0)
- nullify (next.at (j,i));
- else
- {
- weight = 1.f/weight;
- r*= weight; g*= weight; b*= weight;
- next.at (j,i).x*= weight; next.at (j,i).y*= weight; next.at (j,i).z*= weight;
- next.at (j,i).b = static_cast<std::uint8_t> (b);
- next.at (j,i).g = static_cast<std::uint8_t> (g);
- next.at (j,i).r = static_cast<std::uint8_t> (r);
- }
- }
- }
- }
- }
-}
+Pyramid<pcl::PointXYZRGB>::compute (std::vector<Pyramid<pcl::PointXYZRGB>::PointCloudPtr> &output);
template <> void
-Pyramid<pcl::PointXYZRGBA>::compute (std::vector<Pyramid<pcl::PointXYZRGBA>::PointCloudPtr> &output)
-{
- std::cout << "PointXYZRGBA" << std::endl;
- if (!initCompute ())
- {
- PCL_ERROR ("[pcl::%s::compute] initCompute failed!\n", getClassName ().c_str ());
- return;
- }
-
- int kernel_rows = static_cast<int> (kernel_.rows ());
- int kernel_cols = static_cast<int> (kernel_.cols ());
- int kernel_center_x = kernel_cols / 2;
- int kernel_center_y = kernel_rows / 2;
-
- output.resize (levels_ + 1);
- output[0].reset (new pcl::PointCloud<pcl::PointXYZRGBA>);
- *(output[0]) = *input_;
-
- if (input_->is_dense)
- {
- for (int l = 1; l <= levels_; ++l)
- {
- output[l].reset (new pcl::PointCloud<pcl::PointXYZRGBA> (output[l-1]->width/2, output[l-1]->height/2));
- const PointCloud<pcl::PointXYZRGBA> &previous = *output[l-1];
- PointCloud<pcl::PointXYZRGBA> &next = *output[l];
-#pragma omp parallel for \
- default(none) \
- shared(next) \
- num_threads(threads_)
- for(int i=0; i < next.height; ++i) // rows
- {
- for(int j=0; j < next.width; ++j) // columns
- {
- float r = 0, g = 0, b = 0, a = 0;
- for(int m=0; m < kernel_rows; ++m) // kernel rows
- {
- int mm = kernel_rows - 1 - m; // row index of flipped kernel
- for(int n=0; n < kernel_cols; ++n) // kernel columns
- {
- int nn = kernel_cols - 1 - n; // column index of flipped kernel
- // index of input signal, used for checking boundary
- int ii = 2*i + (m - kernel_center_y);
- int jj = 2*j + (n - kernel_center_x);
-
- // ignore input samples which are out of bound
- if (ii < 0) ii = 0;
- if (ii >= previous.height) ii = previous.height - 1;
- if (jj < 0) jj = 0;
- if (jj >= previous.width) jj = previous.width - 1;
- next.at (j,i).x += previous.at (jj,ii).x * kernel_ (mm,nn);
- next.at (j,i).y += previous.at (jj,ii).y * kernel_ (mm,nn);
- next.at (j,i).z += previous.at (jj,ii).z * kernel_ (mm,nn);
- b += previous.at (jj,ii).b * kernel_ (mm,nn);
- g += previous.at (jj,ii).g * kernel_ (mm,nn);
- r += previous.at (jj,ii).r * kernel_ (mm,nn);
- a += previous.at (jj,ii).a * kernel_ (mm,nn);
- }
- }
- next.at (j,i).b = static_cast<std::uint8_t> (b);
- next.at (j,i).g = static_cast<std::uint8_t> (g);
- next.at (j,i).r = static_cast<std::uint8_t> (r);
- next.at (j,i).a = static_cast<std::uint8_t> (a);
- }
- }
- }
- }
- else
- {
- for (int l = 1; l <= levels_; ++l)
- {
- output[l].reset (new pcl::PointCloud<pcl::PointXYZRGBA> (output[l-1]->width/2, output[l-1]->height/2));
- const PointCloud<pcl::PointXYZRGBA> &previous = *output[l-1];
- PointCloud<pcl::PointXYZRGBA> &next = *output[l];
-#pragma omp parallel for \
- default(none) \
- shared(next) \
- num_threads(threads_)
- for(int i=0; i < next.height; ++i)
- {
- for(int j=0; j < next.width; ++j)
- {
- float weight = 0;
- float r = 0, g = 0, b = 0, a = 0;
- for(int m=0; m < kernel_rows; ++m)
- {
- int mm = kernel_rows - 1 - m;
- for(int n=0; n < kernel_cols; ++n)
- {
- int nn = kernel_cols - 1 - n;
- int ii = 2*i + (m - kernel_center_y);
- int jj = 2*j + (n - kernel_center_x);
- if (ii < 0) ii = 0;
- if (ii >= previous.height) ii = previous.height - 1;
- if (jj < 0) jj = 0;
- if (jj >= previous.width) jj = previous.width - 1;
- if (!isFinite (previous.at (jj,ii)))
- continue;
- if (pcl::squaredEuclideanDistance (previous.at (2*j,2*i), previous.at (jj,ii)) < threshold_)
- {
- next.at (j,i).x += previous.at (jj,ii).x * kernel_ (mm,nn);
- next.at (j,i).y += previous.at (jj,ii).y * kernel_ (mm,nn);
- next.at (j,i).z += previous.at (jj,ii).z * kernel_ (mm,nn);
- b += previous.at (jj,ii).b * kernel_ (mm,nn);
- g += previous.at (jj,ii).g * kernel_ (mm,nn);
- r += previous.at (jj,ii).r * kernel_ (mm,nn);
- a += previous.at (jj,ii).a * kernel_ (mm,nn);
- weight+= kernel_ (mm,nn);
- }
- }
- }
- if (weight == 0)
- nullify (next.at (j,i));
- else
- {
- weight = 1.f/weight;
- r*= weight; g*= weight; b*= weight; a*= weight;
- next.at (j,i).x*= weight; next.at (j,i).y*= weight; next.at (j,i).z*= weight;
- next.at (j,i).b = static_cast<std::uint8_t> (b);
- next.at (j,i).g = static_cast<std::uint8_t> (g);
- next.at (j,i).r = static_cast<std::uint8_t> (r);
- next.at (j,i).a = static_cast<std::uint8_t> (a);
- }
- }
- }
- }
- }
-}
+Pyramid<pcl::PointXYZRGBA>::compute (std::vector<Pyramid<pcl::PointXYZRGBA>::PointCloudPtr> &output);
template<> void
Pyramid<pcl::RGB>::nullify (pcl::RGB& p)
}
template <> void
-Pyramid<pcl::RGB>::compute (std::vector<Pyramid<pcl::RGB>::PointCloudPtr> &output)
-{
- std::cout << "RGB" << std::endl;
- if (!initCompute ())
- {
- PCL_ERROR ("[pcl::%s::compute] initCompute failed!\n", getClassName ().c_str ());
- return;
- }
-
- int kernel_rows = static_cast<int> (kernel_.rows ());
- int kernel_cols = static_cast<int> (kernel_.cols ());
- int kernel_center_x = kernel_cols / 2;
- int kernel_center_y = kernel_rows / 2;
-
- output.resize (levels_ + 1);
- output[0].reset (new pcl::PointCloud<pcl::RGB>);
- *(output[0]) = *input_;
-
- if (input_->is_dense)
- {
- for (int l = 1; l <= levels_; ++l)
- {
- output[l].reset (new pcl::PointCloud<pcl::RGB> (output[l-1]->width/2, output[l-1]->height/2));
- const PointCloud<pcl::RGB> &previous = *output[l-1];
- PointCloud<pcl::RGB> &next = *output[l];
-#pragma omp parallel for \
- default(none) \
- shared(next) \
- num_threads(threads_)
- for(int i=0; i < next.height; ++i)
- {
- for(int j=0; j < next.width; ++j)
- {
- float r = 0, g = 0, b = 0;
- for(int m=0; m < kernel_rows; ++m)
- {
- int mm = kernel_rows - 1 - m;
- for(int n=0; n < kernel_cols; ++n)
- {
- int nn = kernel_cols - 1 - n;
- int ii = 2*i + (m - kernel_center_y);
- int jj = 2*j + (n - kernel_center_x);
- if (ii < 0) ii = 0;
- if (ii >= previous.height) ii = previous.height - 1;
- if (jj < 0) jj = 0;
- if (jj >= previous.width) jj = previous.width - 1;
- b += previous.at (jj,ii).b * kernel_ (mm,nn);
- g += previous.at (jj,ii).g * kernel_ (mm,nn);
- r += previous.at (jj,ii).r * kernel_ (mm,nn);
- }
- }
- next.at (j,i).b = static_cast<std::uint8_t> (b);
- next.at (j,i).g = static_cast<std::uint8_t> (g);
- next.at (j,i).r = static_cast<std::uint8_t> (r);
- }
- }
- }
- }
- else
- {
- for (int l = 1; l <= levels_; ++l)
- {
- output[l].reset (new pcl::PointCloud<pcl::RGB> (output[l-1]->width/2, output[l-1]->height/2));
- const PointCloud<pcl::RGB> &previous = *output[l-1];
- PointCloud<pcl::RGB> &next = *output[l];
-#pragma omp parallel for \
- default(none) \
- shared(next) \
- num_threads(threads_)
- for(int i=0; i < next.height; ++i)
- {
- for(int j=0; j < next.width; ++j)
- {
- float weight = 0;
- float r = 0, g = 0, b = 0;
- for(int m=0; m < kernel_rows; ++m)
- {
- int mm = kernel_rows - 1 - m;
- for(int n=0; n < kernel_cols; ++n)
- {
- int nn = kernel_cols - 1 - n;
- int ii = 2*i + (m - kernel_center_y);
- int jj = 2*j + (n - kernel_center_x);
- if (ii < 0) ii = 0;
- if (ii >= previous.height) ii = previous.height - 1;
- if (jj < 0) jj = 0;
- if (jj >= previous.width) jj = previous.width - 1;
- if (!isFinite (previous.at (jj,ii)))
- continue;
- if (pcl::squaredEuclideanDistance (previous.at (2*j,2*i), previous.at (jj,ii)) < threshold_)
- {
- b += previous.at (jj,ii).b * kernel_ (mm,nn);
- g += previous.at (jj,ii).g * kernel_ (mm,nn);
- r += previous.at (jj,ii).r * kernel_ (mm,nn);
- weight+= kernel_ (mm,nn);
- }
- }
- }
- if (weight == 0)
- nullify (next.at (j,i));
- else
- {
- weight = 1.f/weight;
- r*= weight; g*= weight; b*= weight;
- next.at (j,i).b = static_cast<std::uint8_t> (b);
- next.at (j,i).g = static_cast<std::uint8_t> (g);
- next.at (j,i).r = static_cast<std::uint8_t> (r);
- }
- }
- }
- }
- }
-}
+Pyramid<pcl::RGB>::compute (std::vector<Pyramid<pcl::RGB>::PointCloudPtr> &output);
} // namespace filters
} // namespace pcl
#endif
-
template<typename PointT, typename NormalT> void
pcl::ShadowPoints<PointT, NormalT>::applyFilter (PointCloud &output)
{
- assert (input_normals_ != NULL);
+ assert (input_normals_ != nullptr);
output.resize (input_->size ());
if (extract_removed_indices_)
removed_indices_->resize (input_->size ());
template<typename PointT, typename NormalT> void
pcl::ShadowPoints<PointT, NormalT>::applyFilter (Indices &indices)
{
- assert (input_normals_ != NULL);
+ assert (input_normals_ != nullptr);
indices.resize (input_->size ());
if (extract_removed_indices_)
removed_indices_->resize (indices_->size ());
searcher_->setInputCloud (input_);
// The arrays to be used
- Indices nn_indices (mean_k_);
- std::vector<float> nn_dists (mean_k_);
+ const int searcher_k = mean_k_ + 1; // Find one more, since results include the query point.
+ Indices nn_indices (searcher_k);
+ std::vector<float> nn_dists (searcher_k);
std::vector<float> distances (indices_->size ());
indices.resize (indices_->size ());
removed_indices_->resize (indices_->size ());
}
// Perform the nearest k search
- if (searcher_->nearestKSearch ((*indices_)[iii], mean_k_ + 1, nn_indices, nn_dists) == 0)
+ if (searcher_->nearestKSearch ((*indices_)[iii], searcher_k, nn_indices, nn_dists) == 0)
{
distances[iii] = 0.0;
PCL_WARN ("[pcl::%s::applyFilter] Searching for the closest %d neighbors failed.\n", getClassName ().c_str (), mean_k_);
// Calculate the mean distance to its neighbors
double dist_sum = 0.0;
- for (int k = 1; k < mean_k_ + 1; ++k) // k = 0 is the query point
+ for (int k = 1; k < searcher_k; ++k) // k = 0 is the query point
dist_sum += sqrt (nn_dists[k]);
distances[iii] = static_cast<float> (dist_sum / mean_k_);
valid_distances++;
continue;
}
+ // Compute the voxel center
+ Eigen::Vector4f voxel_center = (ijk.cast<float>() + Eigen::Vector4f::Constant(0.5)) * search_radius_;
+ voxel_center[3] = 0;
// Check to see if this point is closer to the leaf center than the previous one we saved
- float diff_cur = ((*input_)[(*indices_)[cp]].getVector4fMap () - ijk.cast<float> ()).squaredNorm ();
- float diff_prev = ((*input_)[leaf.idx].getVector4fMap () - ijk.cast<float> ()).squaredNorm ();
+ float diff_cur = ((*input_)[(*indices_)[cp]].getVector4fMap () - voxel_center).squaredNorm ();
+ float diff_prev = ((*input_)[leaf.idx].getVector4fMap () - voxel_center).squaredNorm ();
// If current point is closer, copy its index instead
if (diff_cur < diff_prev)
#ifndef PCL_FILTERS_IMPL_VOXEL_GRID_H_
#define PCL_FILTERS_IMPL_VOXEL_GRID_H_
+#include <limits>
+
#include <pcl/common/centroid.h>
#include <pcl/common/common.h>
#include <pcl/common/io.h>
Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt, bool limit_negative)
{
Eigen::Array4f min_p, max_p;
- min_p.setConstant (FLT_MAX);
- max_p.setConstant (-FLT_MAX);
+ min_p.setConstant (std::numeric_limits<float>::max());
+ max_p.setConstant (std::numeric_limits<float>::lowest());
// Get the fields list and the distance field index
std::vector<pcl::PCLPointField> fields;
int distance_idx = pcl::getFieldIndex<PointT> (distance_field_name, fields);
+ if (distance_idx < 0 || fields.empty()) {
+ PCL_ERROR ("[pcl::getMinMax3D] Could not find field with name '%s'!\n", distance_field_name.c_str());
+ return;
+ }
+ const auto field_offset = fields[distance_idx].offset;
float distance_value;
// If dense, no need to check for NaNs
for (const auto& point: *cloud)
{
// Get the distance value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
- memcpy (&distance_value, pt_data + fields[distance_idx].offset, sizeof (float));
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
+ memcpy (&distance_value, pt_data + field_offset, sizeof (float));
if (limit_negative)
{
for (const auto& point: *cloud)
{
// Get the distance value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
- memcpy (&distance_value, pt_data + fields[distance_idx].offset, sizeof (float));
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
+ memcpy (&distance_value, pt_data + field_offset, sizeof (float));
if (limit_negative)
{
Eigen::Vector4f &min_pt, Eigen::Vector4f &max_pt, bool limit_negative)
{
Eigen::Array4f min_p, max_p;
- min_p.setConstant (FLT_MAX);
- max_p.setConstant (-FLT_MAX);
+ min_p.setConstant (std::numeric_limits<float>::max());
+ max_p.setConstant (std::numeric_limits<float>::lowest());
// Get the fields list and the distance field index
std::vector<pcl::PCLPointField> fields;
int distance_idx = pcl::getFieldIndex<PointT> (distance_field_name, fields);
+ if (distance_idx < 0 || fields.empty()) {
+ PCL_ERROR ("[pcl::getMinMax3D] Could not find field with name '%s'!\n", distance_field_name.c_str());
+ return;
+ }
+ const auto field_offset = fields[distance_idx].offset;
float distance_value;
// If dense, no need to check for NaNs
for (const auto &index : indices)
{
// Get the distance value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&(*cloud)[index]);
- memcpy (&distance_value, pt_data + fields[distance_idx].offset, sizeof (float));
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&(*cloud)[index]);
+ memcpy (&distance_value, pt_data + field_offset, sizeof (float));
if (limit_negative)
{
for (const auto &index : indices)
{
// Get the distance value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&(*cloud)[index]);
- memcpy (&distance_value, pt_data + fields[distance_idx].offset, sizeof (float));
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&(*cloud)[index]);
+ memcpy (&distance_value, pt_data + field_offset, sizeof (float));
if (limit_negative)
{
// Get the distance field index
std::vector<pcl::PCLPointField> fields;
int distance_idx = pcl::getFieldIndex<PointT> (filter_field_name_, fields);
- if (distance_idx == -1)
- PCL_WARN ("[pcl::%s::applyFilter] Invalid filter field name. Index is %d.\n", getClassName ().c_str (), distance_idx);
+ if (distance_idx == -1) {
+ PCL_ERROR ("[pcl::%s::applyFilter] Invalid filter field name (%s).\n", getClassName ().c_str (), filter_field_name_.c_str());
+ return;
+ }
+ const auto field_offset = fields[distance_idx].offset;
// First pass: go over all points and insert them into the index_vector vector
// with calculated idx. Points with the same idx value will contribute to the
continue;
// Get the distance value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&(*input_)[index]);
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&(*input_)[index]);
float distance_value = 0;
- memcpy (&distance_value, pt_data + fields[distance_idx].offset, sizeof (float));
+ memcpy (&distance_value, pt_data + field_offset, sizeof (float));
if (filter_limit_negative_)
{
continue;
// Get the distance value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&point);
float distance_value = 0;
memcpy (&distance_value, pt_data + fields[distance_idx].offset, sizeof (float));
// Eigen values less than a threshold of max eigen value are inflated to a set fraction of the max eigen value.
double min_covar_eigvalue;
- for (typename std::map<std::size_t, Leaf>::iterator it = leaves_.begin (); it != leaves_.end (); ++it)
+ for (auto it = leaves_.begin (); it != leaves_.end (); ++it)
{
// Normalize the centroid
[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)
+ for (auto it = leaves_.begin (); it != leaves_.end (); ++it)
{
Leaf& leaf = it->second;
/** \brief sets the models coefficients */
inline void
- setModelCoefficients (const pcl::ModelCoefficients model_coefficients)
+ setModelCoefficients (const pcl::ModelCoefficients& model_coefficients)
{
model_coefficients_.resize (model_coefficients.values.size ());
for (std::size_t i = 0; i < model_coefficients.values.size (); i++)
#pragma once
-#include <cfloat> // for FLT_MIN, FLT_MAX
+#include <limits>
#include <pcl/pcl_macros.h>
#include <pcl/filters/filter_indices.h>
* // The indices_xz array indexes all points of cloud_in that have x between 0.0 and 1000.0 and z larger than 10.0 or smaller than -10.0
* ptfilter.setIndices (indices_xz);
* ptfilter.setFilterFieldName ("intensity");
- * ptfilter.setFilterLimits (FLT_MIN, 0.5);
+ * ptfilter.setFilterLimits (std::numeric_limits<float>::lowest(), 0.5);
* ptfilter.setNegative (false);
* ptfilter.filter (*cloud_out);
* // The resulting cloud_out contains all points of cloud_in that are finite and have:
PassThrough (bool extract_removed_indices = false) :
FilterIndices<PointT> (extract_removed_indices),
filter_field_name_ (""),
- filter_limit_min_ (FLT_MIN),
- filter_limit_max_ (FLT_MAX)
+ filter_limit_min_ (std::numeric_limits<float>::lowest()),
+ filter_limit_max_ (std::numeric_limits<float>::max())
{
filter_name_ = "PassThrough";
}
/** \brief Set the numerical limits for the field for filtering data.
* \details In conjunction with setFilterFieldName(), points having values outside this interval for this field will be discarded.
- * \param[in] limit_min The minimum allowed field value (default = FLT_MIN).
- * \param[in] limit_max The maximum allowed field value (default = FLT_MAX).
+ * \param[in] limit_min The minimum allowed field value (default = std::numeric_limits<float>::lowest()).
+ * \param[in] limit_max The maximum allowed field value (default = std::numeric_limits<float>::max()).
*/
inline void
setFilterLimits (const float &limit_min, const float &limit_max)
}
/** \brief Get the numerical limits for the field for filtering data.
- * \param[out] limit_min The minimum allowed field value (default = FLT_MIN).
- * \param[out] limit_max The maximum allowed field value (default = FLT_MAX).
+ * \param[out] limit_min The minimum allowed field value (default = std::numeric_limits<float>::lowest()).
+ * \param[out] limit_max The maximum allowed field value (default = std::numeric_limits<float>::max()).
*/
inline void
getFilterLimits (float &limit_min, float &limit_max) const
limit_max = filter_limit_max_;
}
- /** \brief Set to true if we want to return the data outside the interval specified by setFilterLimits (min, max)
- * Default: false.
- * \warning This method will be removed in the future. Use setNegative() instead.
- * \param[in] limit_negative return data inside the interval (false) or outside (true)
- */
- PCL_DEPRECATED(1, 13, "use inherited FilterIndices::setNegative() instead")
- inline void
- setFilterLimitsNegative (const bool limit_negative)
- {
- negative_ = limit_negative;
- }
-
- /** \brief Get whether the data outside the interval (min/max) is to be returned (true) or inside (false).
- * \warning This method will be removed in the future. Use getNegative() instead.
- * \param[out] limit_negative true if data \b outside the interval [min; max] is to be returned, false otherwise
- */
- PCL_DEPRECATED(1, 13, "use inherited FilterIndices::getNegative() instead")
- inline void
- getFilterLimitsNegative (bool &limit_negative) const
- {
- limit_negative = negative_;
- }
-
/** \brief Get whether the data outside the interval (min/max) is to be returned (true) or inside (false).
* \warning This method will be removed in the future. Use getNegative() instead.
* \return true if data \b outside the interval [min; max] is to be returned, false otherwise
/** \brief The name of the field that will be used for filtering. */
std::string filter_field_name_;
- /** \brief The minimum allowed field value (default = FLT_MIN). */
+ /** \brief The minimum allowed field value (default = std::numeric_limits<float>::lowest()). */
float filter_limit_min_;
- /** \brief The maximum allowed field value (default = FLT_MIN). */
+ /** \brief The maximum allowed field value (default = std::numeric_limits<float>::max()). */
float filter_limit_max_;
};
public:
/** \brief Constructor. */
PassThrough (bool extract_removed_indices = false) :
- FilterIndices<pcl::PCLPointCloud2>::FilterIndices (extract_removed_indices),
- filter_field_name_ (""), filter_limit_min_ (-FLT_MAX), filter_limit_max_ (FLT_MAX)
+ FilterIndices<pcl::PCLPointCloud2>::FilterIndices (extract_removed_indices), filter_field_name_("")
+ , filter_limit_min_(std::numeric_limits<float>::lowest())
+ , filter_limit_max_(std::numeric_limits<float>::max())
{
filter_name_ = "PassThrough";
}
filter_limit_max_ = limit_max;
}
- /** \brief Get the field filter limits (min/max) set by the user. The default values are -FLT_MAX, FLT_MAX.
+ /** \brief Get the field filter limits (min/max) set by the user. The default values are
+ * std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max().
* \param[out] limit_min the minimum allowed field value
* \param[out] limit_max the maximum allowed field value
*/
using Ptr = shared_ptr< PlaneClipper3D<PointT> >;
using ConstPtr = shared_ptr< const PlaneClipper3D<PointT> >;
+ PCL_MAKE_ALIGNED_OPERATOR_NEW;
+
/**
* @author Suat Gedikli <gedikli@willowgarage.com>
* @brief Constructor taking the homogeneous representation of the plane as a Eigen::Vector4f
*/
PlaneClipper3D (const Eigen::Vector4f& plane_params);
- virtual ~PlaneClipper3D () noexcept;
+ virtual ~PlaneClipper3D () noexcept = default;
/**
* \brief Set new plane parameters
}
/** \brief Empty destructor */
- ~ProjectInliers () {}
+ ~ProjectInliers () override = default;
/** \brief The type of model to use (user given parameter).
* \param model the model type (check \a model_types.h)
}
/** \brief Empty destructor */
- ~ProjectInliers () {}
+ ~ProjectInliers () override = default;
/** \brief The type of model to use (user given parameter).
* \param[in] model the model type (check \a model_types.h)
* It is an iterative smoothing subsampling algorithm.
* The subsampling is fixed to 2. Two smoothing kernels may be used:
* - [1/16 1/4 3/8 1/4 1/16] slower but produces finer result;
- * - [1/4 1/2 1/2] the more conventional binomial kernel which is faster.
+ * - [1/4 1/2 1/4] the more conventional binomial kernel which is faster.
* We use a memory efficient algorithm so the convolving and subsampling are combined in a
* single step.
*
Pyramid (int levels = 4)
: levels_ (levels)
, large_ (false)
+ , name_ ("Pyramid")
, threshold_ (0.01)
, threads_ (0)
{
- name_ = "Pyramid";
}
/** \brief Provide a pointer to the input dataset
#include <pcl/filters/filter_indices.h>
#include <ctime>
-#include <climits>
+#include <limits>
namespace pcl
{
/** \brief Empty constructor. */
RandomSample (bool extract_removed_indices = false) :
FilterIndices<PointT> (extract_removed_indices),
- sample_ (UINT_MAX),
+ sample_ (std::numeric_limits<unsigned int>::max()),
seed_ (static_cast<unsigned int> (time (nullptr)))
{
filter_name_ = "RandomSample";
using ConstPtr = shared_ptr<const RandomSample<pcl::PCLPointCloud2> >;
/** \brief Empty constructor. */
- RandomSample () : sample_ (UINT_MAX), seed_ (static_cast<unsigned int> (time (nullptr)))
+ RandomSample ():
+ sample_ (std::numeric_limits<unsigned int>::max()),
+ seed_ (static_cast<unsigned int>(time(nullptr)))
{
filter_name_ = "RandomSample";
}
using Ptr = shared_ptr<UniformSampling<PointT> >;
using ConstPtr = shared_ptr<const UniformSampling<PointT> >;
+ PCL_MAKE_ALIGNED_OPERATOR_NEW;
+
/** \brief Empty constructor. */
UniformSampling (bool extract_removed_indices = false) :
Filter<PointT>(extract_removed_indices),
}
/** \brief Destructor. */
- ~UniformSampling ()
+ ~UniformSampling () override
{
leaves_.clear();
}
#pragma once
#include <pcl/filters/filter.h>
-#include <cfloat> // for FLT_MAX
+#include <limits>
namespace pcl
{
using Ptr = shared_ptr<VoxelGrid<PointT> >;
using ConstPtr = shared_ptr<const VoxelGrid<PointT> >;
+ PCL_MAKE_ALIGNED_OPERATOR_NEW;
+
/** \brief Empty constructor. */
VoxelGrid () :
leaf_size_ (Eigen::Vector4f::Zero ()),
div_b_ (Eigen::Vector4i::Zero ()),
divb_mul_ (Eigen::Vector4i::Zero ()),
filter_field_name_ (""),
- filter_limit_min_ (-FLT_MAX),
- filter_limit_max_ (FLT_MAX),
+ filter_limit_min_ (std::numeric_limits<float>::lowest()),
+ filter_limit_max_ (std::numeric_limits<float>::max()),
filter_limit_negative_ (false),
min_points_per_voxel_ (0)
{
}
/** \brief Destructor. */
- ~VoxelGrid ()
- {
- }
+ ~VoxelGrid () override = default;
/** \brief Set the voxel grid leaf size.
* \param[in] leaf_size the voxel grid leaf size
filter_limit_max_ = limit_max;
}
- /** \brief Get the field filter limits (min/max) set by the user. The default values are -FLT_MAX, FLT_MAX.
+ /** \brief Get the field filter limits (min/max) set by the user.
+ The default values are std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max().
* \param[out] limit_min the minimum allowed field value
* \param[out] limit_max the maximum allowed field value
*/
div_b_ (Eigen::Vector4i::Zero ()),
divb_mul_ (Eigen::Vector4i::Zero ()),
filter_field_name_ (""),
- filter_limit_min_ (-FLT_MAX),
- filter_limit_max_ (FLT_MAX),
+ filter_limit_min_ (std::numeric_limits<float>::lowest()),
+ filter_limit_max_ (std::numeric_limits<float>::max()),
filter_limit_negative_ (false),
min_points_per_voxel_ (0)
{
}
/** \brief Destructor. */
- ~VoxelGrid ()
- {
- }
+ ~VoxelGrid () override = default;
/** \brief Set the voxel grid leaf size.
* \param[in] leaf_size the voxel grid leaf size
filter_limit_max_ = limit_max;
}
- /** \brief Get the field filter limits (min/max) set by the user. The default values are -FLT_MAX, FLT_MAX.
+ /** \brief Get the field filter limits (min/max) set by the user.
+ * The default values are std::numeric_limits<float>::lowest(), std::numeric_limits<float>::max().
* \param[out] limit_min the minimum allowed field value
* \param[out] limit_max the maximum allowed field value
*/
}
else
{
- PCL_WARN ("%s: Covariance calculation requires at least 3 points, setting Min Point per Voxel to 3 ", this->getClassName ().c_str ());
+ PCL_WARN ("[%s::setMinPointPerVoxel] Covariance calculation requires at least 3 points, setting Min Point per Voxel to 3\n", this->getClassName ().c_str ());
min_points_per_voxel_ = 3;
}
}
voxel_centroids_ = PointCloudPtr (new PointCloud (output));
- if (searchable_ && !voxel_centroids_->empty ())
+ if (searchable_)
{
- // Initiates kdtree of the centroids of voxels containing a sufficient number of points
- kdtree_.setInputCloud (voxel_centroids_);
+ if (voxel_centroids_->empty ()) {
+ PCL_WARN ("[%s::filter] No voxels with a sufficient number of points. Grid will not be searchable. You can try reducing the min number of points required per voxel or increasing the voxel/leaf size.\n", this->getClassName ().c_str ());
+ searchable_ = false;
+ } else {
+ // Initiates kdtree of the centroids of voxels containing a sufficient number of points
+ kdtree_.setInputCloud (voxel_centroids_);
+ }
}
}
voxel_centroids_ = PointCloudPtr (new PointCloud);
applyFilter (*voxel_centroids_);
- if (searchable_ && !voxel_centroids_->empty ())
+ if (searchable_)
{
- // Initiates kdtree of the centroids of voxels containing a sufficient number of points
- kdtree_.setInputCloud (voxel_centroids_);
+ if (voxel_centroids_->empty ()) {
+ PCL_WARN ("[%s::filter] No voxels with a sufficient number of points. Grid will not be searchable. You can try reducing the min number of points required per voxel or increasing the voxel/leaf size\n", this->getClassName ().c_str ());
+ searchable_ = false;
+ } else {
+ // Initiates kdtree of the centroids of voxels containing a sufficient number of points
+ kdtree_.setInputCloud (voxel_centroids_);
+ }
}
}
inline LeafConstPtr
getLeaf (int index)
{
- typename std::map<std::size_t, Leaf>::iterator leaf_iter = leaves_.find (index);
+ auto leaf_iter = leaves_.find (index);
if (leaf_iter != leaves_.end ())
{
LeafConstPtr ret (&(leaf_iter->second));
int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
// Find leaf associated with index
- typename std::map<std::size_t, Leaf>::iterator leaf_iter = leaves_.find (idx);
+ auto leaf_iter = leaves_.find (idx);
if (leaf_iter != leaves_.end ())
{
// If such a leaf exists return the pointer to the leaf structure
int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
// Find leaf associated with index
- typename std::map<std::size_t, Leaf>::iterator leaf_iter = leaves_.find (idx);
+ auto leaf_iter = leaves_.find (idx);
if (leaf_iter != leaves_.end ())
{
// If such a leaf exists return the pointer to the leaf structure
}
- /** \brief Get the voxels surrounding point p designated by #relative_coordinates.
+ /** \brief Get the voxels surrounding point p designated by \p relative_coordinates.
* \note Only voxels containing a sufficient number of points are used.
* \param[in] relative_coordinates 3xN matrix that represents relative coordinates of N neighboring voxels with respect to the center voxel
* \param[in] reference_point the point to get the leaf structure at
// Check if kdtree has been built
if (!searchable_)
{
- PCL_WARN ("%s: Not Searchable", this->getClassName ().c_str ());
+ PCL_WARN ("[%s::nearestKSearch] Not Searchable\n", this->getClassName ().c_str ());
return 0;
}
// Check if kdtree has been built
if (!searchable_)
{
- PCL_WARN ("%s: Not Searchable", this->getClassName ().c_str ());
+ PCL_WARN ("[%s::radiusSearch] Not Searchable\n", this->getClassName ().c_str ());
return 0;
}
/** \brief Constructor.
* Sets \ref leaf_size_ to 0.
*/
- VoxelGridLabel () {};
+ VoxelGridLabel () = default;
protected:
using PointCloudConstPtr = typename PointCloud::ConstPtr;
public:
+
+ PCL_MAKE_ALIGNED_OPERATOR_NEW;
+
/** \brief Empty constructor. */
VoxelGridOcclusionEstimation ()
{
}
/** \brief Destructor. */
- ~VoxelGridOcclusionEstimation ()
- {
- }
+ ~VoxelGridOcclusionEstimation () override = default;
/** \brief Initialize the voxel grid, needs to be called first
* Builts the voxel grid and computes additional values for
const static float user_filter_value = user_filter_value_;
for (const auto ri : *removed_indices_) // ri = removed index
{
- std::uint8_t* pt_data = reinterpret_cast<std::uint8_t*> (&output.data[ri * output.point_step]);
+ auto* pt_data = reinterpret_cast<std::uint8_t*> (&output.data[ri * output.point_step]);
for (const auto &offset : offsets)
{
memcpy (pt_data + offset, &user_filter_value, sizeof (float));
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2020-, Open Perception, Inc.
+ *
+ * All rights reserved.
+ */
+
+#include <pcl/filters/farthest_point_sampling.h>
+#include <pcl/filters/impl/farthest_point_sampling.hpp>
+
+#ifndef PCL_NO_PRECOMPILE
+#include <pcl/point_types.h>
+#include <pcl/impl/instantiate.hpp>
+
+PCL_INSTANTIATE(FarthestPointSampling, PCL_XYZ_POINT_TYPES);
+
+#endif // PCL_NO_PRECOMPILE
+
}
// Get the field's value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&input_->data[ii * input_->point_step]);
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&input_->data[ii * input_->point_step]);
float field_value = 0;
memcpy (&field_value, pt_data + input_->fields[distance_idx].offset, sizeof (float));
pcl::ProjectInliers<pcl::PCLPointCloud2>::initSACModel (int model_type)
{
// Convert the input data
- PointCloud<PointXYZ> cloud;
- fromPCLPointCloud2 (*input_, cloud);
- PointCloud<PointXYZ>::Ptr cloud_ptr = cloud.makeShared ();
+ PointCloud<PointXYZ>::Ptr cloud_ptr(new PointCloud<PointXYZ>);
+ fromPCLPointCloud2 (*input_, *cloud_ptr);
// Build the model
switch (model_type)
--- /dev/null
+/*
+ * Software License Agreement (BSD License)
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2020-, Open Perception, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the copyright holder(s) nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <pcl/filters/pyramid.h>
+#include <pcl/console/print.h>
+#include <pcl/point_types.h>
+#include <pcl/common/distances.h> // for squaredEuclideanDistance
+#include <pcl/common/point_tests.h> // for isFinite
+
+namespace pcl {
+namespace filters {
+template <>
+inline void
+Pyramid<pcl::PointXYZRGB>::compute(
+ std::vector<Pyramid<pcl::PointXYZRGB>::PointCloudPtr>& output)
+{
+ std::cout << "PointXYZRGB" << std::endl;
+ if (!initCompute()) {
+ PCL_ERROR("[pcl::%s::compute] initCompute failed!\n", getClassName().c_str());
+ return;
+ }
+
+ int kernel_rows = static_cast<int>(kernel_.rows());
+ int kernel_cols = static_cast<int>(kernel_.cols());
+ int kernel_center_x = kernel_cols / 2;
+ int kernel_center_y = kernel_rows / 2;
+
+ output.resize(levels_ + 1);
+ output[0].reset(new pcl::PointCloud<pcl::PointXYZRGB>);
+ *(output[0]) = *input_;
+
+ if (input_->is_dense) {
+ for (int l = 1; l <= levels_; ++l) {
+ output[l].reset(new pcl::PointCloud<pcl::PointXYZRGB>(output[l - 1]->width / 2,
+ output[l - 1]->height / 2));
+ const PointCloud<pcl::PointXYZRGB>& previous = *output[l - 1];
+ PointCloud<pcl::PointXYZRGB>& next = *output[l];
+#pragma omp parallel for default(none) shared(next, previous, kernel_rows, kernel_cols, kernel_center_x, kernel_center_y) num_threads(threads_)
+ for (int i = 0; i < static_cast<int>(next.height); ++i) { // rows
+ for (int j = 0; j < static_cast<int>(next.width); ++j) { // columns
+ float r = 0, g = 0, b = 0;
+ for (int m = 0; m < kernel_rows; ++m) // kernel rows
+ {
+ int mm = kernel_rows - 1 - m; // row index of flipped kernel
+ for (int n = 0; n < kernel_cols; ++n) // kernel columns
+ {
+ int nn = kernel_cols - 1 - n; // column index of flipped kernel
+ // index of input signal, used for checking boundary
+ int ii = 2 * i + (m - kernel_center_y);
+ int jj = 2 * j + (n - kernel_center_x);
+
+ // ignore input samples which are out of bound
+ if (ii < 0)
+ ii = 0;
+ if (ii >= static_cast<int>(previous.height))
+ ii = previous.height - 1;
+ if (jj < 0)
+ jj = 0;
+ if (jj >= static_cast<int>(previous.width))
+ jj = previous.width - 1;
+ next.at(j, i).x += previous.at(jj, ii).x * kernel_(mm, nn);
+ next.at(j, i).y += previous.at(jj, ii).y * kernel_(mm, nn);
+ next.at(j, i).z += previous.at(jj, ii).z * kernel_(mm, nn);
+ b += previous.at(jj, ii).b * kernel_(mm, nn);
+ g += previous.at(jj, ii).g * kernel_(mm, nn);
+ r += previous.at(jj, ii).r * kernel_(mm, nn);
+ }
+ }
+ next.at(j, i).b = static_cast<std::uint8_t>(b);
+ next.at(j, i).g = static_cast<std::uint8_t>(g);
+ next.at(j, i).r = static_cast<std::uint8_t>(r);
+ }
+ }
+ }
+ }
+ else {
+ for (int l = 1; l <= levels_; ++l) {
+ output[l].reset(new pcl::PointCloud<pcl::PointXYZRGB>(output[l - 1]->width / 2,
+ output[l - 1]->height / 2));
+ const PointCloud<pcl::PointXYZRGB>& previous = *output[l - 1];
+ PointCloud<pcl::PointXYZRGB>& next = *output[l];
+#pragma omp parallel for default(none) shared(next, previous, kernel_rows, kernel_cols, kernel_center_x, kernel_center_y) num_threads(threads_)
+ for (int i = 0; i < static_cast<int>(next.height); ++i) { // rows
+ for (int j = 0; j < static_cast<int>(next.width); ++j) { // columns
+ float weight = 0;
+ float r = 0, g = 0, b = 0;
+ for (int m = 0; m < kernel_rows; ++m) {
+ int mm = kernel_rows - 1 - m;
+ for (int n = 0; n < kernel_cols; ++n) {
+ int nn = kernel_cols - 1 - n;
+ int ii = 2 * i + (m - kernel_center_y);
+ int jj = 2 * j + (n - kernel_center_x);
+ if (ii < 0)
+ ii = 0;
+ if (ii >= static_cast<int>(previous.height))
+ ii = previous.height - 1;
+ if (jj < 0)
+ jj = 0;
+ if (jj >= static_cast<int>(previous.width))
+ jj = previous.width - 1;
+ if (!isFinite(previous.at(jj, ii)))
+ continue;
+ if (pcl::squaredEuclideanDistance(previous.at(2 * j, 2 * i),
+ previous.at(jj, ii)) < threshold_) {
+ next.at(j, i).x += previous.at(jj, ii).x * kernel_(mm, nn);
+ next.at(j, i).y += previous.at(jj, ii).y * kernel_(mm, nn);
+ next.at(j, i).z += previous.at(jj, ii).z * kernel_(mm, nn);
+ b += previous.at(jj, ii).b * kernel_(mm, nn);
+ g += previous.at(jj, ii).g * kernel_(mm, nn);
+ r += previous.at(jj, ii).r * kernel_(mm, nn);
+ weight += kernel_(mm, nn);
+ }
+ }
+ }
+ if (weight == 0)
+ nullify(next.at(j, i));
+ else {
+ weight = 1.f / weight;
+ r *= weight;
+ g *= weight;
+ b *= weight;
+ next.at(j, i).x *= weight;
+ next.at(j, i).y *= weight;
+ next.at(j, i).z *= weight;
+ next.at(j, i).b = static_cast<std::uint8_t>(b);
+ next.at(j, i).g = static_cast<std::uint8_t>(g);
+ next.at(j, i).r = static_cast<std::uint8_t>(r);
+ }
+ }
+ }
+ }
+ }
+}
+
+template <>
+inline void
+Pyramid<pcl::PointXYZRGBA>::compute(
+ std::vector<Pyramid<pcl::PointXYZRGBA>::PointCloudPtr>& output)
+{
+ std::cout << "PointXYZRGBA" << std::endl;
+ if (!initCompute()) {
+ PCL_ERROR("[pcl::%s::compute] initCompute failed!\n", getClassName().c_str());
+ return;
+ }
+
+ int kernel_rows = static_cast<int>(kernel_.rows());
+ int kernel_cols = static_cast<int>(kernel_.cols());
+ int kernel_center_x = kernel_cols / 2;
+ int kernel_center_y = kernel_rows / 2;
+
+ output.resize(levels_ + 1);
+ output[0].reset(new pcl::PointCloud<pcl::PointXYZRGBA>);
+ *(output[0]) = *input_;
+
+ if (input_->is_dense) {
+ for (int l = 1; l <= levels_; ++l) {
+ output[l].reset(new pcl::PointCloud<pcl::PointXYZRGBA>(
+ output[l - 1]->width / 2, output[l - 1]->height / 2));
+ const PointCloud<pcl::PointXYZRGBA>& previous = *output[l - 1];
+ PointCloud<pcl::PointXYZRGBA>& next = *output[l];
+#pragma omp parallel for default(none) shared(next, previous, kernel_rows, kernel_cols, kernel_center_x, kernel_center_y) num_threads(threads_)
+ for (int i = 0; i < static_cast<int>(next.height); ++i) { // rows
+ for (int j = 0; j < static_cast<int>(next.width); ++j) { // columns
+ float r = 0, g = 0, b = 0, a = 0;
+ for (int m = 0; m < kernel_rows; ++m) // kernel rows
+ {
+ int mm = kernel_rows - 1 - m; // row index of flipped kernel
+ for (int n = 0; n < kernel_cols; ++n) // kernel columns
+ {
+ int nn = kernel_cols - 1 - n; // column index of flipped kernel
+ // index of input signal, used for checking boundary
+ int ii = 2 * i + (m - kernel_center_y);
+ int jj = 2 * j + (n - kernel_center_x);
+
+ // ignore input samples which are out of bound
+ if (ii < 0)
+ ii = 0;
+ if (ii >= static_cast<int>(previous.height))
+ ii = previous.height - 1;
+ if (jj < 0)
+ jj = 0;
+ if (jj >= static_cast<int>(previous.width))
+ jj = previous.width - 1;
+ next.at(j, i).x += previous.at(jj, ii).x * kernel_(mm, nn);
+ next.at(j, i).y += previous.at(jj, ii).y * kernel_(mm, nn);
+ next.at(j, i).z += previous.at(jj, ii).z * kernel_(mm, nn);
+ b += previous.at(jj, ii).b * kernel_(mm, nn);
+ g += previous.at(jj, ii).g * kernel_(mm, nn);
+ r += previous.at(jj, ii).r * kernel_(mm, nn);
+ a += previous.at(jj, ii).a * kernel_(mm, nn);
+ }
+ }
+ next.at(j, i).b = static_cast<std::uint8_t>(b);
+ next.at(j, i).g = static_cast<std::uint8_t>(g);
+ next.at(j, i).r = static_cast<std::uint8_t>(r);
+ next.at(j, i).a = static_cast<std::uint8_t>(a);
+ }
+ }
+ }
+ }
+ else {
+ for (int l = 1; l <= levels_; ++l) {
+ output[l].reset(new pcl::PointCloud<pcl::PointXYZRGBA>(
+ output[l - 1]->width / 2, output[l - 1]->height / 2));
+ const PointCloud<pcl::PointXYZRGBA>& previous = *output[l - 1];
+ PointCloud<pcl::PointXYZRGBA>& next = *output[l];
+#pragma omp parallel for default(none) shared(next, previous, kernel_rows, kernel_cols, kernel_center_x, kernel_center_y) num_threads(threads_)
+ for (int i = 0; i < static_cast<int>(next.height); ++i) { // rows
+ for (int j = 0; j < static_cast<int>(next.width); ++j) { // columns
+ float weight = 0;
+ float r = 0, g = 0, b = 0, a = 0;
+ for (int m = 0; m < kernel_rows; ++m) {
+ int mm = kernel_rows - 1 - m;
+ for (int n = 0; n < kernel_cols; ++n) {
+ int nn = kernel_cols - 1 - n;
+ int ii = 2 * i + (m - kernel_center_y);
+ int jj = 2 * j + (n - kernel_center_x);
+ if (ii < 0)
+ ii = 0;
+ if (ii >= static_cast<int>(previous.height))
+ ii = previous.height - 1;
+ if (jj < 0)
+ jj = 0;
+ if (jj >= static_cast<int>(previous.width))
+ jj = previous.width - 1;
+ if (!isFinite(previous.at(jj, ii)))
+ continue;
+ if (pcl::squaredEuclideanDistance(previous.at(2 * j, 2 * i),
+ previous.at(jj, ii)) < threshold_) {
+ next.at(j, i).x += previous.at(jj, ii).x * kernel_(mm, nn);
+ next.at(j, i).y += previous.at(jj, ii).y * kernel_(mm, nn);
+ next.at(j, i).z += previous.at(jj, ii).z * kernel_(mm, nn);
+ b += previous.at(jj, ii).b * kernel_(mm, nn);
+ g += previous.at(jj, ii).g * kernel_(mm, nn);
+ r += previous.at(jj, ii).r * kernel_(mm, nn);
+ a += previous.at(jj, ii).a * kernel_(mm, nn);
+ weight += kernel_(mm, nn);
+ }
+ }
+ }
+ if (weight == 0)
+ nullify(next.at(j, i));
+ else {
+ weight = 1.f / weight;
+ r *= weight;
+ g *= weight;
+ b *= weight;
+ a *= weight;
+ next.at(j, i).x *= weight;
+ next.at(j, i).y *= weight;
+ next.at(j, i).z *= weight;
+ next.at(j, i).b = static_cast<std::uint8_t>(b);
+ next.at(j, i).g = static_cast<std::uint8_t>(g);
+ next.at(j, i).r = static_cast<std::uint8_t>(r);
+ next.at(j, i).a = static_cast<std::uint8_t>(a);
+ }
+ }
+ }
+ }
+ }
+}
+
+template <>
+inline void
+Pyramid<pcl::RGB>::nullify(pcl::RGB& p) const
+{
+ p.r = 0; p.g = 0; p.b = 0;
+}
+
+template <>
+inline void
+Pyramid<pcl::RGB>::compute(std::vector<Pyramid<pcl::RGB>::PointCloudPtr>& output)
+{
+ std::cout << "RGB" << std::endl;
+ if (!initCompute()) {
+ PCL_ERROR("[pcl::%s::compute] initCompute failed!\n", getClassName().c_str());
+ return;
+ }
+
+ int kernel_rows = static_cast<int>(kernel_.rows());
+ int kernel_cols = static_cast<int>(kernel_.cols());
+ int kernel_center_x = kernel_cols / 2;
+ int kernel_center_y = kernel_rows / 2;
+
+ output.resize(levels_ + 1);
+ output[0].reset(new pcl::PointCloud<pcl::RGB>);
+ *(output[0]) = *input_;
+
+ if (input_->is_dense) {
+ for (int l = 1; l <= levels_; ++l) {
+ output[l].reset(new pcl::PointCloud<pcl::RGB>(output[l - 1]->width / 2,
+ output[l - 1]->height / 2));
+ const PointCloud<pcl::RGB>& previous = *output[l - 1];
+ PointCloud<pcl::RGB>& next = *output[l];
+#pragma omp parallel for default(none) shared(next, previous, kernel_rows, kernel_cols, kernel_center_x, kernel_center_y) num_threads(threads_)
+ for (int i = 0; i < static_cast<int>(next.height); ++i) { // rows
+ for (int j = 0; j < static_cast<int>(next.width); ++j) { // columns
+ float r = 0, g = 0, b = 0;
+ for (int m = 0; m < kernel_rows; ++m) {
+ int mm = kernel_rows - 1 - m;
+ for (int n = 0; n < kernel_cols; ++n) {
+ int nn = kernel_cols - 1 - n;
+ int ii = 2 * i + (m - kernel_center_y);
+ int jj = 2 * j + (n - kernel_center_x);
+ if (ii < 0)
+ ii = 0;
+ if (ii >= static_cast<int>(previous.height))
+ ii = previous.height - 1;
+ if (jj < 0)
+ jj = 0;
+ if (jj >= static_cast<int>(previous.width))
+ jj = previous.width - 1;
+ b += previous.at(jj, ii).b * kernel_(mm, nn);
+ g += previous.at(jj, ii).g * kernel_(mm, nn);
+ r += previous.at(jj, ii).r * kernel_(mm, nn);
+ }
+ }
+ next.at(j, i).b = static_cast<std::uint8_t>(b);
+ next.at(j, i).g = static_cast<std::uint8_t>(g);
+ next.at(j, i).r = static_cast<std::uint8_t>(r);
+ }
+ }
+ }
+ }
+ else {
+ for (int l = 1; l <= levels_; ++l) {
+ output[l].reset(new pcl::PointCloud<pcl::RGB>(output[l - 1]->width / 2,
+ output[l - 1]->height / 2));
+ const PointCloud<pcl::RGB>& previous = *output[l - 1];
+ PointCloud<pcl::RGB>& next = *output[l];
+#pragma omp parallel for default(none) shared(next, previous, kernel_rows, kernel_cols, kernel_center_x, kernel_center_y) num_threads(threads_)
+ for (int i = 0; i < static_cast<int>(next.height); ++i) { // rows
+ for (int j = 0; j < static_cast<int>(next.width); ++j) { // columns
+ float weight = 0;
+ float r = 0, g = 0, b = 0;
+ for (int m = 0; m < kernel_rows; ++m) {
+ int mm = kernel_rows - 1 - m;
+ for (int n = 0; n < kernel_cols; ++n) {
+ int nn = kernel_cols - 1 - n;
+ int ii = 2 * i + (m - kernel_center_y);
+ int jj = 2 * j + (n - kernel_center_x);
+ if (ii < 0)
+ ii = 0;
+ if (ii >= static_cast<int>(previous.height))
+ ii = previous.height - 1;
+ if (jj < 0)
+ jj = 0;
+ if (jj >= static_cast<int>(previous.width))
+ jj = previous.width - 1;
+ if (!isFinite(previous.at(jj, ii)))
+ continue;
+ /*if (pcl::squaredEuclideanDistance(previous.at(2 * j, 2 * i),
+ previous.at(jj, ii)) < threshold_)*/ {
+ b += previous.at(jj, ii).b * kernel_(mm, nn);
+ g += previous.at(jj, ii).g * kernel_(mm, nn);
+ r += previous.at(jj, ii).r * kernel_(mm, nn);
+ weight += kernel_(mm, nn);
+ }
+ }
+ }
+ if (weight == 0)
+ nullify(next.at(j, i));
+ else {
+ weight = 1.f / weight;
+ r *= weight;
+ g *= weight;
+ b *= weight;
+ next.at(j, i).b = static_cast<std::uint8_t>(b);
+ next.at(j, i).g = static_cast<std::uint8_t>(g);
+ next.at(j, i).r = static_cast<std::uint8_t>(r);
+ }
+ }
+ }
+ }
+ }
+}
+} // namespace filters
+} // namespace pcl
const static float user_filter_value = user_filter_value_;
for (const auto ri : *removed_indices_) // ri = removed index
{
- std::uint8_t* pt_data = reinterpret_cast<std::uint8_t*> (&output.data[ri * output.point_step]);
+ auto* pt_data = reinterpret_cast<std::uint8_t*> (&output.data[ri * output.point_step]);
for (const auto &offset : offsets)
{
memcpy (pt_data + offset, &user_filter_value, sizeof (float));
*
*/
-#include <iostream>
+#include <limits>
#include <pcl/common/io.h>
#include <pcl/filters/impl/voxel_grid.hpp>
#include <boost/sort/spreadsort/integer_sort.hpp>
}
Eigen::Array4f min_p, max_p;
- min_p.setConstant (FLT_MAX);
- max_p.setConstant (-FLT_MAX);
+ min_p.setConstant (std::numeric_limits<float>::max());
+ max_p.setConstant (std::numeric_limits<float>::lowest());
std::size_t nr_points = cloud->width * cloud->height;
}
Eigen::Array4f min_p, max_p;
- min_p.setConstant (FLT_MAX);
- max_p.setConstant (-FLT_MAX);
+ min_p.setConstant (std::numeric_limits<float>::max());
+ max_p.setConstant (std::numeric_limits<float>::lowest());
// Get the distance field index
int distance_idx = pcl::getFieldIndex (*cloud, distance_field_name);
continue;
// Get the distance value
- const std::uint8_t* pt_data = reinterpret_cast<const std::uint8_t*> (&(*input_)[cp]);
+ const auto* pt_data = reinterpret_cast<const std::uint8_t*> (&(*input_)[cp]);
float distance_value = 0;
memcpy (&distance_value, pt_data + fields[distance_idx].offset, sizeof (float));
{
// store the label in a map data structure
std::uint32_t label = (*input_)[index_vector[cp].cloud_point_index].label;
- std::map<int, int>::iterator it = labels.find (label);
+ auto it = labels.find (label);
if (it == labels.end ())
labels.insert (labels.begin (), std::pair<int, int> (label, 1));
else
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
#ifdef __GNUC__
#pragma GCC system_header
#endif
+PCL_DEPRECATED_HEADER(1, 16, "Please include the needed boost headers directly.")
#include <boost/operators.hpp>
#include <boost/version.hpp>
const Neighborhood& neighborhood = Neighbor8);
/** \brief Destructor*/
- ~LineIterator();
+ ~LineIterator() override;
void
operator++() override;
}
////////////////////////////////////////////////////////////////////////////////
-inline LineIterator::~LineIterator() {}
+inline LineIterator::~LineIterator() = default;
////////////////////////////////////////////////////////////////////////////////
inline void
}
} while (++circ != circ_end);
- for (FaceIndices::const_iterator it = delete_faces_vertex_.begin();
- it != delete_faces_vertex_.end();
- ++it) {
- this->deleteFace(*it);
+ for (const auto& delete_me : delete_faces_vertex_) {
+ this->deleteFace(delete_me);
}
}
}
// Adjust the indices
- for (VertexIterator it = vertices_.begin(); it != vertices_.end(); ++it) {
+ for (auto it = vertices_.begin(); it != vertices_.end(); ++it) {
if (it->idx_outgoing_half_edge_.isValid()) {
it->idx_outgoing_half_edge_ =
new_half_edge_indices[it->idx_outgoing_half_edge_.get()];
}
}
- for (HalfEdgeIterator it = half_edges_.begin(); it != half_edges_.end(); ++it) {
+ for (auto it = half_edges_.begin(); it != half_edges_.end(); ++it) {
it->idx_terminating_vertex_ =
new_vertex_indices[it->idx_terminating_vertex_.get()];
it->idx_next_half_edge_ = new_half_edge_indices[it->idx_next_half_edge_.get()];
}
}
- for (FaceIterator it = faces_.begin(); it != faces_.end(); ++it) {
+ for (auto it = faces_.begin(); it != faces_.end(); ++it) {
it->idx_inner_half_edge_ = new_half_edge_indices[it->idx_inner_half_edge_.get()];
}
}
inline void
resizeVertices(const std::size_t n, const VertexData& data = VertexData())
{
- vertices_.resize(n);
+ vertices_.resize(n, Vertex());
this->resizeData(vertex_data_cloud_, n, data, HasVertexData());
}
const EdgeData& edge_data = EdgeData(),
const HalfEdgeData he_data = HalfEdgeData())
{
- half_edges_.resize(2 * n);
+ half_edges_.resize(2 * n, HalfEdge());
this->resizeData(half_edge_data_cloud_, 2 * n, he_data, HasHalfEdgeData());
this->resizeData(edge_data_cloud_, n, edge_data, HasEdgeData());
}
inline void
resizeFaces(const std::size_t n, const FaceData& data = FaceData())
{
- faces_.resize(n);
+ faces_.resize(n, Face());
this->resizeData(face_data_cloud_, n, data, HasFaceData());
}
Index ind_old(0), ind_new(0);
typename ElementContainerT::const_iterator it_e_old = elements.begin();
- typename ElementContainerT::iterator it_e_new = elements.begin();
+ auto it_e_new = elements.begin();
typename DataContainerT::const_iterator it_d_old = data_cloud.begin();
- typename DataContainerT::iterator it_d_new = data_cloud.begin();
+ auto it_d_new = data_cloud.begin();
- typename IndexContainerT::iterator it_ind_new = new_indices.begin();
+ auto it_ind_new = new_indices.begin();
typename IndexContainerT::const_iterator it_ind_new_end = new_indices.end();
while (it_ind_new != it_ind_new_end) {
}
/** \brief Always manifold. */
- inline bool isManifold(std::true_type /*is_manifold*/) const { return (true); }
+ inline bool
+ isManifold(std::true_type /*is_manifold*/) const
+ {
+ return (true);
+ }
/** \brief Check if all vertices in the mesh are manifold. */
- bool isManifold(std::false_type /*is_manifold*/) const
+ bool
+ isManifold(std::false_type /*is_manifold*/) const
{
for (std::size_t i = 0; i < this->sizeVertices(); ++i) {
if (!this->isManifold(VertexIndex(i)))
/** \brief Resize the mesh data. */
template <class DataCloudT>
inline void
- resizeData(DataCloudT& /*data_cloud*/,
+ resizeData(DataCloudT& data_cloud,
const std::size_t n,
const typename DataCloudT::value_type& data,
std::true_type /*has_data*/) const
{
- data.resize(n, data);
+ data_cloud.resize(n, data);
}
/** \brief Does nothing. */
#pragma once
-#include <pcl/geometry/boost.h>
#include <pcl/geometry/mesh_indices.h>
+#include <boost/operators.hpp>
+
////////////////////////////////////////////////////////////////////////////////
// VertexAroundVertexCirculator
////////////////////////////////////////////////////////////////////////////////
f.write ('#ifndef PCL_GEOMETRY_MESH_CIRCULATORS_H\n')
f.write ('#define PCL_GEOMETRY_MESH_CIRCULATORS_H\n\n')
-f.write ('#include <pcl/geometry/boost.h>\n')
f.write ('#include <pcl/geometry/mesh_indices.h>\n\n')
+f.write ('#include <boost/operators.hpp>\n\n')
for c in classes:
/** \brief Stored index. */
int index_;
- friend std::istream& operator>><>(std::istream& is, MeshIndex<IndexTagT>& index);
+ friend std::istream&
+ operator>><>(std::istream& is, MeshIndex<IndexTagT>& index);
};
/** \brief ostream operator. */
using FaceIndex = typename Mesh::FaceIndex;
/** \brief Constructor. */
- MeshIO() {}
+ MeshIO() = default;
/** \brief Read the mesh from a file with the given filename.
* \param[in] filename Path to the file.
<< mesh.sizeFaces() << "\n";
// Write the vertices
- for (typename Vertices::const_iterator it = mesh.vertices_.begin();
- it != mesh.vertices_.end();
- ++it) {
- file << it->idx_outgoing_half_edge_ << "\n";
+ for (const auto& vertex : mesh.vertices_) {
+ file << vertex.idx_outgoing_half_edge_ << "\n";
}
// Write the half-edges
- for (typename HalfEdges::const_iterator it = mesh.half_edges_.begin();
- it != mesh.half_edges_.end();
- ++it) {
- file << it->idx_terminating_vertex_ << " " << it->idx_next_half_edge_ << " "
- << it->idx_prev_half_edge_ << " " << it->idx_face_ << "\n";
+ for (const auto& edge : mesh.half_edges_) {
+ file << edge.idx_terminating_vertex_ << " " << edge.idx_next_half_edge_ << " "
+ << edge.idx_prev_half_edge_ << " " << edge.idx_face_ << "\n";
}
// Write the faces
- for (typename Faces::const_iterator it = mesh.faces_.begin();
- it != mesh.faces_.end();
- ++it) {
- file << it->idx_inner_half_edge_ << "\n";
+ for (const auto& face : mesh.faces_) {
+ file << face.idx_inner_half_edge_ << "\n";
}
return (true);
{}
////////////////////////////////////////////////////////////////////////////////
-inline OrganizedIndexIterator::~OrganizedIndexIterator() {}
+inline OrganizedIndexIterator::~OrganizedIndexIterator() = default;
////////////////////////////////////////////////////////////////////////////////
inline void
{}
/** \brief Destructor. */
- virtual ~PlanarPolygon() {}
+ virtual ~PlanarPolygon() = default;
/** \brief Set the internal contour
* \param[in] contour the new planar polygonal contour
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
#include <pcl/gpu/containers/kernel_containers.h>
#include <pcl/pcl_exports.h>
+#include <atomic>
+
namespace pcl {
namespace gpu {
///////////////////////////////////////////////////////////////////////////////
std::size_t sizeBytes_;
/** \brief Pointer to reference counter in CPU memory. */
- int* refcount_;
+ std::atomic<int>* refcount_;
};
///////////////////////////////////////////////////////////////////////////////
int rows_;
/** \brief Pointer to reference counter in CPU memory. */
- int* refcount_;
+ std::atomic<int>* refcount_;
};
} // namespace gpu
#include <pcl/gpu/containers/device_memory.h>
#include <pcl/gpu/utils/safe_call.hpp>
+#include <pcl/pcl_config.h> // used for HAVE_CUDA
+#include <pcl/pcl_macros.h> // used for PCL_DEPRECATED
#include <cuda_runtime_api.h>
#include <cassert>
-#define HAVE_CUDA
-//#include <pcl_config.h>
-
#if !defined(HAVE_CUDA)
void
return *this;
}
-void pcl::gpu::DeviceMemory::create(std::size_t) { throw_nogpu(); }
+void
+pcl::gpu::DeviceMemory::create(std::size_t)
+{
+ throw_nogpu();
+}
void
pcl::gpu::DeviceMemory::release()
////////////////////////// XADD ///////////////////////////////
-#ifdef __GNUC__
-#if !defined WIN32 && (defined __i486__ || defined __i586__ || defined __i686__ || \
- defined __MMX__ || defined __SSE__ || defined __ppc__)
-#define CV_XADD __sync_fetch_and_add
-#else
-#include <ext/atomicity.h>
-#define CV_XADD __gnu_cxx::__exchange_and_add
-#endif
-#elif defined WIN32 || defined _WIN32
-#include <intrin.h>
-#define CV_XADD(addr, delta) _InterlockedExchangeAdd((long volatile*)(addr), (delta))
-#else
-
template <typename _Tp>
-static inline _Tp
-CV_XADD(_Tp* addr, _Tp delta)
+PCL_DEPRECATED(1, 16, "Removed in favour of c++11 atomics")
+static inline _Tp CV_XADD(std::atomic<_Tp>* addr, std::atomic<_Tp> delta)
{
- int tmp = *addr;
- *addr += delta;
+ _Tp tmp = addr->fetch_add(delta);
return tmp;
}
-#endif
-
//////////////////////// DeviceArray /////////////////////////////
pcl::gpu::DeviceMemory::DeviceMemory()
, refcount_(other_arg.refcount_)
{
if (refcount_)
- CV_XADD(refcount_, 1);
+ refcount_->fetch_add(1);
}
pcl::gpu::DeviceMemory&
{
if (this != &other_arg) {
if (other_arg.refcount_)
- CV_XADD(other_arg.refcount_, 1);
+ other_arg.refcount_->fetch_add(1);
release();
data_ = other_arg.data_;
cudaSafeCall(cudaMalloc(&data_, sizeBytes_));
- // refcount_ = (int*)cv::fastMalloc(sizeof(*refcount_));
- refcount_ = new int;
- *refcount_ = 1;
+ refcount_ = new std::atomic<int>(1);
}
}
void
pcl::gpu::DeviceMemory::release()
{
- if (refcount_ && CV_XADD(refcount_, -1) == 1) {
- // cv::fastFree(refcount);
+ if (refcount_ && refcount_->fetch_sub(1) == 1) {
delete refcount_;
cudaSafeCall(cudaFree(data_));
}
, refcount_(other_arg.refcount_)
{
if (refcount_)
- CV_XADD(refcount_, 1);
+ refcount_->fetch_add(1);
}
pcl::gpu::DeviceMemory2D&
{
if (this != &other_arg) {
if (other_arg.refcount_)
- CV_XADD(other_arg.refcount_, 1);
+ other_arg.refcount_->fetch_add(1);
release();
colsBytes_ = other_arg.colsBytes_;
cudaSafeCall(cudaMallocPitch((void**)&data_, &step_, colsBytes_, rows_));
- // refcount = (int*)cv::fastMalloc(sizeof(*refcount));
- refcount_ = new int;
- *refcount_ = 1;
+ refcount_ = new std::atomic<int>(1);
}
}
void
pcl::gpu::DeviceMemory2D::release()
{
- if (refcount_ && CV_XADD(refcount_, -1) == 1) {
- // cv::fastFree(refcount);
+ if (refcount_ && refcount_->fetch_sub(1) == 1) {
delete refcount_;
cudaSafeCall(cudaFree(data_));
}
const int line,
const char* func)
{
- std::cout << "Error: " << error_string << "\t" << file << ":" << line << std::endl;
+ std::cout << "Error: " << error_string << "\t" << file << ":" << line << ":" << func
+ << std::endl;
exit(EXIT_FAILURE);
}
namespace {
template <class T>
inline void
-getCudaAttribute(T* attribute, CUdevice_attribute device_attribute, int device)
+getCudaAttribute(T* attribute, CUdevice_attribute /*device_attribute*/, int /*device*/)
{
*attribute = T();
CUresult error =
- CUDA_SUCCESS; // = cuDeviceGetAttribute( attribute, device_attribute, device );
+ CUDA_SUCCESS; // cuDeviceGetAttribute(attribute, device_attribute, device);
+
if (CUDA_SUCCESS == error)
return;
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
{
public:
FPFHEstimation();
- virtual ~FPFHEstimation();
void compute(DeviceArray2D<FPFHSignature33>& features);
#include "pcl/gpu/utils/device/vector_math.hpp"
-using namespace thrust;
-
namespace pcl
{
namespace device
thrust::counting_iterator<int> ce = cf + cloud.size();
thrust::tuple<float, int> init(0.f, 0);
- thrust::maximum< tuple<float, int> > op;
+ thrust::maximum<thrust::tuple<float, int>> op;
- tuple<float, int> res = transform_reduce(
+ thrust::tuple<float, int> res =
+ transform_reduce(
make_zip_iterator(make_tuple( src_beg, cf )),
make_zip_iterator(make_tuple( src_beg, ce )),
TupleDistCvt(pivot), init, op);
thrust::counting_iterator<int> ce = cf + indices.size();
thrust::tuple<float, int> init(0.f, 0);
- thrust::maximum< tuple<float, int> > op;
+ thrust::maximum<thrust::tuple<float, int>> op;
- tuple<float, int> res = transform_reduce(
+ thrust::tuple<float, int> res = transform_reduce(
make_zip_iterator(make_tuple( make_permutation_iterator(src_beg, map_beg), cf )),
make_zip_iterator(make_tuple( make_permutation_iterator(src_beg, map_end), ce )),
TupleDistCvt(pivot), init, op);
#include <pcl/gpu/containers/initialization.h>
#include <pcl/gpu/features/features.hpp>
-#include <pcl/gpu/utils/device/static_check.hpp>
#include "internal.hpp"
#include <pcl/exceptions.h>
pcl::gpu::FPFHEstimation::FPFHEstimation()
{
- Static<sizeof(FPFHEstimation:: PointType) == sizeof(device:: PointType)>::check();
- Static<sizeof(FPFHEstimation::NormalType) == sizeof(device::NormalType)>::check();
+ static_assert(sizeof(FPFHEstimation:: PointType) == sizeof(device:: PointType), "Point sizes do not match");
+ static_assert(sizeof(FPFHEstimation::NormalType) == sizeof(device::NormalType), "Normal sizes do not match");
}
-pcl::gpu::FPFHEstimation::~FPFHEstimation() {}
-
-
void pcl::gpu::FPFHEstimation::compute(const PointCloud& cloud, const Normals& normals, const NeighborIndices& neighbours, DeviceArray2D<FPFHSignature33>& features)
{
assert( cloud.size() == normals.size() );
void pcl::gpu::PPFEstimation::compute(DeviceArray<PPFSignature>& features)
{
- Static<sizeof(PPFEstimation:: PointType) == sizeof(device:: PointType)>::check();
- Static<sizeof(PPFEstimation::NormalType) == sizeof(device::NormalType)>::check();
+ static_assert(sizeof(PPFEstimation:: PointType) == sizeof(device:: PointType), "Point sizes do not match");
+ static_assert(sizeof(PPFEstimation::NormalType) == sizeof(device::NormalType), "Normal sizes do not match");
assert(this->surface_.empty() && !indices_.empty() && !cloud_.empty() && normals_.size() == cloud_.size());
features.create(indices_.size () * cloud_.size ());
void pcl::gpu::PPFRGBEstimation::compute(DeviceArray<PPFRGBSignature>& features)
{
- Static<sizeof(PPFEstimation:: PointType) == sizeof(device:: PointType)>::check();
- Static<sizeof(PPFEstimation::NormalType) == sizeof(device::NormalType)>::check();
+ static_assert(sizeof(PPFEstimation:: PointType) == sizeof(device:: PointType), "Point sizes do not match");
+ static_assert(sizeof(PPFEstimation::NormalType) == sizeof(device::NormalType), "Normal sizes do not match");
assert(this->surface_.empty() && !indices_.empty() && !cloud_.empty() && normals_.size() == cloud_.size());
features.create(indices_.size () * cloud_.size ());
void pcl::gpu::PPFRGBRegionEstimation::compute(DeviceArray<PPFRGBSignature>& features)
{
- Static<sizeof(PPFRGBRegionEstimation:: PointType) == sizeof(device:: PointType)>::check();
- Static<sizeof(PPFRGBRegionEstimation::NormalType) == sizeof(device::NormalType)>::check();
+ static_assert(sizeof(PPFRGBRegionEstimation:: PointType) == sizeof(device:: PointType), "Point sizes do not match");
+ static_assert(sizeof(PPFRGBRegionEstimation::NormalType) == sizeof(device::NormalType), "Normal sizes do not match");
assert(this->surface_.empty() && !indices_.empty() && !cloud_.empty() && normals_.size() == cloud_.size());
void pcl::gpu::PrincipalCurvaturesEstimation::compute(DeviceArray<PrincipalCurvatures>& features)
{
- Static<sizeof(PPFRGBRegionEstimation:: PointType) == sizeof(device:: PointType)>::check();
- Static<sizeof(PPFRGBRegionEstimation::NormalType) == sizeof(device::NormalType)>::check();
+ static_assert(sizeof(PPFRGBRegionEstimation:: PointType) == sizeof(device:: PointType), "Point sizes do not match");
+ static_assert(sizeof(PPFRGBRegionEstimation::NormalType) == sizeof(device::NormalType), "Normal sizes do not match");
assert(/*!indices_.empty() && */!cloud_.empty() && max_results_ > 0 && radius_ > 0.f);
assert(surface_.empty() ? normals_.size() == cloud_.size() : normals_.size() == surface_.size());
{
assert(!surface_.empty() && normals_.size() == surface_.size() && cloud_.empty());
- Static<sizeof(VFHEstimation:: PointType) == sizeof(device:: PointType)>::check();
- Static<sizeof(VFHEstimation::NormalType) == sizeof(device::NormalType)>::check();
+ static_assert(sizeof(VFHEstimation:: PointType) == sizeof(device:: PointType), "Point sizes do not match");
+ static_assert(sizeof(VFHEstimation::NormalType) == sizeof(device::NormalType), "Normal sizes do not match");
feature.create(1);
if (image_width_ != 8)
pcl::gpu::error("Currently only image_width = 8 is supported (less is possible right now, more - need to allocate more memory)", __FILE__, __LINE__);
- Static<sizeof(SpinImageEstimation:: PointType) == sizeof(device:: PointType)>::check();
- Static<sizeof(SpinImageEstimation::NormalType) == sizeof(device::NormalType)>::check();
+ static_assert(sizeof(SpinImageEstimation:: PointType) == sizeof(device:: PointType), "Point sizes do not match");
+ static_assert(sizeof(SpinImageEstimation::NormalType) == sizeof(device::NormalType), "Normal sizes do not match");
features.create (static_cast<int> (indices_.size ()), 1);
mask.create(indices_.size());
set(DEFAULT TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
*/
ColorVolume(const TsdfVolume& tsdf, int max_weight = -1);
- /** \brief Destructor */
- ~ColorVolume();
-
/** \brief Resets color volume to uninitialized state */
void
reset();
/** \brief Default constructor */
MarchingCubes();
- /** \brief Destructor */
- ~MarchingCubes();
-
/** \brief Runs marching cubes triangulation.
* \param[in] tsdf
* \param[in] triangles_buffer Buffer for triangles. Its size determines max extracted triangles. If empty, it will be allocated with default size to be used.
* \param[in] cy principal point y
*/
RayCaster(int rows = 480, int cols = 640, float fx = 525.f, float fy = 525.f, float cx = -1, float cy = -1);
- ~RayCaster();
/** \brief Sets camera intrinsics */
void
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-pcl::gpu::ColorVolume::~ColorVolume()
-{
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
void
pcl::gpu::ColorVolume::reset()
{
for (int z = 0; z < VOLUME_Z - 1; z++)
{
- int numVerts = 0;;
+ int numVerts = 0;
if (x + 1 < VOLUME_X && y + 1 < VOLUME_Y)
{
float field[8];
break;
}
- } /* for(;;) */
+ }
}
};
triTable_.upload(&triTable[0][0], 256 * 16);
}
-pcl::gpu::MarchingCubes::~MarchingCubes() {}
-
DeviceArray<pcl::gpu::MarchingCubes::PointType>
pcl::gpu::MarchingCubes::run(const TsdfVolume& tsdf, DeviceArray<PointType>& triangles_buffer)
{
normal_map_.create(rows * 3, cols);
}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-pcl::gpu::RayCaster::~RayCaster()
-{
-
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::gpu::RayCaster::setIntrinsics(float fx, float fy, float cx, float cy)
cloud.clear ();
cloud.reserve (10000);
- constexpr int DIVISOR = device::DIVISOR; // SHRT_MAX;
+ constexpr int DIVISOR = device::DIVISOR; // std::numeric_limits<short>::max();
#define FETCH(x, y, z) volume_host[(x) + (y) * volume_x + (z) * volume_y * volume_x]
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})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSUBSYS_NAME} PARENT_NAME ${SUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} OPT_DEPS ${SUBSUBSYS_OPT_DEPS} EXT_DEPS ${EXT_DEPS})
if(NOT build)
return()
using Ptr = pcl::shared_ptr<CameraPoseProcessor>;
using ConstPtr = pcl::shared_ptr<const CameraPoseProcessor>;
- virtual ~CameraPoseProcessor () {}
+ virtual ~CameraPoseProcessor () = default;
/// process the camera pose, this method is called at every frame.
virtual void
// Color every point
if (nr_points != static_cast<vtkIdType>(rgb_->size ()))
- std::fill (colors, colors + nr_points * 3, static_cast<unsigned char> (0xFF));
+ std::fill_n (colors, nr_points * 3, static_cast<unsigned char> (0xFF));
else
for (vtkIdType cp = 0; cp < nr_points; ++cp)
{
set(DEFAULT TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
*/
ColorVolume(const TsdfVolume& tsdf, int max_weight = -1);
- /** \brief Destructor */
- ~ColorVolume();
-
/** \brief Resets color volume to uninitialized state */
void
reset();
/** \brief Default constructor */
MarchingCubes();
- /** \brief Destructor */
- ~MarchingCubes();
-
/** \brief Runs marching cubes triangulation.
* \param[in] tsdf
* \param[in] triangles_buffer Buffer for triangles. Its size determines max extracted triangles. If empty, it will be allocated with default size will be used.
* \param[in] cy principal point y
*/
RayCaster(int rows = 480, int cols = 640, float fx = 525.f, float fy = 525.f, float cx = -1, float cy = -1);
-
- ~RayCaster();
/** \brief Sets camera intrinsics */
void
/** Constructor */
ScreenshotManager();
- /** Destructor */
- ~ScreenshotManager(){}
-
/** \brief Sets Depth camera intrinsics
* \param[in] focal focal length x
* \param height
/** \brief Constructor
*/
StandaloneMarchingCubes (int voxels_x = 512, int voxels_y = 512, int voxels_z = 512, float volume_size = 3.0f);
-
- /** \brief Destructor
- */
- ~StandaloneMarchingCubes (){}
+
/** \brief Run marching cubes in a TSDF cloud and returns a PolygonMesh. Input X,Y,Z coordinates must be in indices of the TSDF volume grid, output is in meters.
* \param[in] cloud TSDF cloud with indices between [0 ... VOXELS_X][0 ... VOXELS_Y][0 ... VOXELS_Z]. Intensity value corresponds to the TSDF value in that coordinate.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-pcl::gpu::kinfuLS::ColorVolume::~ColorVolume()
-{
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
void
pcl::gpu::kinfuLS::ColorVolume::reset()
{
triTable_.upload(&triTable[0][0], 256 * 16);
}
-pcl::gpu::kinfuLS::MarchingCubes::~MarchingCubes() {}
-
DeviceArray<pcl::gpu::kinfuLS::MarchingCubes::PointType>
pcl::gpu::kinfuLS::MarchingCubes::run(const TsdfVolume& tsdf, DeviceArray<PointType>& triangles_buffer)
{
normal_map_.create(rows * 3, cols);
}
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-pcl::gpu::kinfuLS::RayCaster::~RayCaster()
-{
-
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::gpu::kinfuLS::RayCaster::setIntrinsics(float fx, float fy, float cx, float cy)
cloud.clear ();
cloud.reserve (10000);
- constexpr int DIVISOR = pcl::device::kinfuLS::DIVISOR; // SHRT_MAX;
+ constexpr int DIVISOR = pcl::device::kinfuLS::DIVISOR; // std::numeric_limits<short>::max();
#define FETCH(x, y, z) volume_host[(x) + (y) * volume_x + (z) * volume_y * volume_x]
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})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSUBSYS_NAME} PARENT_NAME ${SUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} OPT_DEPS ${SUBSUBSYS_OPT_DEPS} EXT_DEPS ${EXT_DEPS})
if(NOT build)
return()
// Color every point
if (nr_points != static_cast<vtkIdType>(rgb_->size ()))
- std::fill(colors, colors + nr_points * 3, (unsigned char)0xFF);
+ std::fill_n(colors, nr_points * 3, (unsigned char)0xFF);
else
for (vtkIdType cp = 0; cp < nr_points; ++cp)
{
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
mark_as_advanced("BUILD_${SUBSYS_NAME}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
if(NOT build)
#ifndef _PCL_GPU_OCTREE_
#define _PCL_GPU_OCTREE_
+#include <limits>
#include <vector>
#include <pcl/memory.h>
* \param[out] out indeces of points within give sphere
* \param[in] max_nn maximum numver of results returned
*/
- void radiusSearchHost(const PointType& center, float radius, std::vector<int>& out, int max_nn = INT_MAX);
+ void radiusSearchHost(const PointType& center, float radius, std::vector<int>& out,
+ int max_nn = std::numeric_limits<int>::max());
/** \brief Performs approximate nearest neighbor search on CPU. It call \a internalDownload if necessary
* \param[in] query 3D point for which neighbour is be fetched
#include "cuda.h"
-using namespace thrust;
-
namespace pcl
{
namespace device
InSphere cond(query.x, query.y, query.z, radius);
- device_ptr<const PointType> cloud_ptr((const PointType*)cloud.ptr());
- device_ptr<int> res_ptr(buffer.ptr());
+ thrust::device_ptr<const PointType> cloud_ptr((const PointType*)cloud.ptr());
+ thrust::device_ptr<int> res_ptr(buffer.ptr());
- counting_iterator<int> first(0);
- counting_iterator<int> last = first + cloud.size();
+ thrust::counting_iterator<int> first(0);
+ thrust::counting_iterator<int> last = first + cloud.size();
//main bottle neck is a kernel call overhead/allocs
//work time for 871k points ~0.8ms
* Author: Anatoly Baskeheev, Itseez Ltd, (myname.mysurname@mycompany.com)
*/
-#include <cfloat>
+#include <limits>
#include "internal.hpp"
#include "pcl/gpu/utils/timers_cuda.hpp"
#include "pcl/gpu/utils/device/funcattrib.hpp"
#include "pcl/gpu/utils/device/algorithm.hpp"
-#include "pcl/gpu/utils/device/static_check.hpp"
#include "utils/scan_block.hpp"
#include "utils/morton.hpp"
#include <thrust/device_ptr.h>
using namespace pcl::gpu;
-using namespace thrust;
namespace pcl
{
__device__ __forceinline__ void operator()() const
{
//32 is a performance penalty step for search
- Static<(max_points_per_leaf % 32) == 0>::check();
+ static_assert((max_points_per_leaf % 32) == 0, "max_points_per_leaf must be a multiple of 32");
if (threadIdx.x == 0)
{
// 3 * sizeof(int) => +1 row
const int transaction_size = 128 / sizeof(int);
- int cols = max<int>(points_num, transaction_size * 4);
+ int cols = std::max<int>(points_num, transaction_size * 4);
int rows = 10 + 1; // = 13
storage.create(rows, cols);
{
//ScopeTimer timer("reduce-morton-sort-permutations");
- device_ptr<PointType> beg(points.ptr());
- device_ptr<PointType> end = beg + points.size();
+ thrust::device_ptr<PointType> beg(points.ptr());
+ thrust::device_ptr<PointType> end = beg + points.size();
{
PointType atmax, atmin;
- atmax.x = atmax.y = atmax.z = FLT_MAX;
- atmin.x = atmin.y = atmin.z = -FLT_MAX;
+ atmax.x = atmax.y = atmax.z = std::numeric_limits<float>::max();
+ atmin.x = atmin.y = atmin.z = std::numeric_limits<float>::lowest();
atmax.w = atmin.w = 0;
//ScopeTimer timer("reduce");
octreeGlobal.maxp = make_float3(maxp.x, maxp.y, maxp.z);
}
- device_ptr<int> codes_beg(codes.ptr());
- device_ptr<int> codes_end = codes_beg + codes.size();
+ thrust::device_ptr<int> codes_beg(codes.ptr());
+ thrust::device_ptr<int> codes_end = codes_beg + codes.size();
{
//ScopeTimer timer("morton");
thrust::transform(beg, end, codes_beg, CalcMorton(octreeGlobal.minp, octreeGlobal.maxp));
}
- device_ptr<int> indices_beg(indices.ptr());
- device_ptr<int> indices_end = indices_beg + indices.size();
+ thrust::device_ptr<int> indices_beg(indices.ptr());
+ thrust::device_ptr<int> indices_end = indices_beg + indices.size();
{
//ScopeTimer timer("sort");
thrust::sequence(indices_beg, indices_end);
}
{
- device_ptr<float> xs(points_sorted.ptr(0));
- device_ptr<float> ys(points_sorted.ptr(1));
- device_ptr<float> zs(points_sorted.ptr(2));
+ thrust::device_ptr<float> xs(points_sorted.ptr(0));
+ thrust::device_ptr<float> ys(points_sorted.ptr(1));
+ thrust::device_ptr<float> zs(points_sorted.ptr(2));
//ScopeTimer timer("perm2");
thrust::transform(make_permutation_iterator(beg, indices_beg),
make_permutation_iterator(end, indices_end),
static void get_gpu_arch_compiled_for(int& bin, int& ptr);
OctreeImpl() {};
- ~OctreeImpl() {};
void setCloud(const PointCloud& input_points);
void build();
#include "internal.hpp"
#include "cuda_runtime.h"
-#include <pcl/gpu/utils/device/static_check.hpp>
#include <pcl/exceptions.h>
#include<cassert>
pcl::gpu::Octree::Octree() : cloud_(nullptr), impl(nullptr)
{
- Static<sizeof(PointType) == sizeof(OctreeImpl::PointType)>::check();
+ static_assert(sizeof(PointType) == sizeof(OctreeImpl::PointType), "Point sizes do not match");
int device;
cudaSafeCall( cudaGetDevice( &device ) );
query_local.y = query.y;
query_local.z = query.z;
- Static<sizeof(PointType) == sizeof(OctreeImpl::PointType)>::check();
+ static_assert(sizeof(PointType) == sizeof(OctreeImpl::PointType), "Point sizes do not match");
PointCloud cloud_local((PointType*)cloud.ptr(), cloud.size());
bruteForceRadiusSearch(cloud_local, query_local, radius, result, buffer);
set(build FALSE)
PCL_SUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSYS_DESC} OFF)
-PCL_SUBSYS_DEPEND(build ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
mark_as_advanced("BUILD_${SUBSYS_NAME}")
PCL_ADD_DOC("${SUBSYS_NAME}")
ProbabilityProcessor::Ptr probability_processor_;
/** \brief Class constructor. */
- PeopleDetector ();
-
- /** \brief Class destructor. */
- ~PeopleDetector () {}
+ PeopleDetector ();
/** \brief User must set non standard intrinsics */
void
class NCV_EXPORTS INCVMemAllocator
{
public:
- virtual ~INCVMemAllocator() = 0;
+ virtual ~INCVMemAllocator() = default;
virtual NCVStatus alloc(NCVMemSegment &seg, std::size_t size) = 0;
virtual NCVStatus dealloc(NCVMemSegment &seg) = 0;
virtual std::size_t maxSize() const = 0;
};
-inline INCVMemAllocator::~INCVMemAllocator() {}
-
-
/**
* NCVMemStackAllocator
*/
clear();
}
- virtual ~NCVVector() {}
-
void clear()
{
_ptr = nullptr;
clear();
}
- virtual ~NCVMatrix() {}
-
void clear()
{
_ptr = nullptr;
#ifndef _ncv_pixel_operations_hpp_
#define _ncv_pixel_operations_hpp_
-#include <limits.h>
-#include <float.h>
+#include <limits>
#include "NCV.hpp"
template<typename TBase> inline __host__ __device__ TBase _pixMaxVal();
-template<> inline __host__ __device__ Ncv8u _pixMaxVal<Ncv8u>() {return UCHAR_MAX;}
-template<> inline __host__ __device__ Ncv16u _pixMaxVal<Ncv16u>() {return USHRT_MAX;}
-template<> inline __host__ __device__ Ncv32u _pixMaxVal<Ncv32u>() {return UINT_MAX;}
-template<> inline __host__ __device__ Ncv8s _pixMaxVal<Ncv8s>() {return SCHAR_MAX;}
-template<> inline __host__ __device__ Ncv16s _pixMaxVal<Ncv16s>() {return SHRT_MAX;}
-template<> inline __host__ __device__ Ncv32s _pixMaxVal<Ncv32s>() {return INT_MAX;}
-template<> inline __host__ __device__ Ncv32f _pixMaxVal<Ncv32f>() {return FLT_MAX;}
-template<> inline __host__ __device__ Ncv64f _pixMaxVal<Ncv64f>() {return DBL_MAX;}
+template<> inline __host__ __device__ Ncv8u _pixMaxVal<Ncv8u>() {return std::numeric_limits<unsigned char>::max();}
+template<> inline __host__ __device__ Ncv16u _pixMaxVal<Ncv16u>() {return std::numeric_limits<unsigned short>::max();}
+template<> inline __host__ __device__ Ncv32u _pixMaxVal<Ncv32u>() {return std::numeric_limits<unsigned int>::max();}
+template<> inline __host__ __device__ Ncv8s _pixMaxVal<Ncv8s>() {return std::numeric_limits<signed char>::max();}
+template<> inline __host__ __device__ Ncv16s _pixMaxVal<Ncv16s>() {return std::numeric_limits<short>::max();}
+template<> inline __host__ __device__ Ncv32s _pixMaxVal<Ncv32s>() {return std::numeric_limits<int>::max();}
+template<> inline __host__ __device__ Ncv32f _pixMaxVal<Ncv32f>() {return std::numeric_limits<float>::max();}
+template<> inline __host__ __device__ Ncv64f _pixMaxVal<Ncv64f>() {return std::numeric_limits<double>::max();}
template<typename TBase> inline __host__ __device__ TBase _pixMinVal();
template<> inline __host__ __device__ Ncv8u _pixMinVal<Ncv8u>() {return 0;}
template<> inline __host__ __device__ Ncv16u _pixMinVal<Ncv16u>() {return 0;}
template<> inline __host__ __device__ Ncv32u _pixMinVal<Ncv32u>() {return 0;}
-template<> inline __host__ __device__ Ncv8s _pixMinVal<Ncv8s>() {return SCHAR_MIN;}
-template<> inline __host__ __device__ Ncv16s _pixMinVal<Ncv16s>() {return SHRT_MIN;}
-template<> inline __host__ __device__ Ncv32s _pixMinVal<Ncv32s>() {return INT_MIN;}
-template<> inline __host__ __device__ Ncv32f _pixMinVal<Ncv32f>() {return FLT_MIN;}
-template<> inline __host__ __device__ Ncv64f _pixMinVal<Ncv64f>() {return DBL_MIN;}
+template<> inline __host__ __device__ Ncv8s _pixMinVal<Ncv8s>() {return std::numeric_limits<signed char>::min();}
+template<> inline __host__ __device__ Ncv16s _pixMinVal<Ncv16s>() {return std::numeric_limits<short>::min();}
+template<> inline __host__ __device__ Ncv32s _pixMinVal<Ncv32s>() {return std::numeric_limits<int>::min();}
+template<> inline __host__ __device__ Ncv32f _pixMinVal<Ncv32f>() {return std::numeric_limits<float>::min();}
+template<> inline __host__ __device__ Ncv64f _pixMinVal<Ncv64f>() {return std::numeric_limits<double>::min();}
template<typename Tvec> struct TConvVec2Base;
template<> struct TConvVec2Base<uchar1> {using TBase = Ncv8u;};
//TODO: consider using CUDA intrinsics to avoid branching
template<typename Tin> static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv8u &out) {out = (Ncv8u)CLAMP_0_255(a);};
-template<typename Tin> static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv16u &out) {out = (Ncv16u)CLAMP(a, 0, USHRT_MAX);}
-template<typename Tin> static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv32u &out) {out = (Ncv32u)CLAMP(a, 0, UINT_MAX);}
+template<typename Tin> static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv16u &out) {out = (Ncv16u)CLAMP(a, 0, std::numeric_limits<unsigned short>::max());}
+template<typename Tin> static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv32u &out) {out = (Ncv32u)CLAMP(a, 0, std::numeric_limits<unsigned int>::max());}
template<typename Tin> static inline __host__ __device__ void _TDemoteClampZ(Tin &a, Ncv32f &out) {out = (Ncv32f)a;}
//TODO: consider using CUDA intrinsics to avoid branching
template<typename Tin> static inline __host__ __device__ void _TDemoteClampNN(Tin &a, Ncv8u &out) {out = (Ncv8u)CLAMP_0_255(a+0.5f);}
-template<typename Tin> static inline __host__ __device__ void _TDemoteClampNN(Tin &a, Ncv16u &out) {out = (Ncv16u)CLAMP(a+0.5f, 0, USHRT_MAX);}
-template<typename Tin> static inline __host__ __device__ void _TDemoteClampNN(Tin &a, Ncv32u &out) {out = (Ncv32u)CLAMP(a+0.5f, 0, UINT_MAX);}
+template<typename Tin> static inline __host__ __device__ void _TDemoteClampNN(Tin &a, Ncv16u &out) {out = (Ncv16u)CLAMP(a+0.5f, 0, std::numeric_limits<unsigned short>::max());}
+template<typename Tin> static inline __host__ __device__ void _TDemoteClampNN(Tin &a, Ncv32u &out) {out = (Ncv32u)CLAMP(a+0.5f, 0, std::numeric_limits<unsigned int>::max());}
template<typename Tin> static inline __host__ __device__ void _TDemoteClampNN(Tin &a, Ncv32f &out) {out = (Ncv32f)a;}
template<typename Tout> inline Tout _pixMakeZero();
*/
+#include <algorithm>
#include <vector>
#include <cuda_runtime.h>
#include "NPP_staging.hpp"
-
texture<Ncv8u, 1, cudaReadModeElementType> tex8u;
texture<Ncv32u, 1, cudaReadModeElementType> tex32u;
texture<uint2, 1, cudaReadModeElementType> tex64u;
Ncv32u WidthII = roiSize.width + 1;
Ncv32u HeightII = roiSize.height + 1;
- memset(h_dst, 0, WidthII * sizeof(Ncv32u));
+ std::fill_n(h_dst, WidthII, 0);
for (Ncv32u i=1; i<HeightII; i++)
{
h_dst[i * dstStep] = 0;
Ncv32u WidthII = roiSize.width + 1;
Ncv32u HeightII = roiSize.height + 1;
- memset(h_dst, 0, WidthII * sizeof(Ncv32u));
+ std::fill_n(h_dst, WidthII, 0);
for (Ncv32u i=1; i<HeightII; i++)
{
h_dst[i * dstStep] = 0.0f;
Ncv32u WidthII = roiSize.width + 1;
Ncv32u HeightII = roiSize.height + 1;
- memset(h_dst, 0, WidthII * sizeof(Ncv64u));
+ std::fill_n(h_dst, WidthII, 0);
for (Ncv32u i=1; i<HeightII; i++)
{
h_dst[i * dstStep] = 0;
#include <pcl/gpu/utils/safe_call.hpp>
#include <pcl/point_types_conversion.h>
-#include <boost/foreach.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
public:
/** \brief Constructor with default values, allocates multilmap device memory **/
MultiTreeLiveProc(int def_rows = 480, int def_cols = 640) : multilmap (def_rows, def_cols) {}
- /** \brief Empty destructor **/
- ~MultiTreeLiveProc() {}
void
process (const Depth& dmap, Labels& lmap);
//PCL_DEBUG("[pcl::device::ProbabilityProc:ProbabilityProc] : (D) : Constructor called");
}
- /** \brief Default destructor **/
- ~ProbabilityProc() {}
-
/** \brief This will merge the votes from the different trees into one final vote, including probabilistic's **/
void
CUDA_SelectLabel ( const Depth& depth, Labels& labels, LabelProbability& probabilities);
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
/** \brief Empty constructor. */
EuclideanClusterExtraction() = default;
+ /** \brief Default virtual destructor. */
+ virtual ~EuclideanClusterExtraction() = default;
+
/** \brief the destructor */
/* ~EuclideanClusterExtraction ()
{
/** \brief Empty constructor. */
EuclideanLabeledClusterExtraction() = default;
+ /** \brief Default virtual destructor. */
+ virtual ~EuclideanLabeledClusterExtraction() = default;
+
/** \brief Provide a pointer to the search object.
* \param tree a pointer to the spatial search object.
*/
set(build FALSE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" OFF)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
PseudoConvexHull3D(std::size_t buffer_size);
- ~PseudoConvexHull3D();
void
reconstruct (const Cloud &points, Cloud &output);
*/
#include <pcl/gpu/surface/convex_hull.h>
-#include <pcl/gpu/utils/device/static_check.hpp>
#include "internal.h"
#include <pcl/exceptions.h>
struct pcl::gpu::PseudoConvexHull3D::Impl
{
Impl(std::size_t buffer_size) : fs(buffer_size) {}
- ~Impl() {};
device::FacetStream fs;
};
{
impl_.reset( new Impl(bsize) );
}
-pcl::gpu::PseudoConvexHull3D::~PseudoConvexHull3D() {}
-
void
pcl::gpu::PseudoConvexHull3D::reconstruct (const Cloud &cloud, DeviceArray2D<int>& vertexes)
#include <pcl/gpu/utils/device/algorithm.hpp>
#include <pcl/gpu/utils/device/warp.hpp>
-#include <pcl/gpu/utils/device/static_check.hpp>
//#include <pcl/gpu/utils/device/funcattrib.hpp>
#include <pcl/gpu/utils/safe_call.hpp>
#include <thrust/unique.h>
#include <thrust/gather.h>
-using namespace thrust;
-
namespace pcl
{
namespace device
template<typename It, typename Unary, typename Init, typename Binary>
int transform_reduce_index(It beg, It end, Unary unop, Init init, Binary binary)
{
- counting_iterator<int> cbeg(0);
- counting_iterator<int> cend = cbeg + thrust::distance(beg, end);
+ thrust::counting_iterator<int> cbeg(0);
+ thrust::counting_iterator<int> cend = cbeg + thrust::distance(beg, end);
thrust::tuple<float, int> t = transform_reduce(
make_zip_iterator(thrust::make_tuple(beg, cbeg)),
facets_dists.create(cloud_size);
perm.create(cloud_size);
- device_ptr<int> pbeg(perm.ptr());
+ thrust::device_ptr<int> pbeg(perm.ptr());
thrust::sequence(pbeg, pbeg + cloud_size);
}
void pcl::device::PointStream::computeInitalSimplex()
{
- device_ptr<const PointType> beg(cloud.ptr());
- device_ptr<const PointType> end = beg + cloud_size;
+ thrust::device_ptr<const PointType> beg(cloud.ptr());
+ thrust::device_ptr<const PointType> end = beg + cloud_size;
int minx = transform_reduce_min_index(beg, end, X());
int maxx = transform_reduce_max_index(beg, end, X());
simplex.x1 = tr(p1); simplex.x2 = tr(p2); simplex.x3 = tr(p3); simplex.x4 = tr(p4);
simplex.i1 = minx; simplex.i2 = maxx; simplex.i3 = maxl; simplex.i4 = maxp;
- float maxy = transform_reduce(beg, end, Y(), std::numeric_limits<float>::min(), maximum<float>());
- float miny = transform_reduce(beg, end, Y(), std::numeric_limits<float>::max(), minimum<float>());
+ float maxy = transform_reduce(beg, end, Y(), std::numeric_limits<float>::min(), thrust::maximum<float>());
+ float miny = transform_reduce(beg, end, Y(), std::numeric_limits<float>::max(), thrust::minimum<float>());
- float maxz = transform_reduce(beg, end, Z(), std::numeric_limits<float>::min(), maximum<float>());
- float minz = transform_reduce(beg, end, Z(), std::numeric_limits<float>::max(), minimum<float>());
+ float maxz = transform_reduce(beg, end, Z(), std::numeric_limits<float>::min(), thrust::maximum<float>());
+ float minz = transform_reduce(beg, end, Z(), std::numeric_limits<float>::max(), thrust::minimum<float>());
float dx = (p2.x - p1.x);
float dy = (maxy - miny);
}
//if (neg_count == 0)
- // then internal point ==>> idx = INT_MAX
+ // then internal point ==>> idx = std::numeric_limits<int>::max()
std::uint64_t res = idx;
res <<= 32;
}
// if (neg_count == 0)
- // new_idx = INT_MAX ==>> internal point
+ // new_idx = std::numeric_limits<int>::max() ==>> internal point
std::uint64_t res = new_idx;
res <<= 32;
{
output.create(indeces.size());
- //device_ptr<const PointType> in(points.ptr());
+ //thrust::device_ptr<const PointType> in(points.ptr());
//thrust::device_ptr<const int> mb(indeces.ptr());
//thrust::device_ptr<const int> me = mb + indeces.size();
- //device_ptr<PointType> out(output.ptr());
+ //thrust::device_ptr<PointType> out(output.ptr());
//thrust::gather(mb, me, in, out);
set(build FALSE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" OFF)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_SET_SUBSYS_INCLUDE_DIR("${SUBSYS_NAME}" "${SUBSYS_PATH}")
mark_as_advanced("BUILD_${SUBSYS_NAME}")
/*
-* Software License Agreement (BSD License)
-*
-* Copyright (c) 2011, Willow Garage, Inc.
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following
-* disclaimer in the documentation and/or other materials provided
-* with the distribution.
-* * Neither the name of Willow Garage, Inc. nor the names of its
-* contributors may be used to endorse or promote products derived
-* from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-* POSSIBILITY OF SUCH DAMAGE.
-*
-* Author: Anatoly Baskeheev, Itseez Ltd, (myname.mysurname@mycompany.com)
-*/
+ * Software License Agreement (BSD License)
+ *
+ * Copyright (c) 2011, Willow Garage, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Willow Garage, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Anatoly Baskeheev, Itseez Ltd, (myname.mysurname@mycompany.com)
+ */
+
+PCL_DEPRECATED_HEADER(1, 15, "pcl::device::Static will be removed at PCL release 1.15");
#ifndef PCL_GPU_DEVICE_STATIC_CHECK_HPP_
#define PCL_GPU_DEVICE_STATIC_CHECK_HPP_
-#if defined(__CUDACC__)
- #define __PCL_GPU_HOST_DEVICE__ __host__ __device__ __forceinline__
+#if defined(__CUDACC__)
+#define __PCL_GPU_HOST_DEVICE__ __host__ __device__ __forceinline__
#else
- #define __PCL_GPU_HOST_DEVICE__
-#endif
+#define __PCL_GPU_HOST_DEVICE__
+#endif
+
+namespace pcl {
+namespace device {
+template <bool expr>
+struct Static {};
-namespace pcl
+template <>
+struct [[deprecated("This class will be replaced at PCL release 1.15 by "
+ "c++11's static_assert instead")]] Static<true>
{
- namespace device
- {
- template<bool expr> struct Static {};
-
- template<> struct Static<true>
- {
- __PCL_GPU_HOST_DEVICE__ static void check() {};
- };
- }
+ __PCL_GPU_HOST_DEVICE__ static void check(){};
+};
+} // namespace device
- namespace gpu
- {
- using pcl::device::Static;
- }
+namespace gpu {
+using pcl::device::Static;
}
+} // namespace pcl
#undef __PCL_GPU_HOST_DEVICE__
-#endif /* PCL_GPU_DEVICE_STATIC_CHECK_HPP_ */
\ No newline at end of file
+#endif /* PCL_GPU_DEVICE_STATIC_CHECK_HPP_ */
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 EXT_DEPS ${SUBSYS_EXT_DEPS})
+ PCL_SUBSYS_DEPEND(build NAME ${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 EXT_DEPS ${SUBSYS_EXT_DEPS})
+ PCL_SUBSYS_DEPEND(build NAME ${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}")
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)
+ if(${VTK_VERSION} VERSION_LESS 8.0)
+ target_link_libraries("${LIB_NAME}" vtkIOMPIImage vtkIOMPIParallel)
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 7.0)
+ target_link_libraries("${LIB_NAME}" vtkFiltersParallelDIY2)
+ endif()
+ else()
+ target_link_libraries("${LIB_NAME}" vtkImagingCore)
endif()
endif()
endif()
target_link_libraries("${LIB_NAME}" ${PCAP_LIBRARIES})
endif()
-set(EXT_DEPS boost eigen3)
+set(EXT_DEPS eigen3) # Although this depends on boost, that cannot be specified here because there is no boost.pc
if(WITH_OPENNI)
list(APPEND EXT_DEPS libopenni)
/** \brief Empty class constructor. */
virtual
- ~ColorCoding ()
- {
- }
+ ~ColorCoding () = default;
/** \brief Define color bit depth of encoded color information.
* \param bitDepth_arg: amounts of bits for representing one color component
}
- const uindex_t len = static_cast<uindex_t> (indexVector_arg.size());
+ const auto len = static_cast<uindex_t> (indexVector_arg.size());
// calculated average color information
if (len > 1)
{
}
- const uindex_t len = static_cast<uindex_t> (indexVector_arg.size());
+ const auto len = static_cast<uindex_t> (indexVector_arg.size());
if (len > 1)
{
unsigned char diffRed;
assert (beginIdx_arg <= endIdx_arg);
// amount of points to be decoded
- unsigned int pointCount = static_cast<unsigned int> (endIdx_arg - beginIdx_arg);
+ auto pointCount = static_cast<unsigned int> (endIdx_arg - beginIdx_arg);
// iterate over points
for (std::size_t i = 0; i < pointCount; i++)
public:
/** \brief Empty constructor. */
- AdaptiveRangeCoder ()
- {
- }
+ AdaptiveRangeCoder () = default;
/** \brief Empty deconstructor. */
virtual
- ~AdaptiveRangeCoder ()
- {
- }
+ ~AdaptiveRangeCoder () = default;
/** \brief Encode char vector to output stream
* \param inputByteVector_arg input vector
/** \brief Empty deconstructor. */
virtual
- ~StaticRangeCoder ()
- {
- }
+ ~StaticRangeCoder () = default;
/** \brief Encode integer vector to output stream
* \param[in] inputIntVector_arg input vector
* Added optimized symbol lookup and fixed/static frequency tables
*
*/
-
-#ifndef __PCL_IO_RANGECODING__HPP
-#define __PCL_IO_RANGECODING__HPP
+#pragma once
#include <pcl/compression/entropy_range_coder.h>
#include <iostream>
const DWord bottom = static_cast<DWord> (1) << 16;
const DWord maxRange = static_cast<DWord> (1) << 16;
- unsigned int input_size = static_cast<unsigned> (inputByteVector_arg.size ());
+ auto input_size = static_cast<unsigned> (inputByteVector_arg.size ());
// init output vector
outputCharVector_.clear ();
const DWord bottom = static_cast<DWord> (1) << 16;
const DWord maxRange = static_cast<DWord> (1) << 16;
- unsigned int output_size = static_cast<unsigned> (outputByteVector_arg.size ());
+ auto output_size = static_cast<unsigned> (outputByteVector_arg.size ());
unsigned long streamByteCount = 0;
const std::uint64_t bottom = static_cast<std::uint64_t> (1) << 48;
const std::uint64_t maxRange = static_cast<std::uint64_t> (1) << 48;
- unsigned long input_size = static_cast<unsigned long> (inputIntVector_arg.size ());
+ auto input_size = static_cast<unsigned long> (inputIntVector_arg.size ());
// init output vector
outputCharVector_.clear ();
}
// init new frequency range with zero
- memset (&cFreqTable_[static_cast<std::size_t> (oldfrequencyTableSize + 1)], 0,
- sizeof(std::uint64_t) * static_cast<std::size_t> (frequencyTableSize - oldfrequencyTableSize));
+ std::fill_n(&cFreqTable_[oldfrequencyTableSize + 1],
+ frequencyTableSize - oldfrequencyTableSize, 0);
}
cFreqTable_[inputSymbol + 1]++;
}
}
// calculate amount of bytes per frequency table entry
- std::uint8_t frequencyTableByteSize = static_cast<std::uint8_t> (std::ceil (
+ auto frequencyTableByteSize = static_cast<std::uint8_t> (std::ceil (
std::log2 (static_cast<double> (cFreqTable_[static_cast<std::size_t> (frequencyTableSize - 1)] + 1)) / 8.0));
// write size of frequency table to output stream
readPos = 0;
std::uint64_t low = 0;
- std::uint64_t range = static_cast<std::uint64_t> (-1);
+ auto range = static_cast<std::uint64_t> (-1);
// start encoding
while (readPos < input_size)
}
// init with zero
- memset (&cFreqTable_[0], 0, sizeof(std::uint64_t) * static_cast<std::size_t> (frequencyTableSize));
+ std::fill(cFreqTable_.begin(), cFreqTable_.end(), 0);
// read cumulative frequency table
for (std::uint64_t f = 1; f < frequencyTableSize; f++)
// initialize range & code
std::uint64_t code = 0;
std::uint64_t low = 0;
- std::uint64_t range = static_cast<std::uint64_t> (-1);
+ auto range = static_cast<std::uint64_t> (-1);
// init code vector
for (unsigned int i = 0; i < 8; i++)
outputCharVector_.clear ();
outputCharVector_.reserve (sizeof(char) * input_size);
- std::uint64_t FreqHist[257];
+ std::uint64_t FreqHist[257]{};
// calculate frequency table
- memset (FreqHist, 0, sizeof(FreqHist));
unsigned int readPos = 0;
while (readPos < input_size)
{
- std::uint8_t symbol = static_cast<std::uint8_t> (inputByteVector_arg[readPos++]);
+ auto symbol = static_cast<std::uint8_t> (inputByteVector_arg[readPos++]);
FreqHist[symbol + 1]++;
}
return (streamByteCount);
}
-#endif
-
const PointCloudConstPtr &cloud_arg,
std::ostream& compressed_tree_data_out_arg)
{
- unsigned char recent_tree_depth =
+ auto recent_tree_depth =
static_cast<unsigned char> (this->getTreeDepth ());
// initialize octree
for (std::size_t i = 0; i < cloud_size; ++i, ++depth_ptr, color_ptr += sizeof(std::uint8_t) * 3)
{
- if (!(*depth_ptr) || (*depth_ptr==0x7FF))
- memset(color_ptr, 0, sizeof(std::uint8_t)*3);
+ if (!(*depth_ptr) || (*depth_ptr==0x7FF)) {
+ std::fill_n(color_ptr, 3, 0);
+ }
}
// Compress disparity information
// grayscale conversion
for (std::size_t i = 0; i < size; ++i)
{
- std::uint8_t grayvalue = static_cast<std::uint8_t>(0.2989 * static_cast<float>(colorImage_arg[i*3+0]) +
+ auto grayvalue = static_cast<std::uint8_t>(0.2989 * static_cast<float>(colorImage_arg[i*3+0]) +
0.5870 * static_cast<float>(colorImage_arg[i*3+1]) +
0.1140 * static_cast<float>(colorImage_arg[i*3+2]));
monoImage.push_back(grayvalue);
/** \brief Empty deconstructor. */
- ~OctreePointCloudCompression ()
- {
- }
+ ~OctreePointCloudCompression () override = default;
/** \brief Initialize globals */
void initialization () {
/** \brief Decode point cloud from input stream
* \param compressed_tree_data_in_arg: binary input stream containing compressed data
* \param cloud_arg: reference to decoded point cloud
+ * \warning This function is blocking until there is data available from the input stream. If the stream never contains any data, this will hang forever!
*/
void
decodePointCloud (std::istream& compressed_tree_data_in_arg, PointCloudPtr &cloud_arg);
using PointCloudConstPtr = typename PointCloud::ConstPtr;
/** \brief Empty Constructor. */
- OrganizedPointCloudCompression ()
- {
- }
+ OrganizedPointCloudCompression () = default;
/** \brief Empty deconstructor. */
- virtual ~OrganizedPointCloudCompression ()
- {
- }
+ virtual ~OrganizedPointCloudCompression () = default;
/** \brief Encode point cloud to output stream
* \param[in] cloud_arg: point cloud to be compressed
if (pcl::isFinite (point))
{
// Inverse depth quantization
- std::uint16_t disparity = static_cast<std::uint16_t> ( focalLength_arg / (disparityScale_arg * point.z) + disparityShift_arg / disparityScale_arg);
+ auto disparity = static_cast<std::uint16_t> ( focalLength_arg / (disparityScale_arg * point.z) + disparityShift_arg / disparityScale_arg);
disparityData_arg.push_back (disparity);
}
else
if (convertToMono)
{
// Encode point color
- std::uint8_t grayvalue = static_cast<std::uint8_t>(0.2989 * point.r
+ auto grayvalue = static_cast<std::uint8_t>(0.2989 * point.r
+ 0.5870 * point.g
+ 0.1140 * point.b);
}
// Inverse depth quantization
- std::uint16_t disparity = static_cast<std::uint16_t> (focalLength_arg / (disparityScale_arg * point.z) + disparityShift_arg / disparityScale_arg);
+ auto disparity = static_cast<std::uint16_t> (focalLength_arg / (disparityScale_arg * point.z) + disparityShift_arg / disparityScale_arg);
// Encode disparity
disparityData_arg.push_back (disparity);
/** \brief Empty class constructor. */
virtual
- ~PointCoding ()
- {
- }
+ ~PointCoding () = default;
/** \brief Define precision of point information
* \param precision_arg: precision
{
public:
ASCIIReader ();
- ~ASCIIReader ();
+ ~ASCIIReader () override;
using FileReader::read;
/* Load only the meta information (number of points, their types, etc),
setExtension (const std::string &ext) { extension_ = ext; }
protected:
- std::string sep_chars_;
- std::string extension_;
+ std::string sep_chars_{", \n\r\t"};
+ std::string extension_{".txt"};
std::vector<pcl::PCLPointField> fields_;
- std::string name_;
+ std::string name_{"AsciiReader"};
/** \brief Parses token based on field type.
SingleBuffer (std::size_t size);
- ~SingleBuffer ();
+ ~SingleBuffer () override;
T
operator[] (std::size_t idx) const override;
MedianBuffer (std::size_t size, unsigned char window_size);
- ~MedianBuffer ();
+ ~MedianBuffer () override;
/** Access an element at a given index.
*
AverageBuffer (std::size_t size, unsigned char window_size);
- ~AverageBuffer ();
+ ~AverageBuffer () override;
/** Access an element at a given index.
*
DinastGrabber (const int device_position=1);
/** \brief Destructor. It never throws. */
- ~DinastGrabber () noexcept;
+ ~DinastGrabber () noexcept override;
/** \brief Check if the grabber is running
* \return true if grabber is running / streaming. False otherwise.
EnsensoGrabber ();
/** @brief Destructor inherited from the Grabber interface. It never throws. */
- virtual
- ~EnsensoGrabber () noexcept;
+
+ ~EnsensoGrabber () noexcept override;
/** @brief Searches for available devices
* @returns The number of Ensenso devices connected */
/** @brief Start the point cloud and or image acquisition
* @note Opens device "0" if no device is open */
void
- start ();
+ start () override;
/** @brief Stop the data acquisition */
void
- stop ();
+ stop () override;
/** @brief Check if the data acquisition is still running
* @return True if running, false otherwise */
bool
- isRunning () const;
+ isRunning () const override;
/** @brief Check if a TCP port is opened
* @return True if open, false otherwise */
/** @brief Get class name
* @returns A string containing the class name */
std::string
- getName () const;
+ getName () const override;
/** @brief Configure Ensenso capture settings
* @param[in] auto_exposure If set to yes, the exposure parameter will be ignored
/** @brief Obtain the number of frames per second (FPS) */
float
- getFramesPerSecond () const;
+ getFramesPerSecond () const override;
/** @brief Open TCP port to enable access via the [nxTreeEdit](http://www.ensenso.de/manual/software_components.htm) program.
* @param[in] port The port number
* @warning If you do not close the TCP port the program might exit with the port still open, if it is the case
* use @code ps -ef @endcode and @code kill PID @endcode to kill the application and effectively close the port. */
bool
- closeTcpPort (void);
+ closeTcpPort ();
/** @brief Returns the full NxLib tree as a JSON string
* @param[in] pretty_format JSON formatting style
public:
/** \brief Empty destructor */
- virtual ~FileGrabber () {}
+ virtual ~FileGrabber () = default;
/** \brief operator[] Returns the idx-th cloud in the dataset, without bounds checking.
* Note that in the future, this could easily be modified to do caching
{
public:
/** \brief empty constructor */
- FileReader() {}
+ FileReader() = default;
/** \brief empty destructor */
- virtual ~FileReader() {}
+ virtual ~FileReader() = default;
/** \brief Read a point cloud data header from a FILE file.
*
* Load only the meta information (number of points, their types, etc),
{
public:
/** \brief Empty constructor */
- FileWriter () {}
+ FileWriter () = default;
/** \brief Empty destructor */
- virtual ~FileWriter () {}
+ virtual ~FileWriter () = default;
/** \brief Save point cloud data to a FILE file containing n-D points
* \param[in] file_name the output file name
Grabber& operator=(Grabber&&) = default;
/** \brief virtual destructor. */
- #if defined(_MSC_VER)
- virtual inline ~Grabber () noexcept {}
- #else
- virtual inline ~Grabber () noexcept = default;
- #endif
+ virtual inline ~Grabber () noexcept = default;
/** \brief registers a callback function/method to a signal with the corresponding signature
* \param[in] callback: the callback function/method
/** \brief virtual Destructor inherited from the Grabber interface. It never throws. */
- ~HDLGrabber () noexcept;
+ ~HDLGrabber () noexcept override;
/** \brief Starts processing the Velodyne packets, either from the network or PCAP file. */
void
{
public:
/** Empty constructor */
- IFSReader () {}
+ IFSReader () = default;
/** Empty destructor */
- ~IFSReader () {}
+ ~IFSReader () = default;
/** \brief we support two versions
* 1.0 classic
class PCL_EXPORTS IFSWriter
{
public:
- IFSWriter() {}
- ~IFSWriter() {}
+ IFSWriter() = default;
+ ~IFSWriter() = default;
/** \brief Save point cloud data to an IFS file containing 3D points.
* \param[in] file_name the output file name
/**
* @brief virtual Destructor that never throws an exception.
*/
- inline virtual ~Image ()
- {}
+ inline virtual ~Image () = default;
/**
* @param[in] input_width width of input image
ImageGrabberBase (const std::vector<std::string>& depth_image_files, float frames_per_second, bool repeat);
/** \brief Virtual destructor. */
- ~ImageGrabberBase () noexcept;
+ ~ImageGrabberBase () noexcept override;
/** \brief Starts playing the list of PCD files if frames_per_second is > 0. Otherwise it works as a trigger: publishes only the next PCD file in the list. */
void
bool repeat = false);
/** \brief Empty destructor */
- ~ImageGrabber () noexcept {}
+ ~ImageGrabber () noexcept override = default;
// Inherited from FileGrabber
const typename pcl::PointCloud<PointT>::ConstPtr
IRImage (FrameWrapper::Ptr ir_metadata);
IRImage (FrameWrapper::Ptr ir_metadata, Timestamp time);
- ~IRImage () noexcept
- {}
+ ~IRImage () noexcept = default;
void
fillRaw (unsigned width, unsigned height, unsigned short* ir_buffer, unsigned line_step = 0) const;
ImageRGB24 (FrameWrapper::Ptr image_metadata);
ImageRGB24 (FrameWrapper::Ptr image_metadata, Timestamp timestamp);
- ~ImageRGB24 () noexcept;
+ ~ImageRGB24 () noexcept override;
inline Encoding
getEncoding () const override
ImageYUV422 (FrameWrapper::Ptr image_metadata);
ImageYUV422 (FrameWrapper::Ptr image_metadata, Timestamp timestamp);
- ~ImageYUV422 () noexcept;
+ ~ImageYUV422 () noexcept override;
inline Encoding
getEncoding () const override
// Remove empty fields and adjust offset
int offset =0;
- for (std::vector<pcl::PCLPointField>::iterator field_iter = fields_.begin ();
+ for (auto field_iter = fields_.begin ();
field_iter != fields_.end (); ++field_iter)
{
if (field_iter->name == "_")
#ifndef PCL_IO_AUTO_IO_IMPL_H_
#define PCL_IO_AUTO_IO_IMPL_H_
+#include <pcl/io/obj_io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/io/ifs_io.h>
result = pcl::io::loadPLYFile (file_name, cloud);
else if (extension == ".ifs")
result = pcl::io::loadIFSFile (file_name, cloud);
+ else if (extension == ".obj")
+ result = pcl::io::loadOBJFile (file_name, cloud);
else
{
PCL_ERROR ("[pcl::io::load] Don't know how to handle file with extension %s\n", extension.c_str ());
template <typename T>
Buffer<T>::~Buffer ()
-{
-}
+= default;
template <typename T>
SingleBuffer<T>::SingleBuffer (std::size_t size)
template <typename T>
SingleBuffer<T>::~SingleBuffer ()
-{
-}
+= default;
template <typename T> T
SingleBuffer<T>::operator[] (std::size_t idx) const
template <typename T>
MedianBuffer<T>::~MedianBuffer ()
-{
-}
+= default;
template <typename T> T
MedianBuffer<T>::operator[] (std::size_t idx) const
template <typename T>
AverageBuffer<T>::~AverageBuffer ()
-{
-}
+= default;
template <typename T> T
AverageBuffer<T>::operator[] (std::size_t idx) const
cloud.resize (getWidth () * getHeight ());
int rgb_idx = 0;
- unsigned char *color_r = reinterpret_cast<unsigned char*> (&uncompressed_data[0]);
- unsigned char *color_g = reinterpret_cast<unsigned char*> (&uncompressed_data[getWidth () * getHeight ()]);
- unsigned char *color_b = reinterpret_cast<unsigned char*> (&uncompressed_data[2 * getWidth () * getHeight ()]);
+ auto *color_r = reinterpret_cast<unsigned char*> (&uncompressed_data[0]);
+ auto *color_g = reinterpret_cast<unsigned char*> (&uncompressed_data[getWidth () * getHeight ()]);
+ auto *color_b = reinterpret_cast<unsigned char*> (&uncompressed_data[2 * getWidth () * getHeight ()]);
for (std::size_t i = 0; i < cloud.size (); ++i, ++rgb_idx)
{
cloud.height = getHeight ();
cloud.resize (getWidth () * getHeight ());
- unsigned char *color_r = reinterpret_cast<unsigned char*> (&uncompressed_data[0]);
- unsigned char *color_g = reinterpret_cast<unsigned char*> (&uncompressed_data[getWidth () * getHeight ()]);
- unsigned char *color_b = reinterpret_cast<unsigned char*> (&uncompressed_data[2 * getWidth () * getHeight ()]);
+ auto *color_r = reinterpret_cast<unsigned char*> (&uncompressed_data[0]);
+ auto *color_g = reinterpret_cast<unsigned char*> (&uncompressed_data[getWidth () * getHeight ()]);
+ auto *color_b = reinterpret_cast<unsigned char*> (&uncompressed_data[2 * getWidth () * getHeight ()]);
#ifdef _OPENMP
#pragma omp parallel for \
cloud.resize (getWidth () * getHeight ());
int wh2 = getWidth () * getHeight () / 2;
- unsigned char *color_u = reinterpret_cast<unsigned char*> (&uncompressed_data[0]);
- unsigned char *color_y = reinterpret_cast<unsigned char*> (&uncompressed_data[wh2]);
- unsigned char *color_v = reinterpret_cast<unsigned char*> (&uncompressed_data[wh2 + getWidth () * getHeight ()]);
+ auto *color_u = reinterpret_cast<unsigned char*> (&uncompressed_data[0]);
+ auto *color_y = reinterpret_cast<unsigned char*> (&uncompressed_data[wh2]);
+ auto *color_v = reinterpret_cast<unsigned char*> (&uncompressed_data[wh2 + getWidth () * getHeight ()]);
int y_idx = 0;
for (int i = 0; i < wh2; ++i, y_idx += 2)
cloud.resize (getWidth () * getHeight ());
int wh2 = getWidth () * getHeight () / 2;
- unsigned char *color_u = reinterpret_cast<unsigned char*> (&uncompressed_data[0]);
- unsigned char *color_y = reinterpret_cast<unsigned char*> (&uncompressed_data[wh2]);
- unsigned char *color_v = reinterpret_cast<unsigned char*> (&uncompressed_data[wh2 + getWidth () * getHeight ()]);
+ auto *color_u = reinterpret_cast<unsigned char*> (&uncompressed_data[0]);
+ auto *color_y = reinterpret_cast<unsigned char*> (&uncompressed_data[wh2]);
+ auto *color_v = reinterpret_cast<unsigned char*> (&uncompressed_data[wh2 + getWidth () * getHeight ()]);
#ifdef _OPENMP
#pragma omp parallel for \
{
if (cloud.empty ())
{
- throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Input point cloud has no data!");
- return (-1);
+ PCL_WARN ("[pcl::PCDWriter::writeBinary] Input point cloud has no data!\n");
}
int data_idx = 0;
std::ostringstream oss;
#else
// Allocate disk space for the entire file to prevent bus errors.
- if (io::raw_fallocate (fd, data_idx + data_size) != 0)
+ const int allocate_res = io::raw_fallocate (fd, data_idx + data_size);
+ if (allocate_res != 0)
{
io::raw_close (fd);
resetLockingPermissions (file_name, file_lock);
- PCL_ERROR ("[pcl::PCDWriter::writeBinary] posix_fallocate errno: %d strerror: %s\n", errno, strerror (errno));
+ PCL_ERROR ("[pcl::PCDWriter::writeBinary] raw_fallocate(length=%zu) returned %i. errno: %d strerror: %s\n",
+ data_idx + data_size, allocate_res, errno, strerror (errno));
- throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during posix_fallocate ()!");
+ throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during raw_fallocate ()!");
return (-1);
}
{
if (cloud.empty ())
{
- throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Input point cloud has no data!");
- return (-1);
+ PCL_WARN ("[pcl::PCDWriter::writeBinaryCompressed] Input point cloud has no data!\n");
}
int data_idx = 0;
std::ostringstream oss;
}
char* temp_buf = static_cast<char*> (malloc (static_cast<std::size_t> (static_cast<float> (data_size) * 1.5f + 8.0f)));
+ unsigned int compressed_final_size = 0;
+ if (data_size != 0) {
// Compress the valid data
unsigned int compressed_size = pcl::lzfCompress (only_valid_data,
static_cast<std::uint32_t> (data_size),
&temp_buf[8],
static_cast<std::uint32_t> (static_cast<float>(data_size) * 1.5f));
- unsigned int compressed_final_size = 0;
- // Was the compression successful?
- if (compressed_size)
- {
- char *header = &temp_buf[0];
- memcpy (&header[0], &compressed_size, sizeof (unsigned int));
- memcpy (&header[4], &data_size, sizeof (unsigned int));
- data_size = compressed_size + 8;
- compressed_final_size = static_cast<std::uint32_t> (data_size) + data_idx;
+ // Was the compression successful?
+ if (compressed_size > 0)
+ {
+ char *header = &temp_buf[0];
+ memcpy (&header[0], &compressed_size, sizeof (unsigned int));
+ memcpy (&header[4], &data_size, sizeof (unsigned int));
+ data_size = compressed_size + 8;
+ compressed_final_size = static_cast<std::uint32_t> (data_size) + data_idx;
+ }
+ else
+ {
+ #ifndef _WIN32
+ io::raw_close (fd);
+ #endif
+ resetLockingPermissions (file_name, file_lock);
+ PCL_WARN("[pcl::PCDWriter::writeBinaryCompressed] Error during compression!\n");
+ return (-1);
+ }
}
else
{
-#ifndef _WIN32
- io::raw_close (fd);
-#endif
- resetLockingPermissions (file_name, file_lock);
- throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during compression!");
- return (-1);
+ // empty cloud case
+ compressed_final_size = 8 + data_idx;
+ auto *header = reinterpret_cast<std::uint32_t*>(&temp_buf[0]);
+ header[0] = 0; // compressed_size is 0
+ header[1] = 0; // data_size is 0
+ data_size = 8; // correct data_size to header size
}
// Prepare the map
#else
// Allocate disk space for the entire file to prevent bus errors.
- if (io::raw_fallocate (fd, compressed_final_size) != 0)
+ const int allocate_res = io::raw_fallocate (fd, compressed_final_size);
+ if (allocate_res != 0)
{
io::raw_close (fd);
resetLockingPermissions (file_name, file_lock);
- PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] posix_fallocate errno: %d strerror: %s\n", errno, strerror (errno));
+ PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] raw_fallocate(length=%u) returned %i. errno: %d strerror: %s\n",
+ compressed_final_size, allocate_res, errno, strerror (errno));
- throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during posix_fallocate ()!");
+ throw pcl::IOException ("[pcl::PCDWriter::writeBinaryCompressed] Error during raw_fallocate ()!");
return (-1);
}
{
if (cloud.empty ())
{
- throw pcl::IOException ("[pcl::PCDWriter::writeASCII] Input point cloud has no data!");
- return (-1);
+ PCL_WARN ("[pcl::PCDWriter::writeASCII] Input point cloud has no data!\n");
}
if (cloud.width * cloud.height != cloud.size ())
{
switch (fields[d].datatype)
{
+ case pcl::PCLPointField::BOOL:
+ {
+ bool value;
+ memcpy (&value, reinterpret_cast<const char*> (&point) + fields[d].offset + c * sizeof (bool), sizeof (bool));
+ stream << boost::numeric_cast<std::int32_t>(value);
+ break;
+ }
case pcl::PCLPointField::INT8:
{
std::int8_t value;
stream << boost::numeric_cast<std::uint32_t>(value);
break;
}
+ case pcl::PCLPointField::INT64:
+ {
+ std::int64_t value;
+ memcpy (&value, reinterpret_cast<const char*> (&point) + fields[d].offset + c * sizeof (std::int64_t), sizeof (std::int64_t));
+ stream << boost::numeric_cast<std::int64_t>(value);
+ break;
+ }
+ case pcl::PCLPointField::UINT64:
+ {
+ std::uint64_t value;
+ memcpy (&value, reinterpret_cast<const char*> (&point) + fields[d].offset + c * sizeof (std::uint64_t), sizeof (std::uint64_t));
+ stream << boost::numeric_cast<std::uint64_t>(value);
+ break;
+ }
case pcl::PCLPointField::FLOAT32:
{
/*
{
if (cloud.empty () || indices.empty ())
{
- throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Input point cloud has no data or empty indices given!");
- return (-1);
+ PCL_WARN ("[pcl::PCDWriter::writeBinary] Input point cloud has no data or empty indices given!\n");
}
int data_idx = 0;
std::ostringstream oss;
#else
// Allocate disk space for the entire file to prevent bus errors.
- if (io::raw_fallocate (fd, data_idx + data_size) != 0)
+ const int allocate_res = io::raw_fallocate (fd, data_idx + data_size);
+ if (allocate_res != 0)
{
io::raw_close (fd);
resetLockingPermissions (file_name, file_lock);
- PCL_ERROR ("[pcl::PCDWriter::writeBinary] posix_fallocate errno: %d strerror: %s\n", errno, strerror (errno));
+ PCL_ERROR ("[pcl::PCDWriter::writeBinary] raw_fallocate(length=%zu) returned %i. errno: %d strerror: %s\n",
+ data_idx + data_size, allocate_res, errno, strerror (errno));
- throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during posix_fallocate ()!");
+ throw pcl::IOException ("[pcl::PCDWriter::writeBinary] Error during raw_fallocate ()!");
return (-1);
}
{
if (cloud.empty () || indices.empty ())
{
- throw pcl::IOException ("[pcl::PCDWriter::writeASCII] Input point cloud has no data or empty indices given!");
- return (-1);
+ PCL_WARN ("[pcl::PCDWriter::writeASCII] Input point cloud has no data or empty indices given!\n");
}
if (cloud.width * cloud.height != cloud.size ())
{
switch (fields[d].datatype)
{
+ case pcl::PCLPointField::BOOL:
+ {
+ bool value;
+ memcpy (&value, reinterpret_cast<const char*> (&cloud.points[index]) + fields[d].offset + c * sizeof (bool), sizeof (bool));
+ stream << boost::numeric_cast<std::int32_t>(value);
+ break;
+ }
case pcl::PCLPointField::INT8:
{
std::int8_t value;
stream << boost::numeric_cast<std::uint32_t>(value);
break;
}
+ case pcl::PCLPointField::INT64:
+ {
+ std::int64_t value;
+ memcpy (&value, reinterpret_cast<const char*> (&cloud.points[index]) + fields[d].offset + c * sizeof (std::int64_t), sizeof (std::int64_t));
+ stream << boost::numeric_cast<std::int64_t>(value);
+ break;
+ }
+ case pcl::PCLPointField::UINT64:
+ {
+ std::uint64_t value;
+ memcpy (&value, reinterpret_cast<const char*> (&cloud.points[index]) + fields[d].offset + c * sizeof (std::uint64_t), sizeof (std::uint64_t));
+ stream << boost::numeric_cast<std::uint64_t>(value);
+ break;
+ }
case pcl::PCLPointField::FLOAT32:
{
/*
{
std::size_t size = img.encoding == "mono16" ? 2 : 3;
for (std::size_t i = 0; i < cloud.size (); ++i)
- if (!pcl::isFinite (cloud[i]))
- std::memset (&img.data[i * size], 0, size);
+ if (!pcl::isFinite (cloud[i])) {
+ std::fill_n(&img.data[i * size], size, 0);
+ }
}
return (result);
img.height = cloud.height;
img.step = img.width * sizeof (unsigned short);
img.data.resize (img.step * img.height);
- unsigned short* data = reinterpret_cast<unsigned short*>(&img.data[0]);
+ auto* data = reinterpret_cast<unsigned short*>(&img.data[0]);
for (std::size_t i = 0; i < cloud.size (); ++i)
{
std::uint32_t val;
img.height = cloud.height;
img.step = img.width * sizeof (unsigned short);
img.data.resize (img.step * img.height);
- unsigned short* data = reinterpret_cast<unsigned short*>(&img.data[0]);
+ auto* data = reinterpret_cast<unsigned short*>(&img.data[0]);
float scaling_factor = scaling_factor_;
float data_min = 0.0f;
unsigned line_number,
const std::string& message);
- ~IOException () noexcept;
+ ~IOException () noexcept override;
IOException&
operator= (const IOException& exception);
va_list args;
va_start (args, format);
vsnprintf (msg, 1024, format, args);
+ va_end (args);
throw IOException (function, file, line, msg);
}
} // namespace
# include <sys/mman.h>
# include <sys/types.h>
# include <sys/stat.h>
-# include <sys/fcntl.h>
+# include <fcntl.h>
# include <cerrno>
#endif
#include <cstddef>
// Android's libc doesn't have posix_fallocate.
if (::fallocate(fd, 0, 0, length) == 0)
return 0;
+
+ // fallocate returns -1 on error and sets errno
+ // EINVAL should indicate an unsupported filesystem.
+ // All other errors are passed up.
+ if (errno != EINVAL)
+ return -1;
# else
// Conforming POSIX systems have posix_fallocate.
- if (::posix_fallocate(fd, 0, length) == 0)
+ const int res = ::posix_fallocate(fd, 0, length);
+ if (res == 0)
return 0;
-# endif
+ // posix_fallocate does not set errno
// EINVAL should indicate an unsupported filesystem.
// All other errors are passed up.
- if (errno != EINVAL)
- return -1;
+ if (res != EINVAL)
+ return res;
+# endif
// Try to deal with unsupported filesystems by simply seeking + writing.
// This may not really allocate space, but the file size will be set.
* \param[in] in_data the input uncompressed buffer
* \param[in] in_len the length of the input buffer
* \param[out] out_data the output buffer where the compressed result will be stored
- * \param[out] out_len the length of the output buffer
+ * \param[in] out_len the length of the output buffer
*
*/
PCL_EXPORTS unsigned int
* \param[in] in_data the input compressed buffer
* \param[in] in_len the length of the input buffer
* \param[out] out_data the output buffer (must be resized to \a out_len)
- * \param[out] out_len the length of the output buffer
+ * \param[in] out_len the length of the output buffer
*/
PCL_EXPORTS unsigned int
lzfDecompress (const void *const in_data, unsigned int in_len,
/** Empty constructor */
LZFImageReader ();
/** Empty destructor */
- virtual ~LZFImageReader () {}
+ virtual ~LZFImageReader () = default;
/** \brief Read camera parameters from a given file and store them internally.
* \return true if operation successful, false otherwise
{}
/** Empty destructor */
- ~LZFDepth16ImageReader () {}
+ ~LZFDepth16ImageReader () override = default;
/** \brief Read the data stored in a PCLZF depth file and convert it to a pcl::PointCloud type.
* \param[in] filename the file name to read the data from
using LZFImageReader::readParameters;
/** Empty constructor */
- LZFRGB24ImageReader () {}
+ LZFRGB24ImageReader () = default;
/** Empty destructor */
- ~LZFRGB24ImageReader () {}
+ ~LZFRGB24ImageReader () override = default;
/** \brief Read the data stored in a PCLZF RGB file and convert it to a pcl::PointCloud type.
* \param[in] filename the file name to read the data from
using LZFRGB24ImageReader::readParameters;
/** Empty constructor */
- LZFYUV422ImageReader () {}
+ LZFYUV422ImageReader () = default;
/** Empty destructor */
- ~LZFYUV422ImageReader () {}
+ ~LZFYUV422ImageReader () override = default;
/** \brief Read the data stored in a PCLZF YUV422 16bit file and convert it to a pcl::PointCloud type.
* \param[in] filename the file name to read the data from
using LZFRGB24ImageReader::readParameters;
/** Empty constructor */
- LZFBayer8ImageReader () {}
+ LZFBayer8ImageReader () = default;
/** Empty destructor */
- ~LZFBayer8ImageReader () {}
+ ~LZFBayer8ImageReader () override = default;
/** \brief Read the data stored in a PCLZF Bayer 8bit file and convert it to a pcl::PointCloud type.
* \param[in] filename the file name to read the data from
{
public:
/** Empty constructor */
- LZFImageWriter () {}
+ LZFImageWriter () = default;
/** Empty destructor */
- virtual ~LZFImageWriter () {}
+ virtual ~LZFImageWriter () = default;
/** \brief Save an image into PCL-LZF format. Virtual.
* \param[in] data the array holding the image
{}
/** Empty destructor */
- ~LZFDepth16ImageWriter () {}
+ ~LZFDepth16ImageWriter () override = default;
/** \brief Save a 16-bit depth image into PCL-LZF format.
* \param[in] data the array holding the depth image
{
public:
/** Empty constructor */
- LZFRGB24ImageWriter () {}
+ LZFRGB24ImageWriter () = default;
/** Empty destructor */
- ~LZFRGB24ImageWriter () {}
+ ~LZFRGB24ImageWriter () override = default;
/** \brief Save a 24-bit RGB image into PCL-LZF format.
* \param[in] data the array holding the RGB image (as [RGB..RGB] or [BGR..BGR])
{
public:
/** Empty constructor */
- LZFYUV422ImageWriter () {}
+ LZFYUV422ImageWriter () = default;
/** Empty destructor */
- ~LZFYUV422ImageWriter () {}
+ ~LZFYUV422ImageWriter () override = default;
/** \brief Save a 16-bit YUV422 image into PCL-LZF format.
* \param[in] data the array holding the YUV422 image (as [YUYV...YUYV])
{
public:
/** Empty constructor */
- LZFBayer8ImageWriter () {}
+ LZFBayer8ImageWriter () = default;
/** Empty destructor */
- ~LZFBayer8ImageWriter () {}
+ ~LZFBayer8ImageWriter () override = default;
/** \brief Save a 8-bit Bayer image into PCL-LZF format.
* \param[in] data the array holding the 8-bit Bayer array
MTLReader ();
/** \brief empty destructor */
- virtual ~MTLReader() {}
+ virtual ~MTLReader() = default;
/** \brief Read a MTL file given its full path.
* \param[in] filename full path to MTL file
{
public:
/** \brief empty constructor */
- OBJReader() {}
+ OBJReader() = default;
/** \brief empty destructor */
- ~OBJReader() {}
+ ~OBJReader() override = default;
/** \brief Read a point cloud data header from a FILE file.
*
* Load only the meta information (number of points, their types, etc),
* \param[in] file_name the name of the file to write to disk
* \param[in] tex_mesh the texture mesh to save
* \param[in] precision the output ASCII precision
+ * \return 0 on success, else a negative number
* \ingroup io
*/
PCL_EXPORTS int
const pcl::TextureMesh &tex_mesh,
unsigned precision = 5);
- /** \brief Saves a PolygonMesh in ascii PLY format.
+ /** \brief Saves a PolygonMesh in ascii OBJ format.
* \param[in] file_name the name of the file to write to disk
* \param[in] mesh the polygonal mesh to save
* \param[in] precision the output ASCII precision default 5
ONIGrabber (const std::string& file_name, bool repeat, bool stream);
/** \brief destructor never throws an exception */
- ~ONIGrabber () noexcept;
+ ~ONIGrabber () noexcept override;
/** \brief For devices that are streaming, the streams are started by calling this method.
* Trigger-based devices, just trigger the device once for each call of start.
{
public:
- OpenNI2FrameListener ()
- {}
+ OpenNI2FrameListener () = default;
+
OpenNI2FrameListener (StreamCallbackFunction cb)
: callback_(std::move(cb)) {}
- ~OpenNI2FrameListener ()
- { };
+ ~OpenNI2FrameListener () override = default;
inline void
onNewFrame (openni::VideoStream& stream) override
/** \brief Constructor. */
ShiftToDepthConverter () : init_(false) {}
- /** \brief Destructor. */
- virtual ~ShiftToDepthConverter () {};
-
/** \brief This method generates a look-up table to convert openni shift values to depth
*/
void
const Mode& image_mode = OpenNI_Default_Mode);
/** \brief virtual Destructor inherited from the Grabber interface. It never throws. */
- ~OpenNI2Grabber () noexcept;
+ ~OpenNI2Grabber () noexcept override;
/** \brief Start the data acquisition. */
void
, shadow_value_ (shadow_value)
, no_sample_value_ (no_sample_value) { }
- DepthImage::~DepthImage () noexcept { }
+ DepthImage::~DepthImage () noexcept = default;
const xn::DepthMetaData&
DepthImage::getDepthMetaData () const throw ()
friend class OpenNIDriver;
public:
DeviceKinect (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& image_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node);
- ~DeviceKinect () noexcept;
+ ~DeviceKinect () noexcept override;
inline void setDebayeringMethod (const ImageBayerGRBG::DebayeringMethod& debayering_method) noexcept;
inline const ImageBayerGRBG::DebayeringMethod& getDebayeringMethod () const throw ();
using ConstPtr = pcl::shared_ptr<const DeviceONI>;
DeviceONI (xn::Context& context, const std::string& file_name, bool repeat = false, bool streaming = true);
- ~DeviceONI () noexcept;
+ ~DeviceONI () noexcept override;
void startImageStream () override;
void stopImageStream () override;
friend class OpenNIDriver;
public:
DevicePrimesense (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& image_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node);
- ~DevicePrimesense () noexcept;
+ ~DevicePrimesense () noexcept override;
//virtual void setImageOutputMode (const XnMapOutputMode& output_mode);
protected:
friend class OpenNIDriver;
public:
DeviceXtionPro (xn::Context& context, const xn::NodeInfo& device_node, const xn::NodeInfo& depth_node, const xn::NodeInfo& ir_node);
- ~DeviceXtionPro () noexcept;
+ ~DeviceXtionPro () noexcept override;
//virtual void setImageOutputMode (const XnMapOutputMode& output_mode);
protected:
/**
* @brief virtual Destructor that never throws an exception
*/
- ~OpenNIException () noexcept;
+ ~OpenNIException () noexcept override;
/**
* @brief Assignment operator to allow copying the message of another exception variable.
va_list args;
va_start (args, format);
vsprintf (msg, format, args);
+ va_end (args);
throw OpenNIException (function_name, file_name, line_number, msg);
}
} // namespace openni_camera
{
}
- Image::~Image () noexcept { }
+ Image::~Image () noexcept = default;
unsigned
Image::getWidth () const throw ()
};
ImageBayerGRBG (pcl::shared_ptr<xn::ImageMetaData> image_meta_data, DebayeringMethod method) noexcept;
- ~ImageBayerGRBG () noexcept;
+ ~ImageBayerGRBG () noexcept override;
inline Encoding
getEncoding () const override
public:
ImageRGB24 (pcl::shared_ptr<xn::ImageMetaData> image_meta_data) noexcept;
- ~ImageRGB24 () noexcept;
+ ~ImageRGB24 () noexcept override;
inline Encoding
getEncoding () const override
{
public:
ImageYUV422 (pcl::shared_ptr<xn::ImageMetaData> image_meta_data) noexcept;
- ~ImageYUV422 () noexcept;
+ ~ImageYUV422 () noexcept override;
inline Encoding
getEncoding () const override
{
}
-IRImage::~IRImage () noexcept
-{
-}
+IRImage::~IRImage () noexcept = default;
unsigned IRImage::getWidth () const throw ()
{
ShiftToDepthConverter () : init_(false) {}
/** \brief Destructor. */
- virtual ~ShiftToDepthConverter () {};
+ virtual ~ShiftToDepthConverter () = default;
/** \brief This method generates a look-up table to convert openni shift values to depth
*/
const Mode& image_mode = OpenNI_Default_Mode);
/** \brief virtual Destructor inherited from the Grabber interface. It never throws. */
- ~OpenNIGrabber () noexcept;
+ ~OpenNIGrabber () noexcept override;
/** \brief Start the data acquisition. */
void
PCDGrabberBase (const std::vector<std::string>& pcd_files, float frames_per_second, bool repeat);
/** \brief Virtual destructor. */
- ~PCDGrabberBase () noexcept;
+ ~PCDGrabberBase () noexcept override;
/** \brief Starts playing the list of PCD files if frames_per_second is > 0. Otherwise it works as a trigger: publishes only the next PCD file in the list. */
void
PCDGrabber (const std::vector<std::string>& pcd_files, float frames_per_second = 0, bool repeat = false);
/** \brief Virtual destructor. */
- ~PCDGrabber () noexcept
+ ~PCDGrabber () noexcept override
{
stop ();
}
{
public:
/** Empty constructor */
- PCDReader () {}
+ PCDReader () = default;
/** Empty destructor */
- ~PCDReader () {}
+ ~PCDReader () override = default;
/** \brief Various PCD file versions.
*
{
public:
PCDWriter() : map_synchronization_(false) {}
- ~PCDWriter() {}
+ ~PCDWriter() override = default;
/** \brief Set whether mmap() synchornization via msync() is desired before munmap() calls.
* Setting this to true could prevent NFS data loss (see
struct property
{
property (const std::string& name) : name (name) {}
- virtual ~property () {}
+ virtual ~property () = default;
virtual bool parse (class ply_parser& ply_parser, format_type format, std::istream& istream) = 0;
std::string name;
};
#include <pcl/memory.h>
#include <pcl/pcl_macros.h>
+#include <pcl/common/io.h> // for copyPointCloud
#include <pcl/io/file_io.h>
#include <pcl/io/ply/ply_parser.h>
#include <pcl/PolygonMesh.h>
return (*this);
}
- ~PLYReader () { delete range_grid_; }
+ ~PLYReader () override { delete range_grid_; }
/** \brief Read a point cloud data header from a PLY file.
*
* Load only the meta information (number of points, their types, etc),
/** Amend property from cloud fields identified by \a old_name renaming
* it \a new_name.
+ * * Returns:
+ * * false on error
+ * * true success
* param[in] old_name property old name
* param[in] new_name property new name
*/
- void
+ bool
amendProperty (const std::string& old_name, const std::string& new_name, std::uint8_t datatype = 0);
/** Callback function for the begin of vertex line */
{
public:
///Constructor
- PLYWriter () {};
+ PLYWriter () = default;
///Destructor
- ~PLYWriter () {};
+ ~PLYWriter () override = default;
/** \brief Generate the header of a PLY v.7 file format
* \param[in] cloud the point cloud data message
int valid_points);
void
- writeContentWithCameraASCII (int nr_points,
- int point_size,
+ writeContentWithCameraASCII (int nr_points,
const pcl::PCLPointCloud2 &cloud,
const Eigen::Vector4f &origin,
const Eigen::Quaternionf &orientation,
std::ofstream& fs);
void
- writeContentWithRangeGridASCII (int nr_points,
- int point_size,
+ writeContentWithRangeGridASCII (int nr_points,
const pcl::PCLPointCloud2 &cloud,
std::ostringstream& fs,
int& nb_valid_points);
namespace io
{
- /** \brief Load a PLY v.6 file into a templated PointCloud type.
+ /** \brief Load a PLY v.6 file into a PCLPointCloud2 type.
*
* Any PLY files containing sensor data will generate a warning as a
* pcl/PCLPointCloud2 message cannot hold the sensor origin.
return (p.read (file_name, cloud));
}
- /** \brief Load any PLY file into a templated PointCloud type.
+ /** \brief Load any PLY file into a PCLPointCloud2 type.
* \param[in] file_name the name of the file to load
* \param[in] cloud the resultant templated point cloud
* \param[in] origin the sensor acquisition origin (only for > PLY_V7 - null if not present)
{}
/** \brief Destructor. */
- virtual ~PointCloudImageExtractor () {}
+ virtual ~PointCloudImageExtractor () = default;
/** \brief Obtain the image from the given cloud.
* \param[in] cloud organized point cloud to extract image from
}
/** \brief Destructor. */
- ~PointCloudImageExtractorWithScaling () {}
+ ~PointCloudImageExtractorWithScaling () override = default;
/** \brief Set scaling method. */
inline void
using ConstPtr = shared_ptr<const PointCloudImageExtractorFromNormalField<PointT> >;
/** \brief Constructor. */
- PointCloudImageExtractorFromNormalField () {}
+ PointCloudImageExtractorFromNormalField () = default;
/** \brief Destructor. */
- ~PointCloudImageExtractorFromNormalField () {}
+ ~PointCloudImageExtractorFromNormalField () override = default;
protected:
using ConstPtr = shared_ptr<const PointCloudImageExtractorFromRGBField<PointT> >;
/** \brief Constructor. */
- PointCloudImageExtractorFromRGBField () {}
+ PointCloudImageExtractorFromRGBField () = default;
/** \brief Destructor. */
- ~PointCloudImageExtractorFromRGBField () {}
+ ~PointCloudImageExtractorFromRGBField () override = default;
protected:
}
/** \brief Destructor. */
- ~PointCloudImageExtractorFromLabelField () {}
+ ~PointCloudImageExtractorFromLabelField () override = default;
/** \brief Set color mapping mode. */
inline void
}
/** \brief Destructor. */
- ~PointCloudImageExtractorFromZField () {}
+ ~PointCloudImageExtractorFromZField () override = default;
protected:
// Members derived from the base class
}
/** \brief Destructor. */
- ~PointCloudImageExtractorFromCurvatureField () {}
+ ~PointCloudImageExtractorFromCurvatureField () override = default;
protected:
// Members derived from the base class
}
/** \brief Destructor. */
- ~PointCloudImageExtractorFromIntensityField () {}
+ ~PointCloudImageExtractorFromIntensityField () override = default;
protected:
// Members derived from the base class
std::shared_ptr<RealSenseDevice>
capture (DeviceInfo& device_info);
- RealSenseDeviceManager ();
-
/** This function discovers devices that are capable of streaming
* depth data. */
void
RealSense2Grabber ( const std::string& file_name_or_serial_number = "", const bool repeat_playback = true );
/** \brief virtual Destructor inherited from the Grabber interface. It never throws. */
- ~RealSense2Grabber ();
+ ~RealSense2Grabber () override;
/** \brief Set the device options
* \param[in] width resolution
getName () const override { return std::string ( "RealSense2Grabber" ); }
//define callback signature typedefs
- typedef void (signal_librealsense_PointXYZ) ( const pcl::PointCloud<pcl::PointXYZ>::ConstPtr& );
- typedef void (signal_librealsense_PointXYZI) ( const pcl::PointCloud<pcl::PointXYZI>::ConstPtr& );
- typedef void (signal_librealsense_PointXYZRGB) ( const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr& );
- typedef void (signal_librealsense_PointXYZRGBA) ( const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr& );
+ using signal_librealsense_PointXYZ = void( const pcl::PointCloud<pcl::PointXYZ>::ConstPtr& );
+ using signal_librealsense_PointXYZI = void( const pcl::PointCloud<pcl::PointXYZI>::ConstPtr& );
+ using signal_librealsense_PointXYZRGB = void( const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr& );
+ using signal_librealsense_PointXYZRGBA = void( const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr& );
protected:
RobotEyeGrabber (const boost::asio::ip::address& ipAddress, unsigned short port=443);
/** \brief virtual Destructor inherited from the Grabber interface. It never throws. */
- ~RobotEyeGrabber () noexcept;
+ ~RobotEyeGrabber () noexcept override;
/** \brief Starts the RobotEye grabber.
* The grabber runs on a separate thread, this call will return without blocking. */
--- /dev/null
+/*
+* SPDX-License-Identifier: BSD-3-Clause
+*
+* Point Cloud Library (PCL) - www.pointclouds.org
+* Copyright (c) 2014-, Open Perception Inc.
+*
+* All rights reserved
+*/
+
+#pragma once
+#include <string>
+
+namespace pcl {
+
+/** \brief Lightweight tokenization function
+ * This function can be used as a boost::split substitute. When benchmarked against
+ * boost, this function will create much less alocations and hence it is much better
+ * suited for quick line tokenization.
+ *
+ * Cool thing is this function will work with SequenceSequenceT =
+ * std::vector<std::string> and std::vector<std::string_view>
+ */
+template <typename SequenceSequenceT>
+void
+split(SequenceSequenceT& result, std::string const& in, const char* const delimiters)
+{
+ using StringSizeT = std::string::size_type;
+
+ const auto len = in.length();
+ StringSizeT token_start = 0;
+
+ result.clear();
+ while (token_start < len) {
+ // eat leading whitespace
+ token_start = in.find_first_not_of(delimiters, token_start);
+ if (token_start == std::string::npos) {
+ return; // nothing left but white space
+ }
+
+ // find the end of the token
+ const auto token_end = in.find_first_of(delimiters, token_start);
+
+ // push token
+ if (token_end == std::string::npos) {
+ result.emplace_back(in.data() + token_start, len - token_start);
+ return;
+ }
+ else {
+ result.emplace_back(in.data() + token_start, token_end - token_start);
+ }
+
+ // set up for next loop
+ token_start = token_end + 1;
+ }
+}
+} // namespace pcl
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <boost/asio.hpp>
-#include <boost/thread.hpp>
+#include <mutex>
#include <vector>
#include <string>
#include <thread>
TimGrabber ();
TimGrabber (const boost::asio::ip::address& ipAddress, const std::uint16_t port);
- ~TimGrabber () noexcept;
+ ~TimGrabber () noexcept override;
void
start () override;
unsigned int wait_time_milliseconds_ = 0;
pcl::EventFrequency frequency_;
- mutable boost::mutex frequency_mutex_;
+ mutable std::mutex frequency_mutex_;
std::thread grabber_thread_;
bool is_running_ = false;
/** \brief virtual Destructor inherited from the Grabber interface. It never throws. */
- ~VLPGrabber () noexcept;
+ ~VLPGrabber () noexcept override;
/** \brief Obtains the name of this I/O Grabber
* \return The name of the grabber
#pragma once
-#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/PolygonMesh.h>
#include <pcl/TextureMesh.h>
#ifdef __GNUC__
#pragma GCC system_header
#endif
+#include <vtkPolyData.h> // for vtkPolyData
#include <vtkSmartPointer.h>
#include <vtkStructuredGrid.h>
-#include <vtkPoints.h>
-#include <vtkPointData.h>
-#include <vtkCellArray.h>
-#include <vtkUnsignedCharArray.h>
-#include <vtkFloatArray.h>
-#include <vtkPolyDataReader.h>
-#include <vtkPolyDataWriter.h>
-#include <vtkPLYReader.h>
-#include <vtkPLYWriter.h>
-#include <vtkOBJReader.h>
-#include <vtkSTLReader.h>
-#include <vtkSTLWriter.h>
-#include <vtkPNGReader.h>
-#include <vtkImageData.h>
-#include <vtkPolyDataNormals.h>
namespace pcl
{
*
*/
+#include <pcl/common/io.h> // for getFieldSize
#include <pcl/common/utils.h> // pcl::utils::ignore
#include <pcl/io/ascii_io.h>
#include <istream>
//////////////////////////////////////////////////////////////////////////////
pcl::ASCIIReader::ASCIIReader ()
{
- extension_ = ".txt";
- sep_chars_ = ", \n\r\t";
- name_ = "AsciiReader";
-
{
pcl::PCLPointField f;
f.datatype = pcl::PCLPointField::FLOAT32;
}
//////////////////////////////////////////////////////////////////////////////
-pcl::ASCIIReader::~ASCIIReader ()
-{
-}
+pcl::ASCIIReader::~ASCIIReader () = default;
//////////////////////////////////////////////////////////////////////////////
int
total++;
origin = Eigen::Vector4f::Zero ();
- orientation = Eigen::Quaternionf ();
+ orientation = Eigen::Quaternionf::Identity ();
cloud.width = total;
cloud.height = 1;
cloud.is_dense = true;
const pcl::PCLPointField& field,
std::uint8_t* data_target)
{
+#define ASSIGN_TOKEN(CASE_LABEL) \
+ case CASE_LABEL: { \
+ *(reinterpret_cast<pcl::traits::asType_t<CASE_LABEL>*>(data_target)) = \
+ boost::lexical_cast<pcl::traits::asType_t<CASE_LABEL>>(token); \
+ return sizeof(pcl::traits::asType_t<CASE_LABEL>); \
+ }
switch (field.datatype)
{
- case pcl::PCLPointField::INT8:
- {
- *(reinterpret_cast<std::int8_t*>(data_target)) = boost::lexical_cast<std::int8_t> (token);
- return (1);
- }
- case pcl::PCLPointField::UINT8:
- {
- *(reinterpret_cast<std::uint8_t*>(data_target)) = boost::lexical_cast<std::uint8_t> (token);
- return 1;
- }
- case pcl::PCLPointField::INT16:
- {
- *(reinterpret_cast<std::int16_t*>(data_target)) = boost::lexical_cast<std::int16_t> (token);
- return 2;
- }
- case pcl::PCLPointField::UINT16:
- {
- *(reinterpret_cast<std::uint16_t*>(data_target)) = boost::lexical_cast<std::uint16_t> (token);
- return 2;
- }
- case pcl::PCLPointField::INT32:
- {
- *(reinterpret_cast<std::int32_t*>(data_target)) = boost::lexical_cast<std::int32_t> (token);
- return 4;
- }
- case pcl::PCLPointField::UINT32:
- {
- *(reinterpret_cast<std::uint32_t*>(data_target)) = boost::lexical_cast<std::uint32_t> (token);
- return 4;
- }
- case pcl::PCLPointField::FLOAT32:
- {
- *(reinterpret_cast<float*>(data_target)) = boost::lexical_cast<float> (token);
- return 4;
- }
- case pcl::PCLPointField::FLOAT64:
- {
- *(reinterpret_cast<double*>(data_target)) = boost::lexical_cast<double> (token);
- return 8;
- }
+ ASSIGN_TOKEN(pcl::PCLPointField::BOOL)
+ ASSIGN_TOKEN(pcl::PCLPointField::INT8)
+ ASSIGN_TOKEN(pcl::PCLPointField::UINT8)
+ ASSIGN_TOKEN(pcl::PCLPointField::INT16)
+ ASSIGN_TOKEN(pcl::PCLPointField::UINT16)
+ ASSIGN_TOKEN(pcl::PCLPointField::INT32)
+ ASSIGN_TOKEN(pcl::PCLPointField::UINT32)
+ ASSIGN_TOKEN(pcl::PCLPointField::INT64)
+ ASSIGN_TOKEN(pcl::PCLPointField::UINT64)
+ ASSIGN_TOKEN(pcl::PCLPointField::FLOAT32)
+ ASSIGN_TOKEN(pcl::PCLPointField::FLOAT64)
}
+#undef ASSIGN_TOKEN
return 0;
}
std::uint32_t
pcl::ASCIIReader::typeSize (int type)
{
- switch (type)
- {
- case pcl::PCLPointField::INT8:
- return 1;
- case pcl::PCLPointField::UINT8:
- return 1;
- case pcl::PCLPointField::INT16:
- return 2;
- case pcl::PCLPointField::UINT16:
- return 2;
- case pcl::PCLPointField::INT32:
- return 4;
- case pcl::PCLPointField::UINT32:
- return 4;
- case pcl::PCLPointField::FLOAT32:
- return 4;
- case pcl::PCLPointField::FLOAT64:
- return 8;
- }
- return (0);
+ return getFieldSize(type);
}
RGB16 * (image_size_) + sync_packet_size_, &actual_length, 1000);
if (res != 0 || actual_length == 0)
{
- memset (&image_[0], 0x00, image_size_);
+ std::fill_n(image_, image_size_, 0x00);
PCL_THROW_EXCEPTION (pcl::IOException, "[pcl::DinastGrabber::readImage] USB read error!");
}
// Handle Ensenso SDK exceptions
// This function is called whenever an exception is raised to provide details about the error
void
-ensensoExceptionHandling (const NxLibException &ex,
- std::string func_nam)
+ensensoExceptionHandling (const NxLibException& ex,
+ const std::string& func_nam)
{
PCL_ERROR ("%s: NxLib error %s (%d) occurred while accessing item %s.\n", func_nam.c_str (), ex.getErrorText ().c_str (), ex.getErrorCode (),
ex.getItemPath ().c_str ());
double timestamp;
std::vector<float> pointMap;
int width, height;
- camera_[itmImages][itmRaw][itmLeft].getBinaryDataInfo (0, 0, 0, 0, 0, ×tamp); // Get raw image timestamp
- camera_[itmImages][itmPointMap].getBinaryDataInfo (&width, &height, 0, 0, 0, 0);
- camera_[itmImages][itmPointMap].getBinaryData (pointMap, 0);
+ camera_[itmImages][itmRaw][itmLeft].getBinaryDataInfo (nullptr, nullptr, nullptr, nullptr, nullptr, ×tamp); // Get raw image timestamp
+ camera_[itmImages][itmPointMap].getBinaryDataInfo (&width, &height, nullptr, nullptr, nullptr, nullptr);
+ camera_[itmImages][itmPointMap].getBinaryData (pointMap, nullptr);
// Copy point cloud and convert in meters
cloud.header.stamp = getPCLStamp (timestamp);
NxLibCommand (cmdCapture).execute ();
double timestamp;
- camera_[itmImages][itmRaw][itmLeft].getBinaryDataInfo (0, 0, 0, 0, 0, ×tamp);
+ camera_[itmImages][itmRaw][itmLeft].getBinaryDataInfo (nullptr, nullptr, nullptr, nullptr, nullptr, ×tamp);
// Gather images
if (num_slots<sig_cb_ensenso_images> () > 0 || num_slots<sig_cb_ensenso_point_cloud_images> () > 0)
if (collected_pattern)
{
- camera_[itmImages][itmWithOverlay][itmLeft].getBinaryDataInfo (&width, &height, &channels, &bpe, &isFlt, 0);
+ camera_[itmImages][itmWithOverlay][itmLeft].getBinaryDataInfo (&width, &height, &channels, &bpe, &isFlt, nullptr);
images->first.header.stamp = images->second.header.stamp = getPCLStamp (timestamp);
images->first.width = images->second.width = width;
images->first.height = images->second.height = height;
images->second.data.resize (width * height * sizeof(float));
images->first.encoding = images->second.encoding = getOpenCVType (channels, bpe, isFlt);
- camera_[itmImages][itmWithOverlay][itmLeft].getBinaryData (images->first.data.data (), images->first.data.size (), 0, 0);
- camera_[itmImages][itmWithOverlay][itmRight].getBinaryData (images->second.data.data (), images->second.data.size (), 0, 0);
+ camera_[itmImages][itmWithOverlay][itmLeft].getBinaryData (images->first.data.data (), images->first.data.size (), nullptr, nullptr);
+ camera_[itmImages][itmWithOverlay][itmRight].getBinaryData (images->second.data.data (), images->second.data.size (), nullptr, nullptr);
}
else
{
- camera_[itmImages][itmRaw][itmLeft].getBinaryDataInfo (&width, &height, &channels, &bpe, &isFlt, 0);
+ camera_[itmImages][itmRaw][itmLeft].getBinaryDataInfo (&width, &height, &channels, &bpe, &isFlt, nullptr);
images->first.header.stamp = images->second.header.stamp = getPCLStamp (timestamp);
images->first.width = images->second.width = width;
images->first.height = images->second.height = height;
images->second.data.resize (width * height * sizeof(float));
images->first.encoding = images->second.encoding = getOpenCVType (channels, bpe, isFlt);
- camera_[itmImages][itmRaw][itmLeft].getBinaryData (images->first.data.data (), images->first.data.size (), 0, 0);
- camera_[itmImages][itmRaw][itmRight].getBinaryData (images->second.data.data (), images->second.data.size (), 0, 0);
+ camera_[itmImages][itmRaw][itmLeft].getBinaryData (images->first.data.data (), images->first.data.size (), nullptr, nullptr);
+ camera_[itmImages][itmRaw][itmRight].getBinaryData (images->second.data.data (), images->second.data.size (), nullptr, nullptr);
}
}
// Get info about the computed point map and copy it into a std::vector
std::vector<float> pointMap;
int width, height;
- camera_[itmImages][itmPointMap].getBinaryDataInfo (&width, &height, 0, 0, 0, 0);
- camera_[itmImages][itmPointMap].getBinaryData (pointMap, 0);
+ camera_[itmImages][itmPointMap].getBinaryDataInfo (&width, &height, nullptr, nullptr, nullptr, nullptr);
+ camera_[itmImages][itmPointMap].getBinaryData (pointMap, nullptr);
// Copy point cloud and convert in meters
cloud->header.stamp = getPCLStamp (timestamp);
{
if (bytesReceived == 1206)
{
- std::uint8_t *dup = static_cast<std::uint8_t *> (malloc (bytesReceived * sizeof(std::uint8_t)));
- memcpy (dup, data, bytesReceived * sizeof (std::uint8_t));
+ auto *dup = static_cast<std::uint8_t *> (malloc (bytesReceived * sizeof(std::uint8_t)));
+ std::copy(data, data + bytesReceived, dup);
hdl_data_.enqueue (dup);
}
//Read the magic
std::uint32_t length_of_magic;
- fs.read ((char*)&length_of_magic, sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&length_of_magic), sizeof (std::uint32_t));
char *magic = new char [length_of_magic];
fs.read (magic, sizeof (char) * length_of_magic);
- if (strcmp (magic, "IFS"))
+ const bool file_is_ifs_file = (strcmp (magic, "IFS") == 0);
+ delete[] magic;
+ if (!file_is_ifs_file)
{
PCL_ERROR ("[pcl::IFSReader::readHeader] File %s is not an IFS file!\n", file_name.c_str ());
fs.close ();
return (-1);
}
- delete[] magic;
//Read IFS version
float version;
- fs.read ((char*)&version, sizeof (float));
+ fs.read (reinterpret_cast<char*>(&version), sizeof (float));
if (version == 1.0f)
ifs_version = IFS_V1_0;
else
//Read the name
std::uint32_t length_of_name;
- fs.read ((char*)&length_of_name, sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&length_of_name), sizeof (std::uint32_t));
char *name = new char [length_of_name];
fs.read (name, sizeof (char) * length_of_name);
delete[] name;
{
//Read the keyword
std::uint32_t length_of_keyword;
- fs.read ((char*)&length_of_keyword, sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&length_of_keyword), sizeof (std::uint32_t));
char *keyword = new char [length_of_keyword];
fs.read (keyword, sizeof (char) * length_of_keyword);
- if (strcmp (keyword, "VERTICES") == 0)
+ const bool keyword_is_vertices = (strcmp (keyword, "VERTICES") == 0);
+ delete[] keyword;
+ if (keyword_is_vertices)
{
- fs.read ((char*)&nr_points, sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&nr_points), sizeof (std::uint32_t));
if ((nr_points == 0) || (nr_points > 10000000))
{
PCL_ERROR ("[pcl::IFSReader::readHeader] Bad number of vertices %lu!\n", nr_points);
fs.seekg (data_size);
// Read the TRIANGLES keyword
std::uint32_t length_of_keyword;
- fs.read ((char*)&length_of_keyword, sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&length_of_keyword), sizeof (std::uint32_t));
char *keyword = new char [length_of_keyword];
fs.read (keyword, sizeof (char) * length_of_keyword);
if (strcmp (keyword, "TRIANGLES"))
delete[] keyword;
// Read the number of facets
std::uint32_t nr_facets;
- fs.read ((char*)&nr_facets, sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&nr_facets), sizeof (std::uint32_t));
if ((nr_facets == 0) || (nr_facets > 10000000))
{
PCL_ERROR ("[pcl::IFSReader::read] Bad number of facets %lu!\n", nr_facets);
{
pcl::Vertices &facet = mesh.polygons[i];
facet.vertices.resize (3);
- fs.read ((char*)&(facet.vertices[0]), sizeof (std::uint32_t));
- fs.read ((char*)&(facet.vertices[1]), sizeof (std::uint32_t));
- fs.read ((char*)&(facet.vertices[2]), sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&(facet.vertices[0])), sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&(facet.vertices[1])), sizeof (std::uint32_t));
+ fs.read (reinterpret_cast<char*>(&(facet.vertices[2])), sizeof (std::uint32_t));
}
// We are done, close the file
fs.close ();
{}
-pcl::io::DepthImage::~DepthImage ()
-{}
-
+pcl::io::DepthImage::~DepthImage () = default;
const unsigned short*
pcl::io::DepthImage::getData ()
short bad_point = std::numeric_limits<short>::quiet_NaN ();
unsigned depthIdx = 0;
- const unsigned short* inputBuffer = static_cast<const unsigned short*> (wrapper_->getData ());
+ const auto* inputBuffer = static_cast<const unsigned short*> (wrapper_->getData ());
for (unsigned yIdx = 0; yIdx < height; ++yIdx, depthIdx += ySkip)
{
float bad_point = std::numeric_limits<float>::quiet_NaN ();
unsigned depthIdx = 0;
- const unsigned short* inputBuffer = static_cast<const unsigned short*> (wrapper_->getData ());
+ const auto* inputBuffer = static_cast<const unsigned short*> (wrapper_->getData ());
for (unsigned yIdx = 0; yIdx < height; ++yIdx, depthIdx += ySkip)
{
// focal length is for the native image resolution -> focal_length = focal_length_ / xStep;
float constant = focal_length_ * baseline_ * 1000.0f / static_cast<float> (xStep);
- const unsigned short* inputBuffer = static_cast<const unsigned short*> (wrapper_->getData ());
+ const auto* inputBuffer = static_cast<const unsigned short*> (wrapper_->getData ());
for (unsigned yIdx = 0, depthIdx = 0; yIdx < height; ++yIdx, depthIdx += ySkip)
{
bool pclzf_mode=false);
//! For now, split rgb / depth folders only makes sense for VTK images
ImageGrabberImpl (pcl::ImageGrabberBase& grabber,
- const std::string& rgb_dir,
const std::string& depth_dir,
+ const std::string& rgb_dir,
float frames_per_second,
bool repeat);
ImageGrabberImpl (pcl::ImageGrabberBase& grabber,
pcl::ImageGrabberBase& grabber_;
float frames_per_second_;
bool repeat_;
- bool running_;
+ bool running_ = false;
// VTK
std::vector<std::string> depth_image_files_;
std::vector<std::string> rgb_image_files_;
std::vector<std::string> rgb_pclzf_files_;
std::vector<std::string> xml_files_;
- std::size_t cur_frame_;
+ std::size_t cur_frame_ = 0;
TimeTrigger time_trigger_;
Eigen::Vector4f origin_;
Eigen::Quaternionf orientation_;
PCL_MAKE_ALIGNED_OPERATOR_NEW
- bool valid_;
+ bool valid_ = false;
//! Flag to say if a user set the focal length by hand
// (so we don't attempt to adjust for QVGA, QQVGA, etc).
- bool pclzf_mode_;
+ bool pclzf_mode_ = false;
- float depth_image_units_;
+ float depth_image_units_ = 1E-3f;
- bool manual_intrinsics_;
- double focal_length_x_;
- double focal_length_y_;
- double principal_point_x_;
- double principal_point_y_;
+ bool manual_intrinsics_ = false;
+ double focal_length_x_ = 525.;
+ double focal_length_y_ = 525.;
+ double principal_point_x_ = 319.5;
+ double principal_point_y_ = 239.5;
- unsigned int num_threads_;
+ unsigned int num_threads_ = 1;
};
///////////////////////////////////////////////////////////////////////////////////////////
: grabber_ (grabber)
, frames_per_second_ (frames_per_second)
, repeat_ (repeat)
- , running_ (false)
, time_trigger_ (1.0 / static_cast<double> (std::max (frames_per_second, 0.001f)), [this] { trigger (); })
- , valid_ (false)
, pclzf_mode_(pclzf_mode)
- , depth_image_units_ (1E-3f)
- , manual_intrinsics_ (false)
- , focal_length_x_ (525.)
- , focal_length_y_ (525.)
- , principal_point_x_ (319.5)
- , principal_point_y_ (239.5)
- , num_threads_ (1)
{
if(pclzf_mode_)
{
{
loadDepthAndRGBFiles (dir);
}
- cur_frame_ = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////
: grabber_ (grabber)
, frames_per_second_ (frames_per_second)
, repeat_ (repeat)
- , running_ (false)
, time_trigger_ (1.0 / static_cast<double> (std::max (frames_per_second, 0.001f)), [this] { trigger (); })
- , valid_ (false)
- , pclzf_mode_ (false)
- , depth_image_units_ (1E-3f)
- , manual_intrinsics_ (false)
- , focal_length_x_ (525.)
- , focal_length_y_ (525.)
- , principal_point_x_ (319.5)
- , principal_point_y_ (239.5)
- , num_threads_ (1)
{
loadDepthAndRGBFiles (depth_dir, rgb_dir);
- cur_frame_ = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////
: grabber_ (grabber)
, frames_per_second_ (frames_per_second)
, repeat_ (repeat)
- , running_ (false)
+ , depth_image_files_ (depth_image_files)
, time_trigger_ (1.0 / static_cast<double> (std::max (frames_per_second, 0.001f)), [this] { trigger (); })
- , valid_ (false)
- , pclzf_mode_ (false)
- , depth_image_units_ (1E-3f)
- , manual_intrinsics_ (false)
- , focal_length_x_ (525.)
- , focal_length_y_ (525.)
- , principal_point_x_ (319.5)
- , principal_point_y_ (239.5)
- , num_threads_ (1)
{
- depth_image_files_ = depth_image_files;
- cur_frame_ = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////
}
//////////////////////////////////////////////////////////
-pcl::ImageGrabberBase::ImageGrabberBase (const std::string& rgb_dir, const std::string &depth_dir, float frames_per_second, bool repeat)
- : impl_ (new ImageGrabberImpl (*this, rgb_dir, depth_dir, frames_per_second, repeat))
+pcl::ImageGrabberBase::ImageGrabberBase (const std::string& depth_directory, const std::string &rgb_directory, float frames_per_second, bool repeat)
+ : impl_ (new ImageGrabberImpl (*this, depth_directory, rgb_directory, frames_per_second, repeat))
{
}
unsigned irIdx = 0;
- const unsigned short* inputBuffer = static_cast<const unsigned short*> (wrapper_->getData ());
+ const auto* inputBuffer = static_cast<const unsigned short*> (wrapper_->getData ());
for (unsigned yIdx = 0; yIdx < height; ++yIdx, irIdx += ySkip)
{
{}
-pcl::io::ImageRGB24::~ImageRGB24 () noexcept
-{}
+pcl::io::ImageRGB24::~ImageRGB24 () noexcept = default;
bool
pcl::io::ImageRGB24::isResizingSupported (unsigned input_width, unsigned input_height, unsigned output_width, unsigned output_height) const
unsigned dst_skip = gray_line_step - width; // skip of padding values in bytes
unsigned char* dst_line = gray_buffer;
- const RGB888Pixel* src_line = (RGB888Pixel*) wrapper_->getData ();
+ const auto* src_line = reinterpret_cast<const RGB888Pixel*>(wrapper_->getData ());
for (unsigned yIdx = 0; yIdx < height; ++yIdx, src_line += src_skip, dst_line += dst_skip)
{
if (width == wrapper_->getWidth () && height == wrapper_->getHeight ())
{
unsigned line_size = width * 3;
+ const auto* src_line = static_cast<const unsigned char*> (wrapper_->getData ());
if (rgb_line_step == 0 || rgb_line_step == line_size)
{
- memcpy (rgb_buffer, wrapper_->getData (), wrapper_->getDataSize ());
+ std::copy(src_line, src_line + wrapper_->getDataSize(), rgb_buffer);
}
else // line by line
{
unsigned char* rgb_line = rgb_buffer;
- const unsigned char* src_line = static_cast<const unsigned char*> (wrapper_->getData ());
for (unsigned yIdx = 0; yIdx < height; ++yIdx, rgb_line += rgb_line_step, src_line += line_size)
{
- memcpy (rgb_line, src_line, line_size);
+ std::copy(src_line, src_line + line_size, rgb_line);
}
}
}
unsigned dst_skip = rgb_line_step - width * 3; // skip of padding values in bytes
- RGB888Pixel* dst_line = reinterpret_cast<RGB888Pixel*> (rgb_buffer);
- const RGB888Pixel* src_line = (RGB888Pixel*) wrapper_->getData ();
+ auto* dst_line = reinterpret_cast<RGB888Pixel*> (rgb_buffer);
+ const auto* src_line = reinterpret_cast<const RGB888Pixel*> (wrapper_->getData ());
for (unsigned yIdx = 0; yIdx < height; ++yIdx, src_line += src_skip)
{
if (dst_skip != 0)
{
// use bytes to skip rather than XnRGB24Pixel's, since line_step does not need to be multiple of 3
- unsigned char* temp = reinterpret_cast <unsigned char*> (dst_line);
+ auto* temp = reinterpret_cast <unsigned char*> (dst_line);
dst_line = reinterpret_cast <RGB888Pixel*> (temp + dst_skip);
}
}
#include <pcl/io/io_exception.h>
-#include <sstream>
-#include <iostream>
-
#define CLIP_CHAR(c) static_cast<unsigned char> ((c)>255?255:(c)<0?0:(c))
using pcl::io::FrameWrapper;
{}
-pcl::io::ImageYUV422::~ImageYUV422 () noexcept
-{}
+pcl::io::ImageYUV422::~ImageYUV422 () noexcept = default;
bool
pcl::io::ImageYUV422::isResizingSupported (unsigned input_width, unsigned input_height, unsigned output_width, unsigned output_height) const
THROW_IO_EXCEPTION ("Downsampling only possible for power of two scale in both dimensions. Request was %d x %d -> %d x %d.", wrapper_->getWidth (), wrapper_->getHeight (), width, height);
}
- const std::uint8_t* yuv_buffer = (std::uint8_t*) wrapper_->getData ();
+ const auto* yuv_buffer = reinterpret_cast<const std::uint8_t*>(wrapper_->getData ());
unsigned rgb_line_skip = 0;
if (rgb_line_step != 0)
unsigned yuv_step = wrapper_->getWidth () / width;
unsigned yuv_x_step = yuv_step << 1;
unsigned yuv_skip = (wrapper_->getHeight () / height - 1) * ( wrapper_->getWidth () << 1 );
- const std::uint8_t* yuv_buffer = ( (std::uint8_t*) wrapper_->getData () + 1);
+ const std::uint8_t* yuv_buffer = ( reinterpret_cast<const std::uint8_t*>(wrapper_->getData ()) + 1);
for (unsigned yIdx = 0; yIdx < wrapper_->getHeight (); yIdx += yuv_step, yuv_buffer += yuv_skip, gray_buffer += gray_line_skip)
{
message_long_ = sstream.str ();
}
-pcl::io::IOException::~IOException () noexcept
-{
-}
+pcl::io::IOException::~IOException () noexcept = default;
pcl::io::IOException&
pcl::io::IOException::operator = (const IOException& exception)
void
user_read_data (png_structp png_ptr, png_bytep data, png_size_t length)
{
- std::uint8_t** input_pointer = reinterpret_cast<std::uint8_t**>(png_get_io_ptr (png_ptr));
+ auto** input_pointer = reinterpret_cast<std::uint8_t**>(png_get_io_ptr (png_ptr));
memcpy (data, *input_pointer, sizeof (std::uint8_t) * length);
(*input_pointer) += length;
void
user_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
{
- std::vector<std::uint8_t>* pngVec = reinterpret_cast<std::vector<std::uint8_t>*>(png_get_io_ptr (png_ptr));
+ auto* pngVec = reinterpret_cast<std::vector<std::uint8_t>*>(png_get_io_ptr (png_ptr));
std::copy (data, data + length, std::back_inserter (*pngVec));
}
#include <cerrno>
#include <climits>
#include <cstddef>
-#include <cstring>
+#include <algorithm>
/*
* Size of hashtable is (1 << HLOG) * sizeof (char *)
pcl::lzfCompress (const void *const in_data, unsigned int in_len,
void *out_data, unsigned int out_len)
{
- LZF_STATE htab;
- const unsigned char *ip = static_cast<const unsigned char *> (in_data);
- unsigned char *op = static_cast<unsigned char *> (out_data);
+ LZF_STATE htab{};
+ const auto *ip = static_cast<const unsigned char *> (in_data);
+ auto *op = static_cast<unsigned char *> (out_data);
const unsigned char *in_end = ip + in_len;
unsigned char *out_end = op + out_len;
return (0);
}
- // Initialize the htab
- memset (htab, 0, sizeof (htab));
-
// Start run
int lit = 0;
op++;
pcl::lzfDecompress (const void *const in_data, unsigned int in_len,
void *out_data, unsigned int out_len)
{
- unsigned char const *ip = static_cast<const unsigned char *> (in_data);
- unsigned char *op = static_cast<unsigned char *> (out_data);
+ auto const *ip = static_cast<const unsigned char *> (in_data);
+ auto *op = static_cast<unsigned char *> (out_data);
unsigned char const *const in_end = ip + in_len;
unsigned char *const out_end = op + out_len;
if (op >= ref + len)
{
- // Disjunct areas
- memcpy (op, ref, len);
+ // Disjunct
+ std::copy(ref, ref + len, op);
op += len;
}
else
HANDLE fm = CreateFileMapping (h_native_file, NULL, PAGE_READWRITE, 0, data_size, NULL);
char *map = static_cast<char*> (MapViewOfFile (fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, data_size));
CloseHandle (fm);
- memcpy (&map[0], data, data_size);
+ std::copy(data, data + data_size, map);
UnmapViewOfFile (map);
CloseHandle (h_native_file);
#else
}
// Copy the data
- memcpy (&map[0], data, data_size);
+ std::copy(data, data + data_size, map);
if (::munmap (map, (data_size)) == -1)
{
}
#endif
- // Check the header identifier here
- char header_string[5];
- memcpy (&header_string, &map[0], 5); // PCLZF
- if (std::string (header_string).substr (0, 5) != "PCLZF")
+ // Check the header identifier here (PCLZF)
+ if (map[0] != 'P' || map[1] != 'C' || map[2] != 'L' || map[3] != 'Z' || map[4] != 'F')
{
PCL_ERROR ("[pcl::io::LZFImageReader::loadImage] Wrong signature header! Should be 'P'C'L'Z'F'.\n");
#ifdef _WIN32
}
memcpy (&width_, &map[5], sizeof (std::uint32_t));
memcpy (&height_, &map[9], sizeof (std::uint32_t));
- char imgtype_string[16];
- memcpy (&imgtype_string, &map[13], 16); // BAYER8, RGB24_, YUV422_, ...
- image_type_identifier_ = std::string (imgtype_string).substr (0, 15);
- image_type_identifier_.insert (image_type_identifier_.end (), 1, '\0');
+ image_type_identifier_ = std::string (map+13, 16); // BAYER8, RGB24_, YUV422_, ...
static const int header_size = LZF_HEADER_SIZE;
std::uint32_t compressed_size;
data.resize (compressed_size);
memcpy (&data[0], &map[header_size], compressed_size);
-
+
#ifdef _WIN32
UnmapViewOfFile (map);
CloseHandle (fm);
#include <fstream>
#include <pcl/common/io.h>
#include <pcl/console/time.h>
+#include <pcl/io/split.h>
+
#include <boost/lexical_cast.hpp> // for lexical_cast
#include <boost/filesystem.hpp> // for exists
-#include <boost/algorithm/string.hpp> // for split
+#include <boost/algorithm/string.hpp> // for trim
pcl::MTLReader::MTLReader ()
{
std::vector<pcl::TexMaterial>::const_iterator
pcl::MTLReader::getMaterial (const std::string& material_name) const
{
- std::vector<pcl::TexMaterial>::const_iterator mat_it = materials_.begin ();
+ auto mat_it = materials_.begin ();
for (; mat_it != materials_.end (); ++mat_it)
if (mat_it->tex_name == material_name)
break;
continue;
// Tokenize the line
- std::stringstream sstream (line);
- sstream.imbue (std::locale::classic ());
- line = sstream.str ();
- boost::trim (line);
- boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
+ pcl::split (st, line, "\t\r ");
// Ignore comments
if (st[0] == "#")
continue;
continue;
// Trim the line
+ //TOOD: we can easily do this without boost
boost::trim (line);
// Ignore comments
if (line.substr (0, 6) == "mtllib")
{
std::vector<std::string> st;
- boost::split(st, line, boost::is_any_of("\t\r "), boost::token_compress_on);
+ pcl::split(st, line, "\t\r ");
material_files.push_back (st.at (1));
continue;
}
// rgba_field = i;
std::vector<std::string> st;
+ std::string line;
try
{
uindex_t point_idx = 0;
while (!fs.eof ())
{
- std::string line;
getline (fs, line);
// Ignore empty lines
if (line.empty())
continue;
// Tokenize the line
- std::stringstream sstream (line);
- sstream.imbue (std::locale::classic ());
- line = sstream.str ();
- boost::trim (line);
- boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
+ pcl::split (st, line, "\t\r ");
// Ignore comments
if (st[0] == "#")
continue;
// Tokenize the line
- std::stringstream sstream (line);
- sstream.imbue (std::locale::classic ());
- line = sstream.str ();
- boost::trim (line);
- boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
+ pcl::split (st, line, "\t\r ");
// Ignore comments
if (st[0] == "#")
if (st[0] == "usemtl")
{
mesh.tex_polygons.emplace_back();
+ mesh.tex_coord_indices.emplace_back();
mesh.tex_materials.emplace_back();
for (const auto &companion : companions_)
{
// Face
if (st[0] == "f")
{
- //We only care for vertices indices
+ // TODO read in normal indices properly
pcl::Vertices face_v; face_v.vertices.resize (st.size () - 1);
+ pcl::Vertices tex_indices; tex_indices.vertices.reserve (st.size () - 1);
for (std::size_t i = 1; i < st.size (); ++i)
{
- int v;
- sscanf (st[i].c_str (), "%d", &v);
+ char* str_end;
+ int v = std::strtol(st[i].c_str(), &str_end, 10);
v = (v < 0) ? v_idx + v : v - 1;
face_v.vertices[i-1] = v;
+ if (str_end[0] == '/' && str_end[1] != '/' && str_end[1] != '\0')
+ {
+ // texture coordinate indices are optional
+ int tex_index = std::strtol(str_end+1, &str_end, 10);
+ tex_indices.vertices.push_back (tex_index - 1);
+ }
}
mesh.tex_polygons.back ().push_back (face_v);
+ mesh.tex_coord_indices.back ().push_back (tex_indices);
++f_idx;
continue;
}
}
double total_time = tt.toc ();
- PCL_DEBUG ("[pcl::OBJReader::read] Loaded %s as a TextureMesh in %g ms with %g points, %g texture materials, %g polygons.\n",
+ PCL_DEBUG ("[pcl::OBJReader::read] Loaded %s as a TextureMesh in %g ms with %zu points, %zu texture materials, %zu polygons.\n",
file_name.c_str (), total_time,
- v_idx -1, mesh.tex_materials.size (), f_idx -1);
+ v_idx, mesh.tex_materials.size (), f_idx);
fs.close ();
return (0);
}
continue;
// Tokenize the line
- std::stringstream sstream (line);
- sstream.imbue (std::locale::classic ());
- line = sstream.str ();
- boost::trim (line);
- boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
+ pcl::split (st, line, "\t\r ");
// Ignore comments
if (st[0] == "#")
}
double total_time = tt.toc ();
- PCL_DEBUG ("[pcl::OBJReader::read] Loaded %s as a PolygonMesh in %g ms with %g points and %g polygons.\n",
+ PCL_DEBUG ("[pcl::OBJReader::read] Loaded %s as a PolygonMesh in %g ms with %zu points and %zu polygons.\n",
file_name.c_str (), total_time,
- mesh.cloud.width * mesh.cloud.height, mesh.polygons.size ());
+ static_cast<std::size_t> (mesh.cloud.width * mesh.cloud.height), mesh.polygons.size ());
fs.close ();
return (0);
}
/* Write 3D information */
// number of points
unsigned nr_points = tex_mesh.cloud.width * tex_mesh.cloud.height;
- unsigned point_size = static_cast<unsigned> (tex_mesh.cloud.data.size () / nr_points);
+ auto point_size = static_cast<unsigned> (tex_mesh.cloud.data.size () / nr_points);
// mesh size
- unsigned nr_meshes = static_cast<unsigned> (tex_mesh.tex_polygons.size ());
+ auto nr_meshes = static_cast<unsigned> (tex_mesh.tex_polygons.size ());
// number of faces for header
unsigned nr_faces = 0;
for (unsigned m = 0; m < nr_meshes; ++m)
}
}
- unsigned f_idx = 0;
-
// int idx_vt =0;
for (unsigned m = 0; m < nr_meshes; ++m)
{
- if (m > 0) f_idx += static_cast<unsigned> (tex_mesh.tex_polygons[m-1].size ());
-
fs << "# The material will be used for mesh " << m << '\n';
fs << "usemtl " << tex_mesh.tex_materials[m].tex_name << '\n';
fs << "# Faces" << '\n';
{
// Write faces with "f"
fs << "f";
- // There's one UV per vertex per face, i.e., the same vertex can have
- // different UV depending on the face.
for (std::size_t j = 0; j < tex_mesh.tex_polygons[m][i].vertices.size (); ++j)
{
std::uint32_t idx = tex_mesh.tex_polygons[m][i].vertices[j] + 1;
- fs << " " << idx
- << "/" << tex_mesh.tex_polygons[m][i].vertices.size () * (i+f_idx) +j+1
- << "/" << idx; // vertex index in obj file format starting with 1
+ fs << " " << idx << "/";
+ // texture coordinate indices are optional
+ if (!tex_mesh.tex_coord_indices[m][i].vertices.empty())
+ fs << tex_mesh.tex_coord_indices[m][i].vertices[j] + 1;
+ fs << "/" << idx; // vertex index in obj file format starting with 1
}
fs << '\n';
}
// number of points
int nr_points = mesh.cloud.width * mesh.cloud.height;
// point size
- unsigned point_size = static_cast<unsigned> (mesh.cloud.data.size () / nr_points);
+ auto point_size = static_cast<unsigned> (mesh.cloud.data.size () / nr_points);
// number of faces for header
- unsigned nr_faces = static_cast<unsigned> (mesh.polygons.size ());
+ auto nr_faces = static_cast<unsigned> (mesh.polygons.size ());
// Do we have vertices normals?
int normal_index = getFieldIndex (mesh.cloud, "normal_x");
int frameWidth = stream->getVideoMode ().getResolutionX ();
float hFov = stream->getHorizontalFieldOfView ();
- float calculatedFocalLengthX = frameWidth / (2.0f * tan (hFov / 2.0f));
+ float calculatedFocalLengthX = frameWidth / (2.0f * std::tan (hFov / 2.0f));
return (calculatedFocalLengthX);
}
int frameWidth = stream->getVideoMode ().getResolutionX ();
float hFov = stream->getHorizontalFieldOfView ();
- float calculatedFocalLengthX = frameWidth / (2.0f * tan (hFov / 2.0f));
+ float calculatedFocalLengthX = frameWidth / (2.0f * std::tan (hFov / 2.0f));
return (calculatedFocalLengthX);
}
int frameWidth = stream->getVideoMode ().getResolutionX ();
float hFov = stream->getHorizontalFieldOfView ();
- float calculatedFocalLengthX = frameWidth / (2.0f * tan (hFov / 2.0f));
+ float calculatedFocalLengthX = frameWidth / (2.0f * std::tan (hFov / 2.0f));
return (calculatedFocalLengthX);
}
}
}
- ~OpenNI2DeviceListener ()
+ ~OpenNI2DeviceListener () override
{
openni::OpenNI::removeDeviceConnectedListener (this);
openni::OpenNI::removeDeviceDisconnectedListener (this);
result->reserve (device_set_.size ());
- std::set<OpenNI2DeviceInfo, OpenNI2DeviceInfoComparator>::const_iterator it;
- std::set<OpenNI2DeviceInfo, OpenNI2DeviceInfoComparator>::const_iterator it_end = device_set_.end ();
-
- for (it = device_set_.begin (); it != it_end; ++it)
- result->push_back (it->uri_);
+ for (const auto& device : device_set_) {
+ result->push_back(device.uri_);
+ }
return result;
}
device_listener_.reset(new OpenNI2DeviceListener);
}
-pcl::io::openni2::OpenNI2DeviceManager::~OpenNI2DeviceManager ()
-{
-}
+pcl::io::openni2::OpenNI2DeviceManager::~OpenNI2DeviceManager () = default;
std::shared_ptr<std::vector<OpenNI2DeviceInfo>>
pcl::io::openni2::OpenNI2DeviceManager::getConnectedDeviceInfos () const
filter_len_(filter_len)
{}
- OpenNI2TimerFilter::~OpenNI2TimerFilter ()
- {}
+ OpenNI2TimerFilter::~OpenNI2TimerFilter () = default;
void OpenNI2TimerFilter::addSample (double sample)
{
float bad_point = std::numeric_limits<float>::quiet_NaN ();
- const std::uint16_t* depth_map = (const std::uint16_t*) depth_image->getData ();
+ const auto* depth_map = reinterpret_cast<const std::uint16_t*>(depth_image->getData ());
if (depth_image->getWidth () != depth_width_ || depth_image->getHeight () != depth_height_)
{
// Resize the image if nessacery
depth_resize_buffer_.resize(depth_width_ * depth_height_);
- depth_image->fillDepthImageRaw (depth_width_, depth_height_, (std::uint16_t*) depth_resize_buffer_.data() );
+ depth_image->fillDepthImageRaw (depth_width_, depth_height_, reinterpret_cast<std::uint16_t*>(depth_resize_buffer_.data()) );
depth_map = depth_resize_buffer_.data();
}
float fx_inv = 1.0f / fx;
float fy_inv = 1.0f / fy;
- const std::uint16_t* depth_map = (const std::uint16_t*) depth_image->getData ();
+ const auto* depth_map = reinterpret_cast<const std::uint16_t*>(depth_image->getData ());
if (depth_image->getWidth () != depth_width_ || depth_image->getHeight () != depth_height_)
{
// Resize the image if nessacery
depth_resize_buffer_.resize(depth_width_ * depth_height_);
+ depth_image->fillDepthImageRaw (depth_width_, depth_height_, depth_resize_buffer_.data() );
depth_map = depth_resize_buffer_.data();
- depth_image->fillDepthImageRaw (depth_width_, depth_height_, (unsigned short*) depth_map );
}
- const std::uint8_t* rgb_buffer = (const std::uint8_t*) image->getData ();
+ const auto* rgb_buffer = reinterpret_cast<const std::uint8_t*>(image->getData ());
if (image->getWidth () != image_width_ || image->getHeight () != image_height_)
{
// Resize the image if nessacery
color_resize_buffer_.resize(image_width_ * image_height_ * 3);
+ image->fillRGB (image_width_, image_height_, color_resize_buffer_.data(), image_width_ * 3);
rgb_buffer = color_resize_buffer_.data();
- image->fillRGB (image_width_, image_height_, (unsigned char*) rgb_buffer, image_width_ * 3);
}
float fy_inv = 1.0f / fy;
- const std::uint16_t* depth_map = (const std::uint16_t*) depth_image->getData ();
+ const auto* depth_map = reinterpret_cast<const std::uint16_t*>(depth_image->getData ());
if (depth_image->getWidth () != depth_width_ || depth_image->getHeight () != depth_height_)
{
// Resize the image if nessacery
depth_resize_buffer_.resize(depth_width_ * depth_height_);
+ depth_image->fillDepthImageRaw (depth_width_, depth_height_, depth_resize_buffer_.data() );
depth_map = depth_resize_buffer_.data();
- depth_image->fillDepthImageRaw (depth_width_, depth_height_, (unsigned short*) depth_map );
}
- const std::uint16_t* ir_map = (const std::uint16_t*) ir_image->getData ();
+ const auto* ir_map = reinterpret_cast<const std::uint16_t*>(ir_image->getData ());
if (ir_image->getWidth () != depth_width_ || ir_image->getHeight () != depth_height_)
{
// Resize the image if nessacery
ir_resize_buffer_.resize(depth_width_ * depth_height_);
+ ir_image->fillRaw (depth_width_, depth_height_, ir_resize_buffer_.data());
ir_map = ir_resize_buffer_.data();
- ir_image->fillRaw (depth_width_, depth_height_, (unsigned short*) ir_map);
}
{
using VideoMode = pcl::io::openni2::OpenNI2VideoMode;
-pcl::io::openni2::OpenNI2VideoMode output_mode;
+ pcl::io::openni2::OpenNI2VideoMode output_mode;
config2oni_map_[OpenNI_SXGA_15Hz] = VideoMode (XN_SXGA_X_RES, XN_SXGA_Y_RES, 15);
bool
pcl::io::OpenNI2Grabber::mapMode2XnMode (int mode, OpenNI2VideoMode &xnmode) const
{
- std::map<int, pcl::io::openni2::OpenNI2VideoMode>::const_iterator it = config2oni_map_.find (mode);
+ auto it = config2oni_map_.find (mode);
if (it != config2oni_map_.end ())
{
xnmode = it->second;
#include <pcl/io/openni_camera/openni_depth_image.h>
#include <pcl/io/openni_camera/openni_ir_image.h>
#include <pcl/io/openni_camera/openni_image.h>
-#include <map>
#include <vector>
#include "XnVersion.h"
for (std::uint32_t nIndex = 1; nIndex < shift_conversion_parameters_.device_max_shift_; nIndex++)
{
- std::int32_t nShiftValue = (std::int32_t)nIndex;
+ auto nShiftValue = (std::int32_t)nIndex;
double dFixedRefX = (double) (nShiftValue - nConstShift) /
(double) shift_conversion_parameters_.param_coeff_;
{
if (hasDepthStream () && hasImageStream() )
{
- xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
- xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
+ auto& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
+ auto& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
std::lock_guard<std::mutex> image_lock (image_mutex_);
std::lock_guard<std::mutex> depth_lock (depth_mutex_);
{
std::lock_guard<std::mutex> image_lock (image_mutex_);
std::lock_guard<std::mutex> depth_lock (depth_mutex_);
- xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&> (image_generator_);
+ auto& image_generator = const_cast<xn::ImageGenerator&> (image_generator_);
return (depth_generator_.IsValid() && image_generator_.IsValid() && depth_generator_.GetAlternativeViewPointCap().IsViewPointSupported(image_generator));
}
{
std::lock_guard<std::mutex> image_lock (image_mutex_);
std::lock_guard<std::mutex> depth_lock (depth_mutex_);
- xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
- xn::ImageGenerator& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
+ auto& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
+ auto& image_generator = const_cast<xn::ImageGenerator&>(image_generator_);
return (depth_generator.GetFrameSyncCap ().CanFrameSyncWith (image_generator) && depth_generator.GetFrameSyncCap ().IsFrameSyncedWith (image_generator));
}
return (false);
{
std::lock_guard<std::mutex> depth_lock (depth_mutex_);
XnCropping cropping;
- xn::DepthGenerator& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
+ auto& depth_generator = const_cast<xn::DepthGenerator&>(depth_generator_);
XnStatus status = depth_generator.GetCroppingCap ().GetCropping (cropping);
if (status != XN_STATUS_OK)
THROW_OPENNI_EXCEPTION ("could not read cropping information for depth stream. Reason: %s", xnGetStatusString (status));
void __stdcall
openni_wrapper::OpenNIDevice::NewDepthDataAvailable (xn::ProductionNode&, void* cookie) noexcept
{
- OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
+ auto* device = reinterpret_cast<OpenNIDevice*>(cookie);
device->depth_condition_.notify_all ();
}
void __stdcall
openni_wrapper::OpenNIDevice::NewImageDataAvailable (xn::ProductionNode&, void* cookie) noexcept
{
- OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
+ auto* device = reinterpret_cast<OpenNIDevice*>(cookie);
device->image_condition_.notify_all ();
}
void __stdcall
openni_wrapper::OpenNIDevice::NewIRDataAvailable (xn::ProductionNode&, void* cookie) noexcept
{
- OpenNIDevice* device = reinterpret_cast<OpenNIDevice*>(cookie);
+ auto* device = reinterpret_cast<OpenNIDevice*>(cookie);
device->ir_condition_.notify_all ();
}
const char*
openni_wrapper::OpenNIDevice::getVendorName () const throw ()
{
- XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
+ auto& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
return (description.strVendor);
}
const char*
openni_wrapper::OpenNIDevice::getProductName () const throw ()
{
- XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
+ auto& description = const_cast<XnProductionNodeDescription&>(device_node_info_.GetDescription ());
return (description.strName);
}
void __stdcall
openni_wrapper::DeviceONI::NewONIDepthDataAvailable (xn::ProductionNode&, void* cookie) noexcept
{
- DeviceONI* device = reinterpret_cast<DeviceONI*>(cookie);
+ auto* device = reinterpret_cast<DeviceONI*>(cookie);
if (device->depth_stream_running_)
device->depth_condition_.notify_all ();
}
void __stdcall
openni_wrapper::DeviceONI::NewONIImageDataAvailable (xn::ProductionNode&, void* cookie) noexcept
{
- DeviceONI* device = reinterpret_cast<DeviceONI*> (cookie);
+ auto* device = reinterpret_cast<DeviceONI*> (cookie);
if (device->image_stream_running_)
device->image_condition_.notify_all ();
}
void __stdcall
openni_wrapper::DeviceONI::NewONIIRDataAvailable (xn::ProductionNode&, void* cookie) noexcept
{
- DeviceONI* device = reinterpret_cast<DeviceONI*> (cookie);
+ auto* device = reinterpret_cast<DeviceONI*> (cookie);
if (device->ir_stream_running_)
device->ir_condition_.notify_all ();
}
#include <pcl/io/openni_camera/openni_device_primesense.h>
#include <pcl/io/openni_camera/openni_device_xtion.h>
#include <pcl/io/openni_camera/openni_device_oni.h>
+
+#include <boost/tokenizer.hpp>
+
#include <sstream>
#include <iostream>
#include <algorithm>
#ifdef _WIN32
if (vendor_id == 0x45e)
{
- strcpy (const_cast<char*> (device_context_[device].device_node.GetDescription ().strVendor), "Microsoft");
- strcpy (const_cast<char*> (device_context_[device].device_node.GetDescription ().strName), "Xbox NUI Camera");
+ strcpy (const_cast<char*> (device.device_node.GetDescription ().strVendor), "Microsoft");
+ strcpy (const_cast<char*> (device.device_node.GetDescription ().strName), "Xbox NUI Camera");
}
else
#endif
openni_wrapper::OpenNIDevice::Ptr
openni_wrapper::OpenNIDriver::getDeviceBySerialNumber (const std::string& serial_number) const
{
- std::map<std::string, unsigned>::const_iterator it = serial_map_.find (serial_number);
+ auto it = serial_map_.find (serial_number);
if (it != serial_map_.end ())
{
openni_wrapper::OpenNIDevice::Ptr
openni_wrapper::OpenNIDriver::getDeviceByAddress (unsigned char bus, unsigned char address) const
{
- std::map<unsigned char, std::map<unsigned char, unsigned> >::const_iterator busIt = bus_map_.find (bus);
+ auto busIt = bus_map_.find (bus);
if (busIt != bus_map_.end ())
{
- std::map<unsigned char, unsigned>::const_iterator devIt = busIt->second.find (address);
+ auto devIt = busIt->second.find (address);
if (devIt != busIt->second.end ())
{
return getDeviceByIndex (devIt->second);
continue;
std::uint8_t address = libusb_get_device_address (device);
- std::map<unsigned char, unsigned>::const_iterator addressIt = busIt->second.find (address);
+ auto addressIt = busIt->second.find (address);
if (addressIt == busIt->second.end ())
continue;
unsigned nodeIdx = addressIt->second;
xn::NodeInfo& current_node = device_context_[nodeIdx].device_node;
- XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(current_node.GetDescription ());
+ auto& description = const_cast<XnProductionNodeDescription&>(current_node.GetDescription ());
libusb_device_descriptor descriptor;
result = libusb_get_device_descriptor (devices[devIdx], &descriptor);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-openni_wrapper::OpenNIDriver::DeviceContext::DeviceContext (const DeviceContext& other)
-: device_node (other.device_node)
-, image_node (other.image_node)
-, depth_node (other.depth_node)
-, ir_node (other.ir_node)
-, device (other.device)
-{
-}
+openni_wrapper::OpenNIDriver::DeviceContext::DeviceContext (const DeviceContext& other) = default;
#endif
message_long_ = sstream.str();
}
-OpenNIException::~OpenNIException () noexcept
-{
-}
+OpenNIException::~OpenNIException () noexcept = default;
OpenNIException& OpenNIException::operator = (const OpenNIException& exception) noexcept
{
}
//////////////////////////////////////////////////////////////////////////////
-openni_wrapper::ImageBayerGRBG::~ImageBayerGRBG () noexcept
-{
-}
+openni_wrapper::ImageBayerGRBG::~ImageBayerGRBG () noexcept = default;
//////////////////////////////////////////////////////////////////////////////
bool
{
}
-ImageRGB24::~ImageRGB24 () noexcept
-{
-}
+ImageRGB24::~ImageRGB24 () noexcept = default;
void ImageRGB24::fillGrayscale (unsigned width, unsigned height, unsigned char* gray_buffer, unsigned gray_line_step) const
{
else // line by line
{
unsigned char* rgb_line = rgb_buffer;
- const unsigned char* src_line = static_cast<const unsigned char*> (image_md_->Data());
+ const auto* src_line = static_cast<const unsigned char*> (image_md_->Data());
for (unsigned yIdx = 0; yIdx < height; ++yIdx, rgb_line += rgb_line_step, src_line += line_size)
{
- memcpy (rgb_line, src_line, line_size);
+ std::copy(src_line, src_line + line_size, rgb_line);
}
}
}
unsigned dst_skip = rgb_line_step - width * 3; // skip of padding values in bytes
- XnRGB24Pixel* dst_line = reinterpret_cast<XnRGB24Pixel*> (rgb_buffer);
+ auto* dst_line = reinterpret_cast<XnRGB24Pixel*> (rgb_buffer);
const XnRGB24Pixel* src_line = image_md_->RGB24Data();
for (unsigned yIdx = 0; yIdx < height; ++yIdx, src_line += src_skip)
if (dst_skip != 0)
{
// use bytes to skip rather than XnRGB24Pixel's, since line_step does not need to be multiple of 3
- unsigned char* temp = reinterpret_cast <unsigned char*> (dst_line);
+ auto* temp = reinterpret_cast <unsigned char*> (dst_line);
dst_line = reinterpret_cast <XnRGB24Pixel*> (temp + dst_skip);
}
}
{
}
-ImageYUV422::~ImageYUV422 () noexcept
-{
-}
+ImageYUV422::~ImageYUV422 () noexcept = default;
bool ImageYUV422::isResizingSupported (unsigned input_width, unsigned input_height, unsigned output_width, unsigned output_height) const
{
{
imageDepthImageCallback (image, depth_image);
});
- openni_wrapper::DeviceKinect* kinect = dynamic_cast<openni_wrapper::DeviceKinect*> (device_.get ());
+ auto* kinect = dynamic_cast<openni_wrapper::DeviceKinect*> (device_.get ());
if (kinect)
kinect->setDebayeringMethod (openni_wrapper::ImageBayerGRBG::EdgeAware);
}
bool
pcl::OpenNIGrabber::mapConfigMode2XnMode (int mode, XnMapOutputMode &xnmode) const
{
- std::map<int, XnMapOutputMode>::const_iterator it = config2xn_map_.find (mode);
+ auto it = config2xn_map_.find (mode);
if (it != config2xn_map_.end ())
{
xnmode = it->second;
io::raw_close (tar_fd_);
tar_fd_ = -1;
tar_offset_ = 0;
- memset (&tar_header_.file_name[0], 0, 512);
+ tar_header_ = pcl::io::TARHeader{};
}
///////////////////////////////////////////////////////////////////////////////////////////
#include <pcl/io/low_level_io.h>
#include <pcl/io/lzf.h>
#include <pcl/io/pcd_io.h>
+#include <pcl/io/split.h>
#include <pcl/console/time.h>
#include <cstring>
#include <cerrno>
#include <boost/filesystem.hpp> // for permissions
-#include <boost/algorithm/string.hpp> // for split
///////////////////////////////////////////////////////////////////////////////////////////
void
// By default, assume that there are _no_ invalid (e.g., NaN) points
//cloud.is_dense = true;
+ // Used to determine if a value has been read
+ bool width_read = false;
+ bool height_read = false;
+
std::size_t nr_points = 0;
std::string line;
continue;
// Tokenize the line
- boost::trim (line);
- boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
+ pcl::split (st, line, "\t\r ");
std::stringstream sstream (line);
sstream.imbue (std::locale::classic ());
int col_count;
sstream >> col_count;
if (col_count < 1)
- throw "Invalid COUNT value specified.";
+ PCL_WARN("[pcl::PCDReader::readHeader] Invalid COUNT value specified (%i, should be larger than 0). This field will be removed.\n", col_count);
cloud.fields[i].count = col_count;
offset += col_count * field_sizes[i];
}
sstream >> cloud.width;
if (sstream.fail ())
throw "Invalid WIDTH value specified.";
+ width_read = true;
if (cloud.point_step != 0)
cloud.row_step = cloud.point_step * cloud.width; // row_step only makes sense for organized datasets
continue;
if (line_type.substr (0, 6) == "HEIGHT")
{
sstream >> cloud.height;
+ if (sstream.fail ())
+ throw "Invalid HEIGHT value specified.";
+ height_read = true;
continue;
}
PCL_ERROR ("[pcl::PCDReader::readHeader] %s\n", exception);
return (-1);
}
+ cloud.fields.erase(std::remove_if(cloud.fields.begin(), cloud.fields.end(),
+ [](const pcl::PCLPointField& field)->bool { return field.count < 1; }),
+ cloud.fields.end());
- // Exit early: if no points have been given, there's no sense to read or check anything anymore
if (nr_points == 0)
{
- PCL_ERROR ("[pcl::PCDReader::readHeader] No points to read\n");
- return (-1);
+ PCL_WARN ("[pcl::PCDReader::readHeader] No points to read\n");
}
// Compatibility with older PCD file versions
- if (cloud.width == 0 && cloud.height == 0)
+ if (!width_read && !height_read)
{
cloud.width = nr_points;
cloud.height = 1;
//assert (cloud.row_step != 0); // If row_step = 0, either point_step was not set or width is 0
// if both height/width are not given, assume an unorganized dataset
- if (cloud.height == 0)
+ if (!height_read)
{
cloud.height = 1;
PCL_WARN ("[pcl::PCDReader::readHeader] no HEIGHT given, setting to 1 (unorganized).\n");
std::istringstream is;
is.imbue (std::locale::classic ());
+ st.reserve(elems_per_line);
+
try
{
while (idx < nr_points && !fs.eof ())
continue;
// Tokenize the line
- boost::trim (line);
- boost::split (st, line, boost::is_any_of ("\t\r "), boost::token_compress_on);
+ pcl::split(st, line, "\r\t ");
if (st.size () != elems_per_line) // If this is not checked, an exception might occur while accessing st
{
}
for (uindex_t c = 0; c < cloud.fields[d].count; ++c)
{
+#define COPY_STRING(CASE_LABEL) \
+ case CASE_LABEL: { \
+ copyStringValue<pcl::traits::asType_t<CASE_LABEL>>( \
+ st.at(total + c), cloud, idx, d, c, is); \
+ break; \
+ }
switch (cloud.fields[d].datatype)
{
- case pcl::PCLPointField::INT8:
- {
- copyStringValue<pcl::traits::asType<pcl::PCLPointField::INT8>::type> (
- st.at (total + c), cloud, idx, d, c, is);
- break;
- }
- case pcl::PCLPointField::UINT8:
- {
- copyStringValue<pcl::traits::asType<pcl::PCLPointField::UINT8>::type> (
- st.at (total + c), cloud, idx, d, c, is);
- break;
- }
- case pcl::PCLPointField::INT16:
- {
- copyStringValue<pcl::traits::asType<pcl::PCLPointField::INT16>::type> (
- st.at (total + c), cloud, idx, d, c, is);
- break;
- }
- case pcl::PCLPointField::UINT16:
- {
- copyStringValue<pcl::traits::asType<pcl::PCLPointField::UINT16>::type> (
- st.at (total + c), cloud, idx, d, c, is);
- break;
- }
- case pcl::PCLPointField::INT32:
- {
- copyStringValue<pcl::traits::asType<pcl::PCLPointField::INT32>::type> (
- st.at (total + c), cloud, idx, d, c, is);
- break;
- }
- case pcl::PCLPointField::UINT32:
- {
- copyStringValue<pcl::traits::asType<pcl::PCLPointField::UINT32>::type> (
- st.at (total + c), cloud, idx, d, c, is);
- break;
- }
- case pcl::PCLPointField::FLOAT32:
- {
- copyStringValue<pcl::traits::asType<pcl::PCLPointField::FLOAT32>::type> (
- st.at (total + c), cloud, idx, d, c, is);
- break;
- }
- case pcl::PCLPointField::FLOAT64:
- {
- copyStringValue<pcl::traits::asType<pcl::PCLPointField::FLOAT64>::type> (
- st.at (total + c), cloud, idx, d, c, is);
- break;
- }
+ COPY_STRING(pcl::PCLPointField::BOOL)
+ COPY_STRING(pcl::PCLPointField::INT8)
+ COPY_STRING(pcl::PCLPointField::UINT8)
+ COPY_STRING(pcl::PCLPointField::INT16)
+ COPY_STRING(pcl::PCLPointField::UINT16)
+ COPY_STRING(pcl::PCLPointField::INT32)
+ COPY_STRING(pcl::PCLPointField::UINT32)
+ COPY_STRING(pcl::PCLPointField::INT64)
+ COPY_STRING(pcl::PCLPointField::UINT64)
+ COPY_STRING(pcl::PCLPointField::FLOAT32)
+ COPY_STRING(pcl::PCLPointField::FLOAT64)
default:
PCL_WARN ("[pcl::PCDReader::read] Incorrect field data type specified (%d)!\n",cloud.fields[d].datatype);
break;
}
+#undef COPY_STRING
}
total += cloud.fields[d].count; // jump over this many elements in the string token
}
cloud.data.resize (uncompressed_size);
}
- unsigned int data_size = static_cast<unsigned int> (cloud.data.size ());
+ auto data_size = static_cast<unsigned int> (cloud.data.size ());
std::vector<char> buf (data_size);
// The size of the uncompressed data better be the same as what we stored in the header
unsigned int tmp_size = pcl::lzfDecompress (&map[data_idx + 8], compressed_size, &buf[0], data_size);
memcpy (&cloud.data[0], &map[0] + data_idx, cloud.data.size ());
// Extra checks (not needed for ASCII)
- int point_size = static_cast<int> (cloud.data.size () / (cloud.height * cloud.width));
+ int point_size = (cloud.width * cloud.height == 0) ? 0 : static_cast<int> (cloud.data.size () / (cloud.height * cloud.width));
// Once copied, we need to go over each field and check if it has NaN/Inf values and assign cloud.is_dense to true or false
for (uindex_t i = 0; i < cloud.width * cloud.height; ++i)
{
{
for (uindex_t c = 0; c < cloud.fields[d].count; ++c)
{
+#define SET_CLOUD_DENSE(CASE_LABEL) \
+ case CASE_LABEL: { \
+ if (!isValueFinite<pcl::traits::asType_t<CASE_LABEL>>(cloud, i, point_size, d, c)) \
+ cloud.is_dense = false; \
+ break; \
+ }
switch (cloud.fields[d].datatype)
{
- case pcl::PCLPointField::INT8:
- {
- if (!isValueFinite<pcl::traits::asType<pcl::PCLPointField::INT8>::type> (cloud, i, point_size, d, c))
- cloud.is_dense = false;
- break;
- }
- case pcl::PCLPointField::UINT8:
- {
- if (!isValueFinite<pcl::traits::asType<pcl::PCLPointField::UINT8>::type> (cloud, i, point_size, d, c))
- cloud.is_dense = false;
- break;
- }
- case pcl::PCLPointField::INT16:
- {
- if (!isValueFinite<pcl::traits::asType<pcl::PCLPointField::INT16>::type> (cloud, i, point_size, d, c))
- cloud.is_dense = false;
- break;
- }
- case pcl::PCLPointField::UINT16:
- {
- if (!isValueFinite<pcl::traits::asType<pcl::PCLPointField::UINT16>::type> (cloud, i, point_size, d, c))
- cloud.is_dense = false;
- break;
- }
- case pcl::PCLPointField::INT32:
- {
- if (!isValueFinite<pcl::traits::asType<pcl::PCLPointField::INT32>::type> (cloud, i, point_size, d, c))
- cloud.is_dense = false;
- break;
- }
- case pcl::PCLPointField::UINT32:
- {
- if (!isValueFinite<pcl::traits::asType<pcl::PCLPointField::UINT32>::type> (cloud, i, point_size, d, c))
- cloud.is_dense = false;
- break;
- }
- case pcl::PCLPointField::FLOAT32:
- {
- if (!isValueFinite<pcl::traits::asType<pcl::PCLPointField::FLOAT32>::type> (cloud, i, point_size, d, c))
- cloud.is_dense = false;
- break;
- }
- case pcl::PCLPointField::FLOAT64:
- {
- if (!isValueFinite<pcl::traits::asType<pcl::PCLPointField::FLOAT64>::type> (cloud, i, point_size, d, c))
- cloud.is_dense = false;
- break;
- }
+ SET_CLOUD_DENSE(pcl::PCLPointField::BOOL)
+ SET_CLOUD_DENSE(pcl::PCLPointField::INT8)
+ SET_CLOUD_DENSE(pcl::PCLPointField::UINT8)
+ SET_CLOUD_DENSE(pcl::PCLPointField::INT16)
+ SET_CLOUD_DENSE(pcl::PCLPointField::UINT16)
+ SET_CLOUD_DENSE(pcl::PCLPointField::INT32)
+ SET_CLOUD_DENSE(pcl::PCLPointField::UINT32)
+ SET_CLOUD_DENSE(pcl::PCLPointField::INT64)
+ SET_CLOUD_DENSE(pcl::PCLPointField::UINT64)
+ SET_CLOUD_DENSE(pcl::PCLPointField::FLOAT32)
+ SET_CLOUD_DENSE(pcl::PCLPointField::FLOAT64)
}
+#undef SET_CLOUD_DENSE
}
}
}
return (-1);
}
#else
- unsigned char *map = static_cast<unsigned char*> (::mmap (nullptr, mmap_size, PROT_READ, MAP_SHARED, fd, 0));
+ auto *map = static_cast<unsigned char*> (::mmap (nullptr, mmap_size, PROT_READ, MAP_SHARED, fd, 0));
if (map == reinterpret_cast<unsigned char*> (-1)) // MAP_FAILED
{
io::raw_close (fd);
{
if (cloud.data.empty ())
{
- PCL_ERROR ("[pcl::PCDWriter::writeASCII] Input point cloud has no data!\n");
+ PCL_WARN ("[pcl::PCDWriter::writeASCII] Input point cloud has no data!\n");
+ }
+ if (cloud.fields.empty())
+ {
+ PCL_ERROR ("[pcl::PCDWriter::writeASCII] Input point cloud has no field data!\n");
return (-1);
}
setLockingPermissions (file_name, file_lock);
int nr_points = cloud.width * cloud.height;
- int point_size = static_cast<int> (cloud.data.size () / nr_points);
+ int point_size = (nr_points == 0) ? 0 : static_cast<int> (cloud.data.size () / nr_points);
// Write the header information
fs << generateHeaderASCII (cloud, origin, orientation) << "DATA ascii\n";
for (int c = 0; c < count; ++c)
{
- switch (cloud.fields[d].datatype)
- {
- case pcl::PCLPointField::INT8:
- {
- copyValueString<pcl::traits::asType<pcl::PCLPointField::INT8>::type>(cloud, i, point_size, d, c, stream);
- break;
- }
- case pcl::PCLPointField::UINT8:
- {
- copyValueString<pcl::traits::asType<pcl::PCLPointField::UINT8>::type>(cloud, i, point_size, d, c, stream);
- break;
- }
- case pcl::PCLPointField::INT16:
- {
- copyValueString<pcl::traits::asType<pcl::PCLPointField::INT16>::type>(cloud, i, point_size, d, c, stream);
- break;
- }
- case pcl::PCLPointField::UINT16:
- {
- copyValueString<pcl::traits::asType<pcl::PCLPointField::UINT16>::type>(cloud, i, point_size, d, c, stream);
- break;
- }
- case pcl::PCLPointField::INT32:
- {
- copyValueString<pcl::traits::asType<pcl::PCLPointField::INT32>::type>(cloud, i, point_size, d, c, stream);
- break;
- }
- case pcl::PCLPointField::UINT32:
- {
- copyValueString<pcl::traits::asType<pcl::PCLPointField::UINT32>::type>(cloud, i, point_size, d, c, stream);
- break;
- }
- case pcl::PCLPointField::FLOAT32:
- {
- /*
- * Despite the float type, store the rgb field as uint32
- * because several fully opaque color values are mapped to
- * nan.
- */
- if ("rgb" == cloud.fields[d].name)
- copyValueString<pcl::traits::asType<pcl::PCLPointField::UINT32>::type>(cloud, i, point_size, d, c, stream);
- else
- copyValueString<pcl::traits::asType<pcl::PCLPointField::FLOAT32>::type>(cloud, i, point_size, d, c, stream);
- break;
- }
- case pcl::PCLPointField::FLOAT64:
- {
- copyValueString<pcl::traits::asType<pcl::PCLPointField::FLOAT64>::type>(cloud, i, point_size, d, c, stream);
- break;
- }
- default:
- PCL_WARN ("[pcl::PCDWriter::writeASCII] Incorrect field data type specified (%d)!\n", cloud.fields[d].datatype);
- break;
+#define COPY_VALUE(CASE_LABEL) \
+ case CASE_LABEL: { \
+ copyValueString<pcl::traits::asType_t<CASE_LABEL>>( \
+ cloud, i, point_size, d, c, stream); \
+ break; \
+ }
+ switch (cloud.fields[d].datatype) {
+ COPY_VALUE(pcl::PCLPointField::BOOL)
+ COPY_VALUE(pcl::PCLPointField::INT8)
+ COPY_VALUE(pcl::PCLPointField::UINT8)
+ COPY_VALUE(pcl::PCLPointField::INT16)
+ COPY_VALUE(pcl::PCLPointField::UINT16)
+ COPY_VALUE(pcl::PCLPointField::INT32)
+ COPY_VALUE(pcl::PCLPointField::UINT32)
+ COPY_VALUE(pcl::PCLPointField::INT64)
+ COPY_VALUE(pcl::PCLPointField::UINT64)
+ COPY_VALUE(pcl::PCLPointField::FLOAT64)
+
+ case pcl::PCLPointField::FLOAT32: {
+ /*
+ * Despite the float type, store the rgb field as uint32
+ * because several fully opaque color values are mapped to
+ * nan.
+ */
+ if ("rgb" == cloud.fields[d].name)
+ copyValueString<pcl::traits::asType_t<pcl::PCLPointField::UINT32>>(
+ cloud, i, point_size, d, c, stream);
+ else
+ copyValueString<pcl::traits::asType_t<pcl::PCLPointField::FLOAT32>>(
+ cloud, i, point_size, d, c, stream);
+ break;
+ }
+ default:
+ PCL_WARN("[pcl::PCDWriter::writeASCII] Incorrect field data type specified "
+ "(%d)!\n",
+ cloud.fields[d].datatype);
+ break;
}
+#undef COPY_VALUE
- if (d < cloud.fields.size () - 1 || c < static_cast<int> (cloud.fields[d].count) - 1)
+ if ((d < cloud.fields.size() - 1) ||
+ (c < static_cast<int>(cloud.fields[d].count) - 1))
stream << " ";
}
}
// Copy the stream, trim it, and write it to disk
- std::string result = stream.str ();
- boost::trim (result);
- stream.str ("");
+ std::string result = stream.str();
+ boost::trim(result);
+ stream.str("");
fs << result << "\n";
}
fs.close (); // Close file
{
if (cloud.data.empty ())
{
- PCL_ERROR ("[pcl::PCDWriter::writeBinary] Input point cloud has no data!\n");
+ PCL_WARN ("[pcl::PCDWriter::writeBinary] Input point cloud has no data!\n");
+ }
+ if (cloud.fields.empty())
+ {
+ PCL_ERROR ("[pcl::PCDWriter::writeBinary] Input point cloud has no field data!\n");
return (-1);
}
+
std::streamoff data_idx = 0;
std::ostringstream oss;
oss.imbue (std::locale::classic ());
{
if (cloud.data.empty ())
{
- PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Input point cloud has no data!\n");
+ PCL_WARN ("[pcl::PCDWriter::writeBinaryCompressed] Input point cloud has no data!\n");
+ }
+ if (cloud.fields.empty())
+ {
+ PCL_ERROR ("[pcl::PCDWriter::writeBinaryCompressed] Input point cloud has no field data!\n");
return (-1);
}
+
if (generateHeaderBinaryCompressed (os, cloud, origin, orientation))
{
return (-1);
}
std::vector<char> temp_buf (data_size * 3 / 2 + 8);
- // Compress the valid data
- unsigned int compressed_size = pcl::lzfCompress (&only_valid_data.front (),
- static_cast<unsigned int> (data_size),
- &temp_buf[8],
- data_size * 3 / 2);
- // Was the compression successful?
- if (compressed_size == 0)
- {
- return (-1);
+ if (data_size != 0) {
+ // Compress the valid data
+ unsigned int compressed_size = pcl::lzfCompress (&only_valid_data.front (),
+ static_cast<unsigned int> (data_size),
+ &temp_buf[8],
+ data_size * 3 / 2);
+ // Was the compression successful?
+ if (compressed_size == 0)
+ {
+ return (-1);
+ }
+ memcpy (&temp_buf[0], &compressed_size, 4);
+ memcpy (&temp_buf[4], &data_size, 4);
+ temp_buf.resize (compressed_size + 8);
+ } else {
+ auto *header = reinterpret_cast<std::uint32_t*>(&temp_buf[0]);
+ header[0] = 0; // compressed_size is 0
+ header[1] = 0; // data_size is 0
}
- memcpy (&temp_buf[0], &compressed_size, 4);
- memcpy (&temp_buf[4], &data_size, 4);
- temp_buf.resize (compressed_size + 8);
-
os.imbue (std::locale::classic ());
os << "DATA binary_compressed\n";
- std::copy (temp_buf.begin (), temp_buf.end (), std::ostream_iterator<char> (os));
+ std::copy (temp_buf.cbegin (), temp_buf.cend (), std::ostream_iterator<char> (os));
os.flush ();
return (os ? 0 : -1);
#include <pcl/common/io.h>
#include <pcl/io/ply_io.h>
+#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <functional>
cloud_->point_step += static_cast<std::uint32_t> (pcl::getFieldSize (pcl::traits::asEnum<Scalar>::value) * size);
}
-void
+bool
pcl::PLYReader::amendProperty (const std::string& old_name, const std::string& new_name, std::uint8_t new_datatype)
{
- auto finder = cloud_->fields.rbegin ();
- for (; finder != cloud_->fields.rend (); ++finder)
- if (finder->name == old_name)
- break;
- assert (finder != cloud_->fields.rend ());
- finder->name = new_name;
- if (new_datatype > 0 && new_datatype != finder->datatype)
- finder->datatype = new_datatype;
+ const auto fieldIndex = pcl::getFieldIndex(*cloud_, old_name);
+ if (fieldIndex == -1) {
+ return false;
+ }
+
+ auto& field = cloud_->fields[fieldIndex];
+
+ field.name = new_name;
+
+ if (new_datatype > 0 && new_datatype != field.datatype)
+ field.datatype = new_datatype;
+
+ return true;
}
namespace pcl
{
if ((property_name == "red") || (property_name == "diffuse_red"))
appendScalarProperty<pcl::io::ply::float32> ("rgb");
- return [=] (pcl::io::ply::uint8 color) { vertexColorCallback (property_name, color); };
+ return [this, property_name] (pcl::io::ply::uint8 color) { vertexColorCallback (property_name, color); };
}
if (property_name == "alpha")
{
- amendProperty ("rgb", "rgba", pcl::PCLPointField::UINT32);
+ if (!amendProperty("rgb", "rgba", pcl::PCLPointField::UINT32))
+ {
+ PCL_ERROR("[pcl::PLYReader::scalarPropertyDefinitionCallback] 'rgb' was not "
+ "found in cloud_->fields!,"
+ " can't amend property '%s' to get new type 'rgba' \n",
+ property_name.c_str());
+ return {};
+ }
+
return [this] (pcl::io::ply::uint8 alpha) { vertexAlphaCallback (alpha); };
}
if (property_name == "intensity")
template<typename Scalar> void
PLYReader::vertexScalarPropertyCallback (Scalar value)
{
- unsetDenseFlagIfNotFinite(value, cloud_);
-
- memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
- &value,
- sizeof (Scalar));
- vertex_offset_before_ += static_cast<int> (sizeof (Scalar));
+ try
+ {
+ unsetDenseFlagIfNotFinite(value, cloud_);
+ cloud_->at<Scalar>(vertex_count_, vertex_offset_before_) = value;
+ vertex_offset_before_ += static_cast<int> (sizeof (Scalar));
+ }
+ catch(const std::out_of_range&)
+ {
+ PCL_WARN ("[pcl::PLYReader::vertexScalarPropertyCallback] Incorrect data index specified (%lu)!\n", vertex_count_ * cloud_->point_step + vertex_offset_before_);
+ assert(false);
+ }
}
template <typename SizeType> void
template<typename ContentType> void
PLYReader::vertexListPropertyContentCallback (ContentType value)
{
- unsetDenseFlagIfNotFinite(value, cloud_);
-
- memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
- &value,
- sizeof (ContentType));
- vertex_offset_before_ += static_cast<int> (sizeof (ContentType));
+ try
+ {
+ unsetDenseFlagIfNotFinite(value, cloud_);
+ cloud_->at<ContentType>(vertex_count_, vertex_offset_before_) = value;
+ vertex_offset_before_ += static_cast<int> (sizeof (ContentType));
+ }
+ catch(const std::out_of_range&)
+ {
+ PCL_WARN ("[pcl::PLYReader::vertexListPropertyContentCallback] Incorrect data index specified (%lu)!\n", vertex_count_ * cloud_->point_step + vertex_offset_before_);
+ assert(false);
+ }
}
template <typename SizeType, typename ContentType>
{
b_ = std::int32_t (color);
std::int32_t rgb = r_ << 16 | g_ << 8 | b_;
- memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + rgb_offset_before_],
- &rgb,
- sizeof (pcl::io::ply::float32));
- vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::float32));
+ try
+ {
+ cloud_->at<std::int32_t>(vertex_count_, rgb_offset_before_) = rgb;
+ vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::float32));
+ }
+ catch(const std::out_of_range&)
+ {
+ PCL_WARN ("[pcl::PLYReader::vertexColorCallback] Incorrect data index specified (%lu)!\n", vertex_count_ * cloud_->point_step + rgb_offset_before_);
+ assert(false);
+ }
}
}
void
pcl::PLYReader::vertexAlphaCallback (pcl::io::ply::uint8 alpha)
{
- a_ = std::uint32_t (alpha);
// get anscient rgb value and store it in rgba
- memcpy (&rgba_,
- &cloud_->data[vertex_count_ * cloud_->point_step + rgb_offset_before_],
- sizeof (pcl::io::ply::float32));
+ rgba_ = cloud_->at<std::uint32_t>(vertex_count_, rgb_offset_before_);
// append alpha
+ a_ = std::uint32_t (alpha);
rgba_ |= a_ << 24;
// put rgba back
- memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + rgb_offset_before_],
- &rgba_,
- sizeof (std::uint32_t));
+ cloud_->at<std::uint32_t>(vertex_count_, rgb_offset_before_) = rgba_;
}
void
pcl::PLYReader::vertexIntensityCallback (pcl::io::ply::uint8 intensity)
{
pcl::io::ply::float32 intensity_ (intensity);
- memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
- &intensity_,
- sizeof (pcl::io::ply::float32));
+ cloud_->at<pcl::io::ply::float32>(vertex_count_, vertex_offset_before_) = intensity_;
vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::float32));
}
{
for (const auto &field : cloud_->fields)
if (field.datatype == ::pcl::PCLPointField::FLOAT32)
- memcpy (&data[r * cloud_->point_step + field.offset],
+ {
+ const auto idx = r * cloud_->point_step + field.offset;
+ if (idx + sizeof (float) > data.size())
+ {
+ PCL_ERROR ("[pcl::PLYReader::read] invalid data index (%lu)!\n", idx);
+ return (-1);
+ }
+ memcpy (&data[idx],
reinterpret_cast<const char*> (&f_nan), sizeof (float));
+ }
else if (field.datatype == ::pcl::PCLPointField::FLOAT64)
- memcpy (&data[r * cloud_->point_step + field.offset],
+ {
+ const auto idx = r * cloud_->point_step + field.offset;
+ if (idx + sizeof (double) > data.size())
+ {
+ PCL_ERROR ("[pcl::PLYReader::read] invalid data index (%lu)!\n", idx);
+ return (-1);
+ }
+ memcpy (&data[idx],
reinterpret_cast<const char*> (&d_nan), sizeof (double));
+ }
else
- memset (&data[r * cloud_->point_step + field.offset], 0,
- pcl::getFieldSize (field.datatype) * field.count);
+ {
+ const auto idx = r * cloud_->point_step + field.offset;
+ if (idx + pcl::getFieldSize (field.datatype) * field.count > data.size())
+ {
+ PCL_ERROR ("[pcl::PLYReader::read] invalid data index (%lu)!\n", idx);
+ return (-1);
+ }
+ std::fill_n(&data[idx],
+ pcl::getFieldSize (field.datatype) * field.count, 0);
+ }
}
else
- memcpy (&data[r* cloud_->point_step], &cloud_->data[(*range_grid_)[r][0] * cloud_->point_step], cloud_->point_step);
+ {
+ const auto srcIdx = (*range_grid_)[r][0] * cloud_->point_step;
+ if (srcIdx + cloud_->point_step > cloud_->data.size())
+ {
+ PCL_ERROR ("[pcl::PLYReader::read] invalid data index (%lu)!\n", srcIdx);
+ return (-1);
+ }
+ memcpy (&data[r* cloud_->point_step], &cloud_->data[srcIdx], cloud_->point_step);
+ }
}
cloud_->data.swap (data);
}
{
for (const auto &field : cloud_->fields)
if (field.datatype == ::pcl::PCLPointField::FLOAT32)
- memcpy (&data[r * cloud_->point_step + field.offset],
+ {
+ const auto idx = r * cloud_->point_step + field.offset;
+ if (idx + sizeof (float) > data.size())
+ {
+ PCL_ERROR ("[pcl::PLYReader::read] invalid data index (%lu)!\n", idx);
+ return (-1);
+ }
+ memcpy (&data[idx],
reinterpret_cast<const char*> (&f_nan), sizeof (float));
+ }
else if (field.datatype == ::pcl::PCLPointField::FLOAT64)
- memcpy (&data[r * cloud_->point_step + field.offset],
+ {
+ const auto idx = r * cloud_->point_step + field.offset;
+ if (idx + sizeof (double) > data.size())
+ {
+ PCL_ERROR ("[pcl::PLYReader::read] invalid data index (%lu)!\n", idx);
+ return (-1);
+ }
+ memcpy (&data[idx],
reinterpret_cast<const char*> (&d_nan), sizeof (double));
+ }
else
- memset (&data[r * cloud_->point_step + field.offset], 0,
- pcl::getFieldSize (field.datatype) * field.count);
+ {
+ const auto idx = r * cloud_->point_step + field.offset;
+ if (idx + pcl::getFieldSize (field.datatype) * field.count > data.size())
+ {
+ PCL_ERROR ("[pcl::PLYReader::read] invalid data index (%lu)!\n", idx);
+ return (-1);
+ }
+ std::fill_n(&data[idx],
+ pcl::getFieldSize (field.datatype) * field.count, 0);
+ }
}
else
- memcpy (&data[r* cloud_->point_step], &cloud_->data[(*range_grid_)[r][0] * cloud_->point_step], cloud_->point_step);
+ {
+ const auto srcIdx = (*range_grid_)[r][0] * cloud_->point_step;
+ if (srcIdx + cloud_->point_step > cloud_->data.size())
+ {
+ PCL_ERROR ("[pcl::PLYReader::read] invalid data index (%lu)!\n", srcIdx);
+ return (-1);
+ }
+ memcpy (&data[r* cloud_->point_step], &cloud_->data[srcIdx], cloud_->point_step);
+ }
}
cloud_->data.swap (data);
}
}
unsigned int nr_points = cloud.width * cloud.height;
- unsigned int point_size = static_cast<unsigned int> (cloud.data.size () / nr_points);
// Write the header information if available
if (use_camera)
{
fs << generateHeader (cloud, origin, orientation, false, use_camera, nr_points);
- writeContentWithCameraASCII (nr_points, point_size, cloud, origin, orientation, fs);
+ writeContentWithCameraASCII (nr_points, cloud, origin, orientation, fs);
}
else
{
std::ostringstream os;
int nr_valid_points;
- writeContentWithRangeGridASCII (nr_points, point_size, cloud, os, nr_valid_points);
+ writeContentWithRangeGridASCII (nr_points, cloud, os, nr_valid_points);
fs << generateHeader (cloud, origin, orientation, false, use_camera, nr_valid_points);
fs << os.str ();
}
void
pcl::PLYWriter::writeContentWithCameraASCII (int nr_points,
- int point_size,
const pcl::PCLPointCloud2 &cloud,
const Eigen::Vector4f &origin,
const Eigen::Quaternionf &orientation,
{
case pcl::PCLPointField::INT8:
{
- char value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (char)], sizeof (char));
- fs << boost::numeric_cast<int> (value);
+ fs << boost::numeric_cast<int> (cloud.at<char>(i, cloud.fields[d].offset + c * sizeof (char)));
break;
}
case pcl::PCLPointField::UINT8:
{
- unsigned char value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned char)], sizeof (unsigned char));
- fs << boost::numeric_cast<int> (value);
+ fs << boost::numeric_cast<int> (cloud.at<unsigned char>(i, cloud.fields[d].offset + c * sizeof (unsigned char)));
break;
}
case pcl::PCLPointField::INT16:
{
- short value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (short)], sizeof (short));
- fs << boost::numeric_cast<int> (value);
+ fs << boost::numeric_cast<int> (cloud.at<short>(i, cloud.fields[d].offset + c * sizeof (short)));
break;
}
case pcl::PCLPointField::UINT16:
{
- unsigned short value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned short)], sizeof (unsigned short));
- fs << boost::numeric_cast<int> (value);
+ fs << boost::numeric_cast<int> (cloud.at<unsigned short>(i, cloud.fields[d].offset + c * sizeof (unsigned short)));
break;
}
case pcl::PCLPointField::INT32:
{
- int value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (int)], sizeof (int));
- fs << value;
+ fs << cloud.at<int>(i, cloud.fields[d].offset + c * sizeof (int));
break;
}
case pcl::PCLPointField::UINT32:
{
if (cloud.fields[d].name.find ("rgba") == std::string::npos)
{
- unsigned int value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned int)], sizeof (unsigned int));
- fs << value;
+ fs << cloud.at<unsigned int>(i, cloud.fields[d].offset + c * sizeof (unsigned int));
}
else
{
- pcl::RGB color;
- memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned int)], sizeof (pcl::RGB));
- int r = color.r;
- int g = color.g;
- int b = color.b;
- int a = color.a;
- fs << r << " " << g << " " << b << " " << a;
+ const auto& color = cloud.at<pcl::RGB>(i, cloud.fields[d].offset + c * sizeof (pcl::RGB));
+ fs << static_cast<int>(color.r) << " " << static_cast<int>(color.g) << " " << static_cast<int>(color.b) << " " << static_cast<int>(color.a);
}
break;
}
{
if (cloud.fields[d].name.find ("rgb") == std::string::npos)
{
- float value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
- fs << value;
+ fs << cloud.at<float>(i, cloud.fields[d].offset + c * sizeof (float));
}
else
{
- pcl::RGB color;
- memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (pcl::RGB));
- int r = color.r;
- int g = color.g;
- int b = color.b;
- fs << r << " " << g << " " << b;
+ const auto& color = cloud.at<pcl::RGB>(i, cloud.fields[d].offset + c * sizeof (pcl::RGB));
+ fs << static_cast<int>(color.r) << " " << static_cast<int>(color.g) << " " << static_cast<int>(color.b);
}
break;
}
case pcl::PCLPointField::FLOAT64:
{
- double value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (double)], sizeof (double));
- fs << value;
+ fs << cloud.at<double>(i, cloud.fields[d].offset + c * sizeof (double));
break;
}
default:
void
pcl::PLYWriter::writeContentWithRangeGridASCII (int nr_points,
- int point_size,
const pcl::PCLPointCloud2 &cloud,
std::ostringstream& fs,
int& valid_points)
{
case pcl::PCLPointField::INT8:
{
- char value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (char)], sizeof (char));
- line << boost::numeric_cast<int> (value);
+ line << boost::numeric_cast<int> (cloud.at<char>(i, cloud.fields[d].offset + c * sizeof (char)));
break;
}
case pcl::PCLPointField::UINT8:
{
- unsigned char value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned char)], sizeof (unsigned char));
- line << boost::numeric_cast<int> (value);
+ line << boost::numeric_cast<int> (cloud.at<unsigned char>(i, cloud.fields[d].offset + c * sizeof (unsigned char)));
break;
}
case pcl::PCLPointField::INT16:
{
- short value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (short)], sizeof (short));
- line << boost::numeric_cast<int> (value);
+ line << boost::numeric_cast<int> (cloud.at<short>(i, cloud.fields[d].offset + c * sizeof (short)));
break;
}
case pcl::PCLPointField::UINT16:
{
- unsigned short value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned short)], sizeof (unsigned short));
- line << boost::numeric_cast<int> (value);
+ line << boost::numeric_cast<int> (cloud.at<unsigned short>(i, cloud.fields[d].offset + c * sizeof (unsigned short)));
break;
}
case pcl::PCLPointField::INT32:
{
- int value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (int)], sizeof (int));
- line << value;
+ line << cloud.at<int>(i, cloud.fields[d].offset + c * sizeof (int));
break;
}
case pcl::PCLPointField::UINT32:
{
if (cloud.fields[d].name.find ("rgba") == std::string::npos)
{
- unsigned int value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned int)], sizeof (unsigned int));
- line << value;
+ line << cloud.at<unsigned int>(i, cloud.fields[d].offset + c * sizeof (unsigned int));
}
else
{
- pcl::RGB color;
- memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned int)], sizeof (pcl::RGB));
- int r = color.r;
- int g = color.g;
- int b = color.b;
- int a = color.a;
- line << r << " " << g << " " << b << " " << a;
+ const auto& color = cloud.at<pcl::RGB>(i, cloud.fields[d].offset + c * sizeof (pcl::RGB));
+ line << static_cast<int>(color.r) << " " << static_cast<int>(color.g) << " " << static_cast<int>(color.b) << " " << static_cast<int>(color.a);
}
break;
}
{
if (cloud.fields[d].name.find ("rgb") == std::string::npos)
{
- float value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
+ const float& value = cloud.at<float>(i, cloud.fields[d].offset + c * sizeof (float));
// Test if x-coordinate is NaN, thus an invalid point
if ("x" == cloud.fields[d].name)
{
}
else
{
- pcl::RGB color;
- memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (pcl::RGB));
- int r = color.r;
- int g = color.g;
- int b = color.b;
- line << r << " " << g << " " << b;
+ const auto& color = cloud.at<pcl::RGB>(i, cloud.fields[d].offset + c * sizeof (pcl::RGB));
+ line << static_cast<int>(color.r) << " " << static_cast<int>(color.g) << " " << static_cast<int>(color.b);
}
break;
}
case pcl::PCLPointField::FLOAT64:
{
- double value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (double)], sizeof (double));
- line << value;
+ line << cloud.at<double>(i, cloud.fields[d].offset + c * sizeof (double));
break;
}
default:
for (int i = 0; i < nr_points; ++i)
{
fs << grids [i].size ();
- for (std::vector <int>::const_iterator it = grids [i].begin ();
- it != grids [i].end ();
- ++it)
- fs << " " << *it;
+ for (const auto& grid : grids [i]) {
+ fs << " " << grid;
+ }
fs << '\n';
}
}
}
unsigned int nr_points = cloud.width * cloud.height;
- unsigned int point_size = static_cast<unsigned int> (cloud.data.size () / nr_points);
// Compute the range_grid, if necessary, and then write out the PLY header
bool doRangeGrid = !use_camera && cloud.height > 1;
{
for (std::size_t i=0; i < nr_points; ++i)
{
- float value;
- memcpy(&value, &cloud.data[i * point_size + cloud.fields[xfield].offset], sizeof(float));
+ const float& value = cloud.at<float>(i, cloud.fields[xfield].offset);
if (std::isfinite(value))
{
rangegrid[i] = valid_points;
{
case pcl::PCLPointField::INT8:
{
- char value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (char)], sizeof (char));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (char));
+ fpout.write (&cloud.at<char>(i, cloud.fields[d].offset + (total + c) * sizeof (char)), sizeof (char));
break;
}
case pcl::PCLPointField::UINT8:
{
- unsigned char value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (unsigned char)], sizeof (unsigned char));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (unsigned char));
+ fpout.write (reinterpret_cast<const char*> (&cloud.at<unsigned char>(i, cloud.fields[d].offset + (total + c) * sizeof (unsigned char))), sizeof (unsigned char));
break;
}
case pcl::PCLPointField::INT16:
{
- short value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (short)], sizeof (short));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (short));
+ fpout.write (reinterpret_cast<const char*> (&cloud.at<short>(i, cloud.fields[d].offset + (total + c) * sizeof (short))), sizeof (short));
break;
}
case pcl::PCLPointField::UINT16:
{
- unsigned short value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (unsigned short)], sizeof (unsigned short));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (unsigned short));
+ fpout.write (reinterpret_cast<const char*> (&cloud.at<unsigned short>(i, cloud.fields[d].offset + (total + c) * sizeof (unsigned short))), sizeof (unsigned short));
break;
}
case pcl::PCLPointField::INT32:
{
- int value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (int)], sizeof (int));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (int));
+ fpout.write (reinterpret_cast<const char*> (&cloud.at<int>(i, cloud.fields[d].offset + (total + c) * sizeof (int))), sizeof (int));
break;
}
case pcl::PCLPointField::UINT32:
{
if (cloud.fields[d].name.find ("rgba") == std::string::npos)
{
- unsigned int value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (unsigned int)], sizeof (unsigned int));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (unsigned int));
+ fpout.write (reinterpret_cast<const char*> (&cloud.at<unsigned int>(i, cloud.fields[d].offset + (total + c) * sizeof (unsigned int))), sizeof (unsigned int));
}
else
{
- pcl::RGB color;
- memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (unsigned int)], sizeof (pcl::RGB));
- unsigned char r = color.r;
- unsigned char g = color.g;
- unsigned char b = color.b;
- unsigned char a = color.a;
- fpout.write (reinterpret_cast<const char*> (&r), sizeof (unsigned char));
- fpout.write (reinterpret_cast<const char*> (&g), sizeof (unsigned char));
- fpout.write (reinterpret_cast<const char*> (&b), sizeof (unsigned char));
- fpout.write (reinterpret_cast<const char*> (&a), sizeof (unsigned char));
+ const auto& color = cloud.at<pcl::RGB>(i, cloud.fields[d].offset + (total + c) * sizeof (pcl::RGB));
+ fpout.write (reinterpret_cast<const char*> (&color.r), sizeof (unsigned char));
+ fpout.write (reinterpret_cast<const char*> (&color.g), sizeof (unsigned char));
+ fpout.write (reinterpret_cast<const char*> (&color.b), sizeof (unsigned char));
+ fpout.write (reinterpret_cast<const char*> (&color.a), sizeof (unsigned char));
}
break;
}
{
if (cloud.fields[d].name.find ("rgb") == std::string::npos)
{
- float value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (float)], sizeof (float));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (float));
+ fpout.write (reinterpret_cast<const char*> (&cloud.at<float>(i, cloud.fields[d].offset + (total + c) * sizeof (float))), sizeof (float));
}
else
{
- pcl::RGB color;
- memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (float)], sizeof (pcl::RGB));
- unsigned char r = color.r;
- unsigned char g = color.g;
- unsigned char b = color.b;
- fpout.write (reinterpret_cast<const char*> (&r), sizeof (unsigned char));
- fpout.write (reinterpret_cast<const char*> (&g), sizeof (unsigned char));
- fpout.write (reinterpret_cast<const char*> (&b), sizeof (unsigned char));
+ const auto& color = cloud.at<pcl::RGB>(i, cloud.fields[d].offset + (total + c) * sizeof (pcl::RGB));
+ fpout.write (reinterpret_cast<const char*> (&color.r), sizeof (unsigned char));
+ fpout.write (reinterpret_cast<const char*> (&color.g), sizeof (unsigned char));
+ fpout.write (reinterpret_cast<const char*> (&color.b), sizeof (unsigned char));
}
break;
}
case pcl::PCLPointField::FLOAT64:
{
- double value;
- memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (double)], sizeof (double));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (double));
+ fpout.write (reinterpret_cast<const char*> (&cloud.at<double>(i, cloud.fields[d].offset + (total + c) * sizeof (double))), sizeof (double));
break;
}
default:
return (0);
}
+namespace pcl {
+namespace io {
+void writePLYHeader (std::ostream& fs, const pcl::PolygonMesh& mesh, const std::string& format) {
+ // Write header
+ fs << "ply";
+ fs << "\nformat " << format;
+ fs << "\ncomment PCL generated";
+ // Vertices
+ fs << "\nelement vertex "<< mesh.cloud.width * mesh.cloud.height;
+ for(const pcl::PCLPointField& field : mesh.cloud.fields) {
+ if(field.name == "x")
+ fs << "\nproperty float x";
+ else if(field.name == "y")
+ fs << "\nproperty float y";
+ else if(field.name == "z")
+ fs << "\nproperty float z";
+ else if(field.name == "rgb")
+ fs << "\nproperty uchar red"
+ "\nproperty uchar green"
+ "\nproperty uchar blue";
+ else if(field.name == "rgba")
+ fs << "\nproperty uchar red"
+ "\nproperty uchar green"
+ "\nproperty uchar blue"
+ "\nproperty uchar alpha";
+ else if(field.name == "normal_x")
+ fs << "\nproperty float nx";
+ else if(field.name == "normal_y")
+ fs << "\nproperty float ny";
+ else if(field.name == "normal_z")
+ fs << "\nproperty float nz";
+ else if(field.name == "curvature")
+ fs << "\nproperty float curvature";
+ else
+ PCL_WARN("[pcl::io::writePLYHeader] unknown field: %s\n", field.name.c_str());
+ }
+ // Faces
+ fs << "\nelement face "<< mesh.polygons.size ();
+ fs << "\nproperty list uchar int vertex_indices";
+ fs << "\nend_header\n";
+}
+} // namespace io
+} // namespace pcl
+
////////////////////////////////////////////////////////////////////////////////////////
int
pcl::io::savePLYFile (const std::string &file_name, const pcl::PolygonMesh &mesh, unsigned precision)
// number of points
std::size_t nr_points = mesh.cloud.width * mesh.cloud.height;
- std::size_t point_size = mesh.cloud.data.size () / nr_points;
- // number of faces
- std::size_t nr_faces = mesh.polygons.size ();
-
- // Write header
- fs << "ply";
- fs << "\nformat ascii 1.0";
- fs << "\ncomment PCL generated";
- // Vertices
- fs << "\nelement vertex "<< mesh.cloud.width * mesh.cloud.height;
- fs << "\nproperty float x"
- "\nproperty float y"
- "\nproperty float z";
- // Check if we have color on vertices
- int rgba_index = getFieldIndex (mesh.cloud, "rgba"),
- rgb_index = getFieldIndex (mesh.cloud, "rgb");
- if (rgba_index != -1)
- {
- fs << "\nproperty uchar red"
- "\nproperty uchar green"
- "\nproperty uchar blue"
- "\nproperty uchar alpha";
- }
- else if (rgb_index != -1)
- {
- fs << "\nproperty uchar red"
- "\nproperty uchar green"
- "\nproperty uchar blue";
- }
- // Check if we have normal on vertices
- int normal_x_index = getFieldIndex(mesh.cloud, "normal_x");
- int normal_y_index = getFieldIndex(mesh.cloud, "normal_y");
- int normal_z_index = getFieldIndex(mesh.cloud, "normal_z");
- if (normal_x_index != -1 && normal_y_index != -1 && normal_z_index != -1)
- {
- fs << "\nproperty float nx"
- "\nproperty float ny"
- "\nproperty float nz";
- }
- // Check if we have curvature on vertices
- int curvature_index = getFieldIndex(mesh.cloud, "curvature");
- if ( curvature_index != -1)
- {
- fs << "\nproperty float curvature";
- }
- // Faces
- fs << "\nelement face "<< nr_faces;
- fs << "\nproperty list uchar int vertex_indices";
- fs << "\nend_header\n";
+ pcl::io::writePLYHeader (fs, mesh, "ascii 1.0");
// Write down vertices
for (std::size_t i = 0; i < nr_points; ++i)
int xyz = 0;
for (std::size_t d = 0; d < mesh.cloud.fields.size (); ++d)
{
- int c = 0;
-
// adding vertex
if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) && (
mesh.cloud.fields[d].name == "x" ||
mesh.cloud.fields[d].name == "y" ||
mesh.cloud.fields[d].name == "z"))
{
- float value;
- memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
- fs << value;
+ fs << mesh.cloud.at<float>(i, mesh.cloud.fields[d].offset) << " ";
// if (++xyz == 3)
// break;
++xyz;
(mesh.cloud.fields[d].name == "rgb"))
{
- pcl::RGB color;
- memcpy (&color, &mesh.cloud.data[i * point_size + mesh.cloud.fields[rgb_index].offset + c * sizeof (float)], sizeof (RGB));
- fs << int (color.r) << " " << int (color.g) << " " << int (color.b);
+ const auto& color = mesh.cloud.at<RGB>(i, mesh.cloud.fields[d].offset);
+ fs << int (color.r) << " " << int (color.g) << " " << int (color.b) << " ";
}
else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::UINT32) &&
(mesh.cloud.fields[d].name == "rgba"))
{
- pcl::RGB color;
- memcpy (&color, &mesh.cloud.data[i * point_size + mesh.cloud.fields[rgba_index].offset + c * sizeof (std::uint32_t)], sizeof (RGB));
- fs << int (color.r) << " " << int (color.g) << " " << int (color.b) << " " << int (color.a);
+ const auto& color = mesh.cloud.at<RGB>(i, mesh.cloud.fields[d].offset);
+ fs << int (color.r) << " " << int (color.g) << " " << int (color.b) << " " << int (color.a) << " ";
}
else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) && (
mesh.cloud.fields[d].name == "normal_x" ||
mesh.cloud.fields[d].name == "normal_y" ||
mesh.cloud.fields[d].name == "normal_z"))
{
- float value;
- memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof(float)], sizeof(float));
- fs << value;
+ fs << mesh.cloud.at<float>(i, mesh.cloud.fields[d].offset) << " ";
}
else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) && (
mesh.cloud.fields[d].name == "curvature"))
{
- float value;
- memcpy(&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof(float)], sizeof(float));
- fs << value;
+ fs << mesh.cloud.at<float>(i, mesh.cloud.fields[d].offset) << " ";
}
- fs << " ";
}
if (xyz != 3)
{
}
// Write down faces
- for (std::size_t i = 0; i < nr_faces; i++)
+ PCL_DEBUG ("[pcl::io::savePLYFile] Saving %zu polygons/faces\n", mesh.polygons.size());
+ for (const pcl::Vertices& polygon : mesh.polygons)
{
- fs << mesh.polygons[i].vertices.size () << " ";
- for (std::size_t j = 0; j < mesh.polygons[i].vertices.size () - 1; ++j)
- fs << mesh.polygons[i].vertices[j] << " ";
- fs << mesh.polygons[i].vertices.back() << '\n';
+ fs << polygon.vertices.size ();
+ for (const auto& vertex : polygon.vertices)
+ fs << " " << vertex;
+ fs << '\n';
}
// Close file
// number of points
std::size_t nr_points = mesh.cloud.width * mesh.cloud.height;
- std::size_t point_size = mesh.cloud.data.size () / nr_points;
- // number of faces
- std::size_t nr_faces = mesh.polygons.size ();
-
- // Write header
- fs << "ply";
- fs << "\nformat " << (mesh.cloud.is_bigendian ? "binary_big_endian" : "binary_little_endian") << " 1.0";
- fs << "\ncomment PCL generated";
- // Vertices
- fs << "\nelement vertex "<< mesh.cloud.width * mesh.cloud.height;
- fs << "\nproperty float x"
- "\nproperty float y"
- "\nproperty float z";
- // Check if we have color on vertices
- int rgba_index = getFieldIndex (mesh.cloud, "rgba"),
- rgb_index = getFieldIndex (mesh.cloud, "rgb");
- if (rgba_index != -1)
- {
- fs << "\nproperty uchar red"
- "\nproperty uchar green"
- "\nproperty uchar blue"
- "\nproperty uchar alpha";
- }
- else if (rgb_index != -1)
- {
- fs << "\nproperty uchar red"
- "\nproperty uchar green"
- "\nproperty uchar blue";
- }
- // Check if we have normal on vertices
- int normal_x_index = getFieldIndex(mesh.cloud, "normal_x");
- int normal_y_index = getFieldIndex(mesh.cloud, "normal_y");
- int normal_z_index = getFieldIndex(mesh.cloud, "normal_z");
- if (normal_x_index != -1 && normal_y_index != -1 && normal_z_index != -1)
- {
- fs << "\nproperty float nx"
- "\nproperty float ny"
- "\nproperty float nz";
- }
- // Check if we have curvature on vertices
- int curvature_index = getFieldIndex(mesh.cloud, "curvature");
- if ( curvature_index != -1)
- {
- fs << "\nproperty float curvature";
- }
- // Faces
- fs << "\nelement face "<< nr_faces;
- fs << "\nproperty list uchar int vertex_indices";
- fs << "\nend_header\n";
+ pcl::io::writePLYHeader(fs, mesh, (mesh.cloud.is_bigendian ? "binary_big_endian 1.0" : "binary_little_endian 1.0"));
// Close the file
fs.close ();
int xyz = 0;
for (std::size_t d = 0; d < mesh.cloud.fields.size (); ++d)
{
- int c = 0;
-
// adding vertex
if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) && (
mesh.cloud.fields[d].name == "x" ||
mesh.cloud.fields[d].name == "y" ||
mesh.cloud.fields[d].name == "z"))
{
- float value;
- memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (float));
+ fpout.write (reinterpret_cast<const char*> (&mesh.cloud.at<float>(i, mesh.cloud.fields[d].offset)), sizeof (float));
// if (++xyz == 3)
// break;
++xyz;
(mesh.cloud.fields[d].name == "rgb"))
{
- pcl::RGB color;
- memcpy (&color, &mesh.cloud.data[i * point_size + mesh.cloud.fields[rgb_index].offset + c * sizeof (float)], sizeof (RGB));
+ const auto& color = mesh.cloud.at<RGB>(i, mesh.cloud.fields[d].offset);
fpout.write (reinterpret_cast<const char*> (&color.r), sizeof (unsigned char));
fpout.write (reinterpret_cast<const char*> (&color.g), sizeof (unsigned char));
fpout.write (reinterpret_cast<const char*> (&color.b), sizeof (unsigned char));
else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::UINT32) &&
(mesh.cloud.fields[d].name == "rgba"))
{
- pcl::RGB color;
- memcpy (&color, &mesh.cloud.data[i * point_size + mesh.cloud.fields[rgba_index].offset + c * sizeof (std::uint32_t)], sizeof (RGB));
+ const auto& color = mesh.cloud.at<RGB>(i, mesh.cloud.fields[d].offset);
fpout.write (reinterpret_cast<const char*> (&color.r), sizeof (unsigned char));
fpout.write (reinterpret_cast<const char*> (&color.g), sizeof (unsigned char));
fpout.write (reinterpret_cast<const char*> (&color.b), sizeof (unsigned char));
mesh.cloud.fields[d].name == "normal_y" ||
mesh.cloud.fields[d].name == "normal_z"))
{
- float value;
- memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (float));
+ fpout.write (reinterpret_cast<const char*> (&mesh.cloud.at<float>(i, mesh.cloud.fields[d].offset)), sizeof (float));
}
else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) &&
(mesh.cloud.fields[d].name == "curvature"))
{
- float value;
- memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
- fpout.write (reinterpret_cast<const char*> (&value), sizeof (float));
+ fpout.write (reinterpret_cast<const char*> (&mesh.cloud.at<float>(i, mesh.cloud.fields[d].offset)), sizeof (float));
}
}
if (xyz != 3)
{
- PCL_ERROR ("[pcl::io::savePLYFile] Input point cloud has no XYZ data!\n");
+ PCL_ERROR ("[pcl::io::savePLYFileBinary] Input point cloud has no XYZ data!\n");
return (-2);
}
}
// Write down faces
- for (std::size_t i = 0; i < nr_faces; i++)
+ for (const pcl::Vertices& polygon : mesh.polygons)
{
- unsigned char value = static_cast<unsigned char> (mesh.polygons[i].vertices.size ());
+ auto value = static_cast<unsigned char> (polygon.vertices.size ());
fpout.write (reinterpret_cast<const char*> (&value), sizeof (unsigned char));
- for (const int value : mesh.polygons[i].vertices)
+ for (const int value : polygon.vertices)
{
//fs << mesh.polygons[i].vertices[j] << " ";
fpout.write (reinterpret_cast<const char*> (&value), sizeof (int));
populateDeviceList ();
}
-pcl::io::real_sense::RealSenseDeviceManager::~RealSenseDeviceManager ()
-{
-}
-
pcl::io::real_sense::RealSenseDevice::Ptr
pcl::io::real_sense::RealSenseDeviceManager::captureDevice ()
{
if (need_xyz_ || need_xyzrgba_)
{
selectMode ();
- PXCCapture::Device::StreamProfileSet profile;
- memset (&profile, 0, sizeof (profile));
+ PXCCapture::Device::StreamProfileSet profile{};
profile.depth.frameRate.max = mode_selected_.fps;
profile.depth.frameRate.min = mode_selected_.fps;
profile.depth.imageInfo.width = mode_selected_.depth_width;
#include <pcl/common/point_tests.h> // for pcl::isFinite
#include <pcl/console/print.h>
+#include <string>
+
/////////////////////////////////////////////////////////////////////////////
pcl::RobotEyeGrabber::RobotEyeGrabber ()
: terminate_thread_ (false)
//The new packet data format contains this as a header
//char[6] "EBRBEP"
//std::uint32_t Timestamp // counts of a 66 MHz clock since power-on of eye.
- std::size_t response_size = 6; //"EBRBEP"
- if( !strncmp((char*)(data_packet), "EBRBEP", response_size) )
+ const std::string PACKET_HEADER("EBRBEP");
+ constexpr std::size_t RESPONSE_SIZE = 6; //"EBRBEP"
+ std::string packet(reinterpret_cast<const char*>(data_packet), RESPONSE_SIZE);
+ if(packet == PACKET_HEADER)
{
std::uint32_t timestamp; // counts of a 66 MHz clock since power-on of eye.
- computeTimestamp(timestamp, data_packet + response_size);
+ computeTimestamp(timestamp, data_packet + RESPONSE_SIZE);
//std::cout << "Timestamp: " << timestamp << std::endl;
- offset = (response_size + sizeof(timestamp));
+ offset = (RESPONSE_SIZE + sizeof(timestamp));
}
else
{
|| sensor_address_ == sender_endpoint_.address ())
{
data_size_ = number_of_bytes;
- unsigned char *dup = new unsigned char[number_of_bytes];
+ auto *dup = new unsigned char[number_of_bytes];
memcpy (dup, receive_buffer_, number_of_bytes);
packet_queue_.enqueue (boost::shared_array<unsigned char>(dup));
}
float
pcl::TimGrabber::getFramesPerSecond () const
{
- boost::mutex::scoped_lock lock (frequency_mutex_);
+ std::lock_guard<std::mutex> lock (frequency_mutex_);
return (frequency_.getFrequency ());
}
}
/////////////////////////////////////////////////////////////////////////////
-pcl::VLPGrabber::~VLPGrabber () noexcept
-{
-}
+pcl::VLPGrabber::~VLPGrabber () noexcept = default;
/////////////////////////////////////////////////////////////////////////////
void
fs.open (file_name.c_str ());
unsigned int nr_points = triangles.cloud.width * triangles.cloud.height;
- unsigned int point_size = static_cast<unsigned int> (triangles.cloud.data.size () / nr_points);
+ auto point_size = static_cast<unsigned int> (triangles.cloud.data.size () / nr_points);
// Write the header information
fs << "# vtk DataFile Version 3.0\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS " << nr_points << " float" << '\n';
fs.open (file_name.c_str ());
unsigned int nr_points = cloud.width * cloud.height;
- unsigned int point_size = static_cast<unsigned int> (cloud.data.size () / nr_points);
+ auto point_size = static_cast<unsigned int> (cloud.data.size () / nr_points);
// Write the header information
fs << "# vtk DataFile Version 3.0\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS " << nr_points << " float" << '\n';
#include <pcl/PCLPointCloud2.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
-#include <vtkDoubleArray.h>
+#include <vtkFloatArray.h> // for vtkFloatArray
#include <vtkImageData.h>
#include <vtkImageShiftScale.h>
-#include <vtkPNGWriter.h>
+#include <vtkOBJReader.h> // for vtkOBJReader
+#include <vtkPoints.h> // for vtkPoints
+#include <vtkPolyDataReader.h> // for vtkPolyDataReader
+#include <vtkPolyDataWriter.h> // for vtkPolyDataWriter
+#include <vtkPLYReader.h> // for vtkPLYReader
+#include <vtkPLYWriter.h> // for vtkPLYWriter
+#include <vtkPNGWriter.h> // for vtkPNGWriter
+#include <vtkSTLReader.h> // for vtkSTLReader
+#include <vtkSTLWriter.h> // for vtkSTLWriter
+#include <vtkUnsignedCharArray.h> // for vtkUnsignedCharArray
// Support for VTK 7.1 upwards
#ifdef vtkGenericDataArray_h
mesh.header = polygon_mesh.header;
/// TODO check for sub-meshes
mesh.tex_polygons.push_back (polygon_mesh.polygons);
+ mesh.tex_coord_indices.push_back (polygon_mesh.polygons);
// Add dummy material
mesh.tex_materials.emplace_back();
pcl::io::mesh2vtk (const pcl::PolygonMesh& mesh, vtkSmartPointer<vtkPolyData>& poly_data)
{
auto nr_points = mesh.cloud.width * mesh.cloud.height;
- unsigned int nr_polygons = static_cast<unsigned int> (mesh.polygons.size ());
+ auto nr_polygons = static_cast<unsigned int> (mesh.polygons.size ());
// reset vtkPolyData object
poly_data = vtkSmartPointer<vtkPolyData>::New (); // OR poly_data->Reset();
{
for (unsigned int i = 0; i < nr_polygons; i++)
{
- unsigned int nr_points_in_polygon = static_cast<unsigned int> (mesh.polygons[i].vertices.size ());
+ auto nr_points_in_polygon = static_cast<unsigned int> (mesh.polygons[i].vertices.size ());
vtk_mesh_polygons->InsertNextCell (nr_points_in_polygon);
for (unsigned int j = 0; j < nr_points_in_polygon; j++)
vtk_mesh_polygons->InsertCellPoint (mesh.polygons[i].vertices[j]);
std::uint64_t stamp;
stamp = sweep->header.stamp;
time_t systemTime = static_cast<time_t>(((stamp & 0xffffffff00000000l) >> 32) & 0x00000000ffffffff);
- std::uint32_t usec = static_cast<std::uint32_t>(stamp & 0x00000000ffffffff);
+ auto usec = static_cast<std::uint32_t>(stamp & 0x00000000ffffffff);
std::cout << std::hex << stamp << " " << ctime(&systemTime) << " usec: " << usec << std::endl;
}
*
*/
-#include <pcl/point_cloud.h>
-#include <pcl/point_types.h>
-#include <pcl/io/pcd_io.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/common/time.h>
#include <pcl/console/parse.h>
class PCDBuffer
{
public:
- PCDBuffer () {}
+ PCDBuffer () = default;
+ PCDBuffer (const PCDBuffer&) = delete; // Disabled copy constructor
+ PCDBuffer& operator = (const PCDBuffer&) = delete; // Disabled assignment operator
bool
pushBack (typename PointCloud<PointT>::ConstPtr); // thread-save wrapper for push_back() method of ciruclar_buffer
}
private:
- PCDBuffer (const PCDBuffer&) = delete; // Disabled copy constructor
- PCDBuffer& operator = (const PCDBuffer&) = delete; // Disabled assignment operator
-
std::mutex bmutex_;
std::condition_variable buff_empty_;
boost::circular_buffer<typename PointCloud<PointT>::ConstPtr> buffer_;
void
grabAndSend ()
{
- OpenNIGrabber* grabber = new OpenNIGrabber ();
+ auto* grabber = new OpenNIGrabber ();
grabber->getDevice ()->setDepthOutputFormat (depth_mode_);
Grabber* interface = grabber;
openni_wrapper::OpenNIDevice::Ptr device = grabber.getDevice ();
std::cout << "Supported depth modes for device: " << device->getVendorName () << " , " << device->getProductName () << std::endl;
std::vector<std::pair<int, XnMapOutputMode > > modes = grabber.getAvailableDepthModes ();
- for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin (); it != modes.end (); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
if (device->hasImageStream ())
{
std::cout << std::endl << "Supported image modes for device: " << device->getVendorName () << " , " << device->getProductName () << std::endl;
modes = grabber.getAvailableImageModes ();
- for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin (); it != modes.end (); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
}
}
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS flann)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS flann)
PCL_ADD_DOC("${SUBSYS_NAME}")
// Wrap indices vector (no data allocation)
::flann::Matrix<std::size_t> indices_mat(&indices[0], 1, k);
auto ret = index.knnSearch(query, indices_mat, dists, k, params);
- std::copy(indices.cbegin(), indices.cend(), k_indices.begin());
+ // cast appropriately
+ std::transform(indices.cbegin(),
+ indices.cend(),
+ k_indices.begin(),
+ [](const auto& x) { return static_cast<pcl::index_t>(x); });
return ret;
}
std::vector<std::vector<std::size_t>> indices(1);
int neighbors_in_radius = index.radiusSearch(query, indices, dists, radius, params);
k_indices.resize(indices[0].size());
- std::copy(indices[0].cbegin(), indices[0].cend(), k_indices.begin());
+ // cast appropriately
+ std::transform(indices[0].cbegin(),
+ indices[0].cend(),
+ k_indices.begin(),
+ [](const auto& x) { return static_cast<pcl::index_t>(x); });
return neighbors_in_radius;
}
}
/** \brief Destructor for KdTree. Deletes all allocated data arrays and destroys the kd-tree structures. */
- virtual ~KdTree () {};
+ virtual ~KdTree () = default;
/** \brief Search for k-nearest neighbors for the given query point.
* \param[in] p_q the given query point
/** \brief Destructor for KdTreeFLANN.
* Deletes all allocated data arrays and destroys the kd-tree structures.
*/
- ~KdTreeFLANN() { cleanup(); }
+ ~KdTreeFLANN() override
+ {
+ cleanup();
+ }
/** \brief Provide a pointer to the input dataset.
* \param[in] cloud the const boost shared pointer to a PointCloud message
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
{}
/** \brief Destructor. */
- virtual ~AbstractAgastDetector () {}
+ virtual ~AbstractAgastDetector () = default;
/** \brief Detects corner points.
* \param intensity_data
}
/** \brief Destructor. */
- ~AgastDetector7_12s () {}
+ ~AgastDetector7_12s () override = default;
/** \brief Computes corner score.
* \param im
}
/** \brief Destructor. */
- ~AgastDetector5_8 () {}
+ ~AgastDetector5_8 () override = default;
/** \brief Computes corner score.
* \param im
}
/** \brief Destructor. */
- ~OastDetector9_16 () {}
+ ~OastDetector9_16 () override = default;
/** \brief Computes corner score.
* \param im
}
/** \brief Destructor. */
- ~AgastKeypoint2DBase ()
- {
- }
+ ~AgastKeypoint2DBase () override = default;
/** \brief Sets the threshold for corner detection.
* \param[in] threshold the threshold used for corner detection.
}
/** \brief Destructor. */
- ~AgastKeypoint2D ()
- {
- }
+ ~AgastKeypoint2D () override = default;
protected:
/** \brief Detects the keypoints.
}
/** \brief Destructor. */
- ~AgastKeypoint2D ()
- {
- }
+ ~AgastKeypoint2D () override = default;
protected:
/** \brief Detects the keypoints.
}
/** \brief Destructor. */
- ~BriskKeypoint2D ()
- {
- }
+ ~BriskKeypoint2D () override = default;
/** \brief Sets the threshold for corner detection.
* \param[in] threshold the threshold used for corner detection.
}
/** \brief Empty destructor */
- ~HarrisKeypoint3D () {}
+ ~HarrisKeypoint3D () override = default;
/** \brief Provide a pointer to the input dataset
* \param[in] cloud the const boost shared pointer to a PointCloud message
}
/** \brief Empty destructor */
- virtual ~HarrisKeypoint6D () {}
+ virtual ~HarrisKeypoint6D () = default;
/**
* @brief set the radius for normal estimation and non maxima supression.
int y = static_cast<int> (index / input_->width);
// indices 0 1 2
// coefficients: ixix ixiy iyiy
- memset (coefficients, 0, sizeof (float) * 3);
+ std::fill_n(coefficients, 3, 0);
int endx = std::min (width, x + half_window_width_);
int endy = std::min (height, y + half_window_height_);
coefficients [7] = zz / float(count);
}
else
- memset (coefficients, 0, sizeof (float) * 8);
+ std::fill_n(coefficients, 8, 0);
#else
- memset (coefficients, 0, sizeof (float) * 8);
+ std::fill_n(coefficients, 8, 0);
for (const auto& index : neighbors)
{
if (std::isfinite ((*normals_)[index].normal_x))
{
Eigen::Matrix3f nnT;
Eigen::Matrix3f NNT;
- Eigen::Matrix3f NNTInv;
Eigen::Vector3f NNTp;
const unsigned max_iterations = 10;
#pragma omp parallel for \
default(none) \
shared(corners) \
- firstprivate(nnT, NNT, NNTInv, NNTp) \
+ firstprivate(nnT, NNT, NNTp) \
num_threads(threads_)
for (int cIdx = 0; cIdx < static_cast<int> (corners.size ()); ++cIdx)
{
NNT += nnT;
NNTp += nnT * (*surface_)[index].getVector3fMap ();
}
- if (invert3x3SymMatrix (NNT, NNTInv) != 0)
- corners[cIdx].getVector3fMap () = NNTInv * NNTp;
+ const Eigen::LDLT<Eigen::Matrix3f> ldlt(NNT);
+ if (ldlt.rcond() > 1e-4)
+ corners[cIdx].getVector3fMap () = ldlt.solve(NNTp);
const auto diff = (corners[cIdx].getVector3fMap () - corner.getVector3fMap()).squaredNorm ();
if (diff <= 1e-6) {
template <typename PointInT, typename PointOutT, typename NormalT> void
pcl::HarrisKeypoint6D<PointInT, PointOutT, NormalT>::calculateCombinedCovar (const pcl::Indices& neighbors, float* coefficients) const
{
- memset (coefficients, 0, sizeof (float) * 21);
+ std::fill_n(coefficients, 21, 0);
unsigned count = 0;
for (const auto &neighbor : neighbors)
{
// Suat: ToDo: remove this magic number or expose using set/get
if (len > 200.0)
{
- len = 1.0 / sqrt (len);
+ len = 1.0 / std::sqrt (len);
intensity_gradients_->points [idx].gradient_x *= len;
intensity_gradients_->points [idx].gradient_y *= len;
intensity_gradients_->points [idx].gradient_z *= len;
{
const PointInT& current_point = (*input_)[current_index];
- double central_point[3];
- memset(central_point, 0, sizeof(double) * 3);
+ double central_point[3]{};
central_point[0] = current_point.x;
central_point[1] = current_point.y;
if (n_neighbors < min_neighbors_)
return;
- double cov[9];
- memset(cov, 0, sizeof(double) * 9);
+ double cov[9]{};
for (const auto& n_idx : nn_indices)
{
const PointInT& n_point = (*input_)[n_idx];
- double neigh_point[3];
- memset(neigh_point, 0, sizeof(double) * 3);
+ double neigh_point[3]{};
neigh_point[0] = n_point.x;
neigh_point[1] = n_point.y;
delete[] third_eigen_value_;
- third_eigen_value_ = new double[input_->size ()];
- memset(third_eigen_value_, 0, sizeof(double) * input_->size ());
+ third_eigen_value_ = new double[input_->size ()]{};
delete[] edge_points_;
for (std::size_t i = 0; i < threads_; i++)
omp_mem[i].setZero (3);
#else
- Eigen::Vector3d *omp_mem = new Eigen::Vector3d[1];
+ auto *omp_mem = new Eigen::Vector3d[1];
omp_mem[0].setZero (3);
#endif
}
omp_mem[tid][0] = e2c / e1c;
- omp_mem[tid][1] = e3c / e2c;;
+ omp_mem[tid][1] = e3c / e2c;
omp_mem[tid][2] = e3c;
}
if (label_idx_ != -1)
{
// save the index in the cloud
- std::uint32_t label = static_cast<std::uint32_t> (point_index);
+ auto label = static_cast<std::uint32_t> (point_index);
memcpy (reinterpret_cast<char*> (&point_out) + out_fields_[label_idx_].offset,
&label, sizeof (std::uint32_t));
}
if (label_idx_ != -1)
{
// save the index in the cloud
- std::uint32_t label = static_cast<std::uint32_t> (point_index);
+ auto label = static_cast<std::uint32_t> (point_index);
memcpy (reinterpret_cast<char*> (&point_out) + out_fields_[label_idx_].offset,
&label, sizeof (std::uint32_t));
}
shared(height, indices, occupency_map, output, width) \
num_threads(threads_)
#endif
- for (std::size_t i = 0; i < indices.size (); ++i)
+ for (std::ptrdiff_t i = 0; i < static_cast<std::ptrdiff_t> (indices.size ()); ++i)
{
int idx = indices[i];
if (((*response_)[idx] < second_threshold_) || occupency_map[idx])
* Code example:
*
* \code
- * pcl::PointCloud<pcl::PointXYZRGBA>::Ptr model (new pcl::PointCloud<pcl::PointXYZRGBA> ());;
+ * pcl::PointCloud<pcl::PointXYZRGBA>::Ptr model (new pcl::PointCloud<pcl::PointXYZRGBA> ());
* pcl::PointCloud<pcl::PointXYZRGBA>::Ptr model_keypoints (new pcl::PointCloud<pcl::PointXYZRGBA> ());
* pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBA> ());
*
}
/** \brief Destructor. */
- ~ISSKeypoint3D ()
+ ~ISSKeypoint3D () override
{
delete[] third_eigen_value_;
delete[] edge_points_;
{};
/** \brief Empty destructor */
- ~Keypoint () {}
+ ~Keypoint () override = default;
/** \brief Provide a pointer to the input dataset that we need to estimate features at every point for.
* \param cloud the const boost shared pointer to a PointCloud message
// =====CONSTRUCTOR & DESTRUCTOR=====
NarfKeypoint (RangeImageBorderExtractor* range_image_border_extractor=nullptr, float support_size=-1.0f);
- ~NarfKeypoint ();
+ ~NarfKeypoint () override;
// =====PUBLIC METHODS=====
//! Erase all data calculated for the current range image
}
/** \brief Empty destructor */
- ~SUSANKeypoint () {}
+ ~SUSANKeypoint () override = default;
/** \brief set the radius for normal estimation and non maxima supression.
* \param[in] radius
const std::vector<pcl::PointUV, Eigen::aligned_allocator<pcl::PointUV> > &corners_all,
std::vector<ScoreIndex> &scores) const
{
- unsigned int num_corners = static_cast<unsigned int> (corners_all.size ());
+ auto num_corners = static_cast<unsigned int> (corners_all.size ());
if (num_corners > scores.capacity ())
{
const std::vector<pcl::PointUV, Eigen::aligned_allocator<pcl::PointUV> > &corners_all,
std::vector<ScoreIndex> &scores) const
{
- unsigned int num_corners = static_cast<unsigned int> (corners_all.size ());
+ auto num_corners = static_cast<unsigned int> (corners_all.size ());
if (num_corners > scores.capacity ())
{
}
/////////////////////////////////////////////////////////////////////////////////////////
-pcl::keypoints::brisk::ScaleSpace::~ScaleSpace ()
-{
-}
+pcl::keypoints::brisk::ScaleSpace::~ScaleSpace () = default;
/////////////////////////////////////////////////////////////////////////////////////////
// construct the image pyramids
const int r_x_1 =6 - r_x;
const int r_y = (sixths_y % 6);
const int r_y_1 = 6 - r_y;
- std::uint8_t score = static_cast<std::uint8_t> (
+ auto score = static_cast<std::uint8_t> (
0xFF & ((r_x_1 * r_y_1 * l.getAgastScore (x_above, y_above, 1) +
r_x * r_y_1 * l.getAgastScore (x_above + 1, y_above, 1) +
r_x_1 * r_y * l.getAgastScore (x_above, y_above + 1, 1) +
const int r_x_1 = 8 - r_x;
const int r_y = (eighths_y % 8);
const int r_y_1 = 8 - r_y;
- std::uint8_t score = static_cast<std::uint8_t> (
+ auto score = static_cast<std::uint8_t> (
0xFF & ((r_x_1 * r_y_1 * l.getAgastScore (x_above, y_above, 1) +
r_x * r_y_1 * l.getAgastScore (x_above + 1, y_above, 1) +
r_x_1 * r_y * l.getAgastScore (x_above , y_above + 1, 1) +
delta.push_back (1);
}
- unsigned int deltasize = static_cast<unsigned int> (delta.size ());
+ auto deltasize = static_cast<unsigned int> (delta.size ());
if (deltasize != 0)
{
// in this case, we have to analyze the situation more carefully:
// guess the lower intra octave...
pcl::keypoints::brisk::Layer& l = pyramid_[0];
int s_0_0 = l.getAgastScore_5_8 (x_layer - 1, y_layer - 1, 1);
- unsigned char max_below_uchar = static_cast<unsigned char> (s_0_0);
+ auto max_below_uchar = static_cast<unsigned char> (s_0_0);
int s_1_0 = l.getAgastScore_5_8 (x_layer, y_layer - 1, 1);
if (s_1_0 > max_below_uchar) max_below_uchar = static_cast<unsigned char> (s_1_0);
}
agast_detector_5_8_->setThreshold (threshold - 1);
- std::uint8_t score = std::uint8_t (agast_detector_5_8_->computeCornerScore (&img_[0] + x + y * img_width_));
+ auto score = std::uint8_t (agast_detector_5_8_->computeCornerScore (&img_[0] + x + y * img_width_));
if (score < threshold) score = 0;
return (score);
}
{
pcl::utils::ignore(dstheight);
#if defined(__SSSE3__) && !defined(__i386__)
- const unsigned short leftoverCols = static_cast<unsigned short> ((srcwidth % 16) / 2); // take care with border...
+ const auto leftoverCols = static_cast<unsigned short> ((srcwidth % 16) / 2); // take care with border...
const bool noleftover = (srcwidth % 16) == 0; // note: leftoverCols can be zero but this still false...
// make sure the destination image is of the right size:
__m128i mask = _mm_set_epi32 (0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF);
// data pointers:
- const __m128i* p1 = reinterpret_cast<const __m128i*> (&srcimg[0]);
- const __m128i* p2 = reinterpret_cast<const __m128i*> (&srcimg[0] + srcwidth);
- __m128i* p_dest = reinterpret_cast<__m128i*> (&dstimg[0]);
+ const auto* p1 = reinterpret_cast<const __m128i*> (&srcimg[0]);
+ const auto* p2 = reinterpret_cast<const __m128i*> (&srcimg[0] + srcwidth);
+ auto* p_dest = reinterpret_cast<__m128i*> (&dstimg[0]);
unsigned char* p_dest_char;//=(unsigned char*)p_dest;
// size:
// Todo: find the equivalent to may_alias
#define UCHAR_ALIAS unsigned char //__declspec(noalias)
#endif
- const UCHAR_ALIAS* result = reinterpret_cast<const UCHAR_ALIAS*> (&result1);
+ const auto* result = reinterpret_cast<const UCHAR_ALIAS*> (&result1);
for (unsigned int j = 0; j < 8; j++)
{
*(p_dest_char++) = static_cast<unsigned char> ((*(result + 2 * j) + *(result + 2 * j + 1)) / 2);
}
else
{
- const unsigned char* p1_src_char = reinterpret_cast<const unsigned char*> (p1);
- const unsigned char* p2_src_char = reinterpret_cast<const unsigned char*> (p2);
+ const auto* p1_src_char = reinterpret_cast<const unsigned char*> (p1);
+ const auto* p2_src_char = reinterpret_cast<const unsigned char*> (p2);
for (unsigned int k = 0; k < leftoverCols; k++)
{
- unsigned short tmp = static_cast<unsigned short> (p1_src_char[k] + p1_src_char[k+1]+ p2_src_char[k] + p2_src_char[k+1]);
+ auto tmp = static_cast<unsigned short> (p1_src_char[k] + p1_src_char[k+1]+ p2_src_char[k] + p2_src_char[k+1]);
*(p_dest_char++) = static_cast<unsigned char>(tmp / 4);
}
// done with the two rows:
{
pcl::utils::ignore(dstheight);
#if defined(__SSSE3__) && !defined(__i386__)
- const unsigned short leftoverCols = static_cast<unsigned short> (((srcwidth / 3) * 3) % 15);// take care with border...
+ const auto leftoverCols = static_cast<unsigned short> (((srcwidth / 3) * 3) % 15);// take care with border...
// make sure the destination image is of the right size:
assert (std::floor (double (srcwidth) / 3.0 * 2.0) == dstwidth);
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
#include <pcl/common/utils.h> // pcl::utils::ignore
#include <pcl/ml/stats_estimator.h>
-#include <istream>
-#include <ostream>
-
namespace pcl {
/** Interface for branch estimators. */
class PCL_EXPORTS BranchEstimator {
public:
/** Destructor. */
- virtual ~BranchEstimator() {}
+ virtual ~BranchEstimator() = default;
/** Returns the number of branches the corresponding tree has. */
virtual std::size_t
class PCL_EXPORTS BinaryTreeThresholdBasedBranchEstimator : public BranchEstimator {
public:
/** Constructor. */
- inline BinaryTreeThresholdBasedBranchEstimator() {}
+ inline BinaryTreeThresholdBasedBranchEstimator() = default;
/** Destructor. */
- inline ~BinaryTreeThresholdBasedBranchEstimator() {}
+ inline ~BinaryTreeThresholdBasedBranchEstimator() override = default;
/** Returns the number of branches the corresponding tree has. */
inline std::size_t
class PCL_EXPORTS TernaryTreeMissingDataBranchEstimator : public BranchEstimator {
public:
/** Constructor. */
- inline TernaryTreeMissingDataBranchEstimator() {}
+ inline TernaryTreeMissingDataBranchEstimator() = default;
/** Destructor. */
- inline ~TernaryTreeMissingDataBranchEstimator() {}
+ inline ~TernaryTreeMissingDataBranchEstimator() override = default;
/** \brief Returns the number of branches the corresponding tree has. */
inline std::size_t
public:
/** Constructor. */
- DecisionForest() {}
+ DecisionForest() = default;
/** Destructor. */
- virtual ~DecisionForest() {}
+ virtual ~DecisionForest() = default;
/** Serializes the decision tree.
*
DecisionTree() : root_() {}
/** Destructor. */
- virtual ~DecisionTree() {}
+ virtual ~DecisionTree() = default;
/** Sets the root node of the tree.
*
NodeType>>;
/** Constructor. */
- DecisionTreeTrainerDataProvider() {}
+ DecisionTreeTrainerDataProvider() = default;
/** Destructor. */
- ~DecisionTreeTrainerDataProvider() {}
+ virtual ~DecisionTreeTrainerDataProvider() = default;
/** Virtual function called to obtain training examples and labels before
* training a specific tree */
class PCL_EXPORTS FeatureHandler {
public:
/** Destructor. */
- virtual ~FeatureHandler(){};
+ virtual ~FeatureHandler() = default;
/** Creates random features.
*
/** Constructor. */
Fern() : num_of_decisions_(0), features_(0), thresholds_(0), nodes_(1) {}
- /** Destructor. */
- virtual ~Fern() {}
-
/** Initializes the fern.
*
* \param num_of_decisions the number of decisions taken to access the nodes
stream.write(reinterpret_cast<const char*>(&num_of_decisions_),
sizeof(num_of_decisions_));
- for (std::size_t feature_index = 0; feature_index < features_.size();
- ++feature_index) {
- features_[feature_index].serialize(stream);
+ for (auto& feature : features_) {
+ feature.serialize(stream);
}
- for (std::size_t threshold_index = 0; threshold_index < thresholds_.size();
- ++threshold_index) {
- stream.write(reinterpret_cast<const char*>(&(thresholds_[threshold_index])),
- sizeof(thresholds_[threshold_index]));
+ for (const auto& threshold : thresholds_) {
+ stream.write(reinterpret_cast<const char*>(&threshold), sizeof(threshold));
}
- for (std::size_t node_index = 0; node_index < nodes_.size(); ++node_index) {
- nodes_[node_index].serialize(stream);
+ for (auto& node : nodes_) {
+ node.serialize(stream);
}
}
thresholds_.resize(num_of_decisions_);
nodes_.resize(0x1 << num_of_decisions_);
- for (std::size_t feature_index = 0; feature_index < features_.size();
- ++feature_index) {
- features_[feature_index].deserialize(stream);
+ for (auto& feature : features_) {
+ feature.deserialize(stream);
}
- for (std::size_t threshold_index = 0; threshold_index < thresholds_.size();
- ++threshold_index) {
- stream.read(reinterpret_cast<char*>(&(thresholds_[threshold_index])),
- sizeof(thresholds_[threshold_index]));
+ for (const auto& threshold : thresholds_) {
+ stream.read(reinterpret_cast<char*>(&(threshold)), sizeof(threshold));
}
- for (std::size_t node_index = 0; node_index < nodes_.size(); ++node_index) {
- nodes_[node_index].deserialize(stream);
+ for (auto& node : nodes_) {
+ node.deserialize(stream);
}
}
/** Constructor. */
FernEvaluator();
- /** Destructor. */
- virtual ~FernEvaluator();
-
/** Evaluates the specified examples using the supplied tree.
*
* \param[in] fern the decision tree
/** Constructor. */
FernTrainer();
- /** Destructor. */
- virtual ~FernTrainer();
-
/** Sets the feature handler used to create and evaluate features.
*
* \param[in] feature_handler the feature handler
class ExampleIndex,
class NodeType>
pcl::DecisionForestEvaluator<FeatureType, DataSet, LabelType, ExampleIndex, NodeType>::
- ~DecisionForestEvaluator()
-{}
+ ~DecisionForestEvaluator() = default;
template <class FeatureType,
class DataSet,
class ExampleIndex,
class NodeType>
DecisionForestTrainer<FeatureType, DataSet, LabelType, ExampleIndex, NodeType>::
- ~DecisionForestTrainer()
-{}
+ ~DecisionForestTrainer() = default;
template <class FeatureType,
class DataSet,
class ExampleIndex,
class NodeType>
DecisionTreeEvaluator<FeatureType, DataSet, LabelType, ExampleIndex, NodeType>::
- DecisionTreeEvaluator()
-{}
+ DecisionTreeEvaluator() = default;
template <class FeatureType,
class DataSet,
class ExampleIndex,
class NodeType>
DecisionTreeEvaluator<FeatureType, DataSet, LabelType, ExampleIndex, NodeType>::
- ~DecisionTreeEvaluator()
-{}
+ ~DecisionTreeEvaluator() = default;
template <class FeatureType,
class DataSet,
class ExampleIndex,
class NodeType>
DecisionTreeTrainer<FeatureType, DataSet, LabelType, ExampleIndex, NodeType>::
- ~DecisionTreeTrainer()
-{}
+ ~DecisionTreeTrainer() = default;
template <class FeatureType,
class DataSet,
FernEvaluator<FeatureType, DataSet, LabelType, ExampleIndex, NodeType>::FernEvaluator()
{}
-template <class FeatureType,
- class DataSet,
- class LabelType,
- class ExampleIndex,
- class NodeType>
-FernEvaluator<FeatureType, DataSet, LabelType, ExampleIndex, NodeType>::~FernEvaluator()
-{}
-
template <class FeatureType,
class DataSet,
class LabelType,
, examples_()
{}
-template <class FeatureType,
- class DataSet,
- class LabelType,
- class ExampleIndex,
- class NodeType>
-FernTrainer<FeatureType, DataSet, LabelType, ExampleIndex, NodeType>::~FernTrainer()
-{}
-
template <class FeatureType,
class DataSet,
class LabelType,
Kmeans<PointT>::Kmeans() : cluster_field_name_("")
{}
-template <typename PointT>
-Kmeans<PointT>::~Kmeans()
-{}
-
template <typename PointT>
void
Kmeans<PointT>::cluster(std::vector<PointIndices>& clusters)
/** Empty constructor. */
Kmeans(unsigned int num_points, unsigned int num_dimensions);
- /** This destructor destroys. */
- ~Kmeans();
-
/** This method sets the k-means cluster size.
*
* \param[in] k number of clusters
MultiChannel2DComparisonFeature() : p1(), p2(), channel(0) {}
/** Destructor. */
- virtual ~MultiChannel2DComparisonFeature() {}
+ virtual ~MultiChannel2DComparisonFeature() = default;
/** Serializes the feature to a stream.
*
, feature_window_height_(feature_window_height)
{}
- /** Destructor. */
- virtual ~MultiChannel2DComparisonFeatureHandler() {}
-
/** Sets the feature window size.
*
* \param[in] width the width of the feature window
, feature_window_height_(feature_window_height)
{}
- /** Destructor. */
- virtual ~ScaledMultiChannel2DComparisonFeatureHandler() {}
-
/** Sets the feature window size.
*
* \param[in] width the width of the feature window
pcl::MultipleData2DExampleIndex> {
public:
ScaledMultiChannel2DComparisonFeatureHandlerCCodeGenerator() {}
- virtual ~ScaledMultiChannel2DComparisonFeatureHandlerCCodeGenerator() {}
void
generateEvalFunctionCode(std::ostream& stream) const;
/** Constructor. */
inline MultiChannel2DData() : data_(NULL), width_(0), height_(0) {}
- /** Destructor. */
- virtual ~MultiChannel2DData() {}
-
/** Resizes the internal data storage.
*
* \param[in] width the width of the resized 2D data array
/** Constructor. */
inline MultiChannel2DDataSet() : data_set_() {}
- /** Destructor. */
- virtual ~MultiChannel2DDataSet() {}
-
/** Adds a new two-dimensional data block to the data set.
*
* \param[in] width the width of the new data block
const float w);
/** Deconstructor for PairwisePotential class. */
- ~PairwisePotential(){};
+ ~PairwisePotential() = default;
void
compute(std::vector<float>& out,
/** Constructor for Permutohedral class. */
Permutohedral();
- /** Deconstructor for Permutohedral class. */
- ~Permutohedral(){};
-
/** Initialization. */
void
init(const std::vector<float>& feature, const int feature_dimension, const int N);
HashTableOLD(const HashTableOLD& o)
: key_size_(o.key_size_), filled_(0), capacity_(o.capacity_)
{
- table_ = new int[capacity_];
- keys_ = new short[(capacity_ / 2 + 10) * key_size_];
- memset(table_, -1, capacity_ * sizeof(int));
+ table_ = new int[capacity_]{};
+ keys_ = new short[(capacity_ / 2 + 10) * key_size_]{};
+ std::fill(table_, table_ + capacity_, -1);
}
protected:
int old_capacity = static_cast<int>(capacity_);
capacity_ *= 2;
// Allocate the new memory
- keys_ = new short[(old_capacity + 10) * key_size_];
- table_ = new int[capacity_];
- memset(table_, -1, capacity_ * sizeof(int));
- memcpy(keys_, old_keys, filled_ * key_size_ * sizeof(short));
+ keys_ = new short[(old_capacity + 10) * key_size_]{};
+ table_ = new int[capacity_]{};
+ std::fill(table_, table_ + capacity_, -1);
+ std::copy(old_keys, old_keys + filled_ * key_size_, keys_);
// Reinsert each element
for (int i = 0; i < old_capacity; i++)
explicit HashTableOLD(int key_size, int n_elements)
: key_size_(key_size), filled_(0), capacity_(2 * n_elements)
{
- table_ = new int[capacity_];
- keys_ = new short[(capacity_ / 2 + 10) * key_size_];
- memset(table_, -1, capacity_ * sizeof(int));
+ table_ = new int[capacity_]{};
+ keys_ = new short[(capacity_ / 2 + 10) * key_size_]{};
+ std::fill(table_, table_ + capacity_, -1);
}
~HashTableOLD()
reset()
{
filled_ = 0;
- memset(table_, -1, capacity_ * sizeof(int));
+ std::fill(table_, table_ + capacity_, -1);
}
int
/** Constructor. */
inline PointXY32f() : x(0.0f), y(0.0f) {}
/** Destructor. */
- inline virtual ~PointXY32f() {}
+ inline virtual ~PointXY32f() = default;
/** Serializes the point to the specified stream.
*
inline PointXY32i() : x(0), y(0) {}
/** Destructor. */
- inline virtual ~PointXY32i() {}
+ inline virtual ~PointXY32i() = default;
/** Serializes the point to the specified stream.
*
/** Constructor. */
RegressionVarianceNode() : value(0), variance(0), threshold(0), sub_nodes() {}
- /** Destructor. */
- virtual ~RegressionVarianceNode() {}
-
/** Serializes the node to the specified stream.
*
* \param[out] stream the destination for the serialization
: branch_estimator_(branch_estimator)
{}
- /** Destructor. */
- virtual ~RegressionVarianceStatsEstimator() {}
-
/** Returns the number of branches the corresponding tree has. */
inline std::size_t
getNumOfBranches() const
public:
/** Destructor. */
- virtual ~StatsEstimator(){};
+ virtual ~StatsEstimator() = default;
/** Returns the number of brances a node can have (e.g. a binary tree has 2). */
virtual std::size_t
next_[i] = -unary_[i];
// Add up all pairwise potentials
- for (auto& p : pairwise_potential_)
+ for (auto& p : pairwise_potential_) {
p->compute(next_, current_, tmp_, M_);
+ }
// Exponentiate and normalize
expAndNormalize(current_, next_, 1.0, relax);
// data_ (num_points_, Point (num_dimensions_))
{}
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-pcl::Kmeans::~Kmeans() {}
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::Kmeans::initialClusterPoints()
#include <pcl/common/utils.h> // pcl::utils::ignore
#include <pcl/ml/svm.h>
-#include <climits>
+#include <algorithm>
#include <cmath>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <limits>
int libsvm_version = LIBSVM_VERSION;
using Qfloat = float;
using schar = signed char;
clone(T*& dst, S* src, int n)
{
dst = new T[n];
- memcpy(
- reinterpret_cast<void*>(dst), reinterpret_cast<const void*>(src), sizeof(T) * n);
+ std::copy(src, src + n, dst);
}
static inline double
get_QD() const = 0;
virtual void
swap_index(int i, int j) const = 0;
- virtual ~QMatrix() {}
+ virtual ~QMatrix() = default;
};
} // namespace pcl
public:
Kernel(int l, svm_node* const* x, const svm_parameter& param);
- ~Kernel();
+ ~Kernel() override;
static double
k_function(const svm_node* x, const svm_node* y, const svm_parameter& param);
double
kernel_precomputed(int i, int j) const
{
- return x[i][int(x[j][0].value)].value;
+ return x[i][static_cast<int>(x[j][0].value)].value;
}
};
return std::tanh(param.gamma * dot(x, y) + param.coef0);
case PRECOMPUTED: // x: test (validation), y: SV
- return x[int(y->value)].value;
+ return x[static_cast<int>(y->value)].value;
default:
return 0; // Unreachable
class Solver {
public:
- Solver(){};
+ Solver() = default;
- virtual ~Solver(){};
+ virtual ~Solver() = default;
struct SolutionInfo {
double obj;
// optimization step
int iter = 0;
- int max_iter = max(10000000, l > INT_MAX / 100 ? INT_MAX : 100 * l);
+ int max_iter =
+ max(10000000,
+ l > std::numeric_limits<int>::max() / 100 ? std::numeric_limits<int>::max()
+ : 100 * l);
int counter = min(l, 1000) + 1;
while (iter < max_iter) {
class Solver_NU : public Solver {
public:
- Solver_NU() {}
+ Solver_NU() = default;
void
Solve(int l,
if ((start = cache->get_data(i, &data, len)) < len) {
for (int j = start; j < len; j++)
- data[j] = Qfloat(y[i] * y[j] * (this->*kernel_function)(i, j));
+ data[j] = static_cast<Qfloat>(y[i] * y[j] * (this->*kernel_function)(i, j));
}
return data;
swap(QD[i], QD[j]);
}
- ~SVC_Q()
+ ~SVC_Q() override
{
delete[] y;
delete cache;
if ((start = cache->get_data(i, &data, len)) < len) {
for (int j = start; j < len; j++)
- data[j] = Qfloat((this->*kernel_function)(i, j));
+ data[j] = static_cast<Qfloat>((this->*kernel_function)(i, j));
}
return data;
swap(QD[i], QD[j]);
}
- ~ONE_CLASS_Q()
+ ~ONE_CLASS_Q() override
{
delete cache;
delete[] QD;
if (cache->get_data(real_i, &data, l) < l) {
for (j = 0; j < l; j++)
- data[j] = Qfloat((this->*kernel_function)(real_i, j));
+ data[j] = static_cast<Qfloat>((this->*kernel_function)(real_i, j));
}
// reorder and copy
schar si = sign[i];
for (j = 0; j < len; j++)
- buf[j] = Qfloat(si) * Qfloat(sign[j]) * data[index[j]];
+ buf[j] = static_cast<Qfloat>(si) * static_cast<Qfloat>(sign[j]) * data[index[j]];
return buf;
}
return QD;
}
- ~SVR_Q()
+ ~SVR_Q() override
{
delete cache;
delete[] sign;
double* zeros = new double[l];
schar* ones = new schar[l];
- int n = int(param->nu * prob->l); // # of alpha's at upper bound
+ int n = static_cast<int>(param->nu * prob->l); // # of alpha's at upper bound
for (int i = 0; i < n; i++)
alpha[i] = 1;
int* data_label = Malloc(int, l);
for (int i = 0; i < l; i++) {
- int this_label = int(prob->y[i]);
+ int this_label = static_cast<int>(prob->y[i]);
int j;
for (j = 0; j < nr_class; j++) {
svm_model*
svm_train(const svm_problem* prob, const svm_parameter* param)
{
- svm_model* model = Malloc(svm_model, 1);
+ auto* model = Malloc(svm_model, 1);
model->param = *param;
model->free_sv = 0; // XXX
model->probA = nullptr;
if (nr_class == 1)
info("WARNING: training data in only one class. See README for details.\n");
- svm_node** x = Malloc(svm_node*, l);
+ auto** x = Malloc(svm_node*, l);
for (int i = 0; i < l; i++)
x[i] = prob->x[perm[i]];
for (int i = 0; i < l; i++)
nonzero[i] = false;
- decision_function* f = Malloc(decision_function, nr_class * (nr_class - 1) / 2);
+ auto* f = Malloc(decision_function, nr_class * (nr_class - 1) / 2);
double *probA = nullptr, *probB = nullptr;
const svm_node* p = SV[i];
if (param.kernel_type == PRECOMPUTED)
- fprintf(fp, "0:%d ", int(p->value));
+ fprintf(fp, "0:%d ", static_cast<int>(p->value));
else
while (p->index != -1) {
fprintf(fp, "%d:%.8g ", p->index, p->value);
while (strrchr(line, '\n') == nullptr) {
max_line_len *= 2;
line = static_cast<char*>(realloc(line, max_line_len));
- int len = int(strlen(line));
+ int len = static_cast<int>(strlen(line));
if (fgets(line + len, max_line_len - len, input) == nullptr)
break;
// read parameters
- svm_model* model = Malloc(svm_model, 1);
+ auto* model = Malloc(svm_model, 1);
svm_parameter& param = model->param;
res = fscanf(fp, "%d", &model->nSV[i]);
}
else if (res > 0 && strcmp(cmd, "scaling") == 0) {
- char *idx, buff[10000];
+ char *idx, buff[10001]; // 1 char more than 10000 to leave room for \0 at the end
int ii = 0;
// char delims[]="\t: ";
model->scaling = Malloc(struct svm_node, 1);
if (val == nullptr)
break;
- x_space[j].index = int(strtol(idx, nullptr, 10));
+ x_space[j].index = static_cast<int>(strtol(idx, nullptr, 10));
x_space[j].value = strtod(val, nullptr);
int* count = Malloc(int, max_nr_class);
for (int i = 0; i < l; i++) {
- int this_label = int(prob->y[i]);
+ int this_label = static_cast<int>(prob->y[i]);
int j;
for (j = 0; j < nr_class; j++)
{
int total_correct = 0;
double sumv = 0, sumy = 0, sumvv = 0, sumyy = 0, sumvy = 0;
- double* target = Malloc(double, prob_.l);
+ double* target;
// number of fold for the cross validation (n of folds = number of splitting of the
// input dataset)
fprintf(stderr, "n-fold cross validation: n must >= 2\n");
return;
}
+ target = Malloc(double, prob_.l);
svm_cross_validation(&prob_, ¶m_, nr_fold_, target); // perform cross validation
int k = 0;
- for (std::size_t j = 0; j < training_set[i].SV.size(); j++)
- if (training_set[i].SV[j].idx != -1 &&
- std::isfinite(training_set[i].SV[j].value)) {
- prob.x[i][k].index = training_set[i].SV[j].idx;
- if (training_set[i].SV[j].idx < scaling_.max &&
- scaling_.obj[training_set[i].SV[j].idx].index == 1)
- prob.x[i][k].value = training_set[i].SV[j].value /
- scaling_.obj[training_set[i].SV[j].idx].value;
- else
- prob.x[i][k].value = training_set[i].SV[j].value;
- k++;
+ for (const auto& train_SV : training_set[i].SV)
+ if (train_SV.idx != -1 && std::isfinite(train_SV.value)) {
+ prob.x[i][k].index = train_SV.idx;
+ if (train_SV.idx < scaling_.max && scaling_.obj[train_SV.idx].index == 1) {
+ prob.x[i][k].value = train_SV.value / scaling_.obj[train_SV.idx].value;
+ }
+ else {
+ prob.x[i][k].value = train_SV.value;
+ }
+ ++k;
}
prob.x[i][k].index = -1;
doCrossValidation();
}
else {
- SVMModel* out;
- out = static_cast<SVMModel*>(svm_train(&prob_, ¶m_));
+ auto* out = reinterpret_cast<SVMModel*>(svm_train(&prob_, ¶m_));
if (out == nullptr) {
PCL_ERROR("[pcl::%s::trainClassifier] Error taining the classifier model.\n",
getClassName().c_str());
bool
pcl::SVMClassify::loadClassifierModel(const char* filename)
{
- SVMModel* out;
- out = static_cast<SVMModel*>(svm_load_model(filename));
+ auto* out = reinterpret_cast<SVMModel*>(svm_load_model(filename));
if (out == nullptr) {
PCL_ERROR("[pcl::%s::loadClassifierModel] Can't open classifier model %s.\n",
getClassName().c_str(),
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
// recursively proceed with indexed child branch
return createLeafRecursive(key_arg,
- depth_mask_arg / 2,
+ depth_mask_arg >> 1,
child_branch,
return_leaf_arg,
parent_of_leaf_arg,
if (child_branch)
// recursively proceed with indexed child branch
- findLeafRecursive(key_arg, depth_mask_arg / 2, child_branch, result_arg);
+ findLeafRecursive(key_arg, depth_mask_arg >> 1, child_branch, result_arg);
}
else {
// we reached leaf node level
if (branch_arg->hasChild(buffer_selector_, child_idx)) {
// return existing leaf node
- LeafNode* leaf_node =
+ auto* leaf_node =
static_cast<LeafNode*>(branch_arg->getChildPtr(buffer_selector_, child_idx));
result_arg = leaf_node->getContainerPtr();
}
if (child_branch) {
// recursively explore the indexed child branch
bool bBranchOccupied =
- deleteLeafRecursive(key_arg, depth_mask_arg / 2, child_branch);
+ deleteLeafRecursive(key_arg, depth_mask_arg >> 1, child_branch);
if (!bBranchOccupied) {
// child branch does not own any sub-child nodes anymore -> delete child branch
break;
}
case LEAF_NODE: {
- LeafNode* child_leaf = static_cast<LeafNode*>(child_node);
+ auto* child_leaf = static_cast<LeafNode*>(child_node);
if (new_leafs_filter_arg) {
if (!branch_arg->hasChild(!buffer_selector_, child_idx)) {
// recursively proceed with indexed child branch
deserializeTreeRecursive(child_branch,
- depth_mask_arg / 2,
+ depth_mask_arg >> 1,
key_arg,
binaryTreeIT_arg,
binaryTreeIT_End_arg,
std::min(static_cast<uindex_t>(OctreeKey::maxDepth),
static_cast<uindex_t>(std::ceil(std::log2(max_voxel_index_arg))));
- // define depthMask_ by setting a single bit to 1 at bit position == tree depth
- depth_mask_ = (1 << (tree_depth - 1));
+ setTreeDepth(tree_depth);
}
//////////////////////////////////////////////////////////////////////////////////////////////
OctreeBase<LeafContainerT, BranchContainerT>::setTreeDepth(uindex_t depth_arg)
{
assert(depth_arg > 0);
+ assert(depth_arg <= OctreeKey::maxDepth);
// set octree depth
octree_depth_ = depth_arg;
- // define depthMask_ by setting a single bit to 1 at bit position == tree depth
+ // define depth_mask_ by setting a single bit to 1 at bit position == tree depth
depth_mask_ = (1 << (depth_arg - 1));
- // define max. keys
+ // define max_key_
max_key_.x = max_key_.y = max_key_.z = (1 << depth_arg) - 1;
}
LeafContainerT*
OctreeBase<LeafContainerT, BranchContainerT>::findLeaf(uindex_t idx_x_arg,
uindex_t idx_y_arg,
- uindex_t idx_z_arg)
+ uindex_t idx_z_arg) const
{
// generate key
OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
- // check if key exist in octree
+ // find the leaf node addressed by key
return (findLeaf(key));
}
// generate key
OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
- // check if key exist in octree
+ // create a leaf node addressed by key
return (createLeaf(key));
}
// generate key
OctreeKey key(idx_x_arg, idx_y_arg, idx_z_arg);
- // check if key exist in octree
+ // delete the leaf node addressed by key
deleteLeafRecursive(key, depth_mask_, root_node_);
}
template <typename LeafContainerT, typename BranchContainerT>
void
OctreeBase<LeafContainerT, BranchContainerT>::serializeTree(
- std::vector<char>& binary_tree_out_arg)
+ std::vector<char>& binary_tree_out_arg) const
{
OctreeKey new_key;
void
OctreeBase<LeafContainerT, BranchContainerT>::serializeTree(
std::vector<char>& binary_tree_out_arg,
- std::vector<LeafContainerT*>& leaf_container_vector_arg)
+ std::vector<LeafContainerT*>& leaf_container_vector_arg) const
{
OctreeKey new_key;
// recursively proceed with indexed child branch
return createLeafRecursive(key_arg,
- depth_mask_arg / 2,
+ depth_mask_arg >> 1,
childBranch,
return_leaf_arg,
parent_of_leaf_arg);
case BRANCH_NODE:
// recursively proceed with indexed child branch
return createLeafRecursive(key_arg,
- depth_mask_arg / 2,
+ depth_mask_arg >> 1,
static_cast<BranchNode*>(child_node),
return_leaf_arg,
parent_of_leaf_arg);
BranchNode* child_branch;
child_branch = static_cast<BranchNode*>(child_node);
- findLeafRecursive(key_arg, depth_mask_arg / 2, child_branch, result_arg);
+ findLeafRecursive(key_arg, depth_mask_arg >> 1, child_branch, result_arg);
break;
case LEAF_NODE:
{
// index to branch child
unsigned char child_idx;
- // indicates if branch is empty and can be safely removed
- bool b_no_children;
+ // indicates if branch has children, if so, it can't be removed
+ bool b_has_children;
// find branch child from key
child_idx = key_arg.getChildIdxWithDepthMask(depth_mask_arg);
child_branch = static_cast<BranchNode*>(child_node);
// recursively explore the indexed child branch
- b_no_children = deleteLeafRecursive(key_arg, depth_mask_arg / 2, child_branch);
+ b_has_children = deleteLeafRecursive(key_arg, depth_mask_arg >> 1, child_branch);
- if (!b_no_children) {
+ if (!b_has_children) {
// child branch does not own any sub-child nodes anymore -> delete child branch
deleteBranchChild(*branch_arg, child_idx);
branch_count_--;
}
// check if current branch still owns children
- b_no_children = false;
- for (child_idx = 0; (!b_no_children) && (child_idx < 8); child_idx++) {
- b_no_children = branch_arg->hasChild(child_idx);
+ b_has_children = false;
+ for (child_idx = 0; (!b_has_children) && (child_idx < 8); child_idx++) {
+ b_has_children = branch_arg->hasChild(child_idx);
}
- // return true if current branch can be deleted
- return (b_no_children);
+ // return false if current branch can be deleted
+ return (b_has_children);
}
//////////////////////////////////////////////////////////////////////////////////////////////
break;
}
case LEAF_NODE: {
- LeafNode* child_leaf = static_cast<LeafNode*>(childNode);
+ auto* child_leaf = static_cast<LeafNode*>(childNode);
if (leaf_container_vector_arg)
leaf_container_vector_arg->push_back(child_leaf->getContainerPtr());
// recursively proceed with new child branch
deserializeTreeRecursive(newBranch,
- depth_mask_arg / 2,
+ depth_mask_arg >> 1,
key_arg,
binary_tree_input_it_arg,
binary_tree_input_it_end_arg,
if (leaf_container_vector_it_arg &&
(*leaf_container_vector_it_arg != *leaf_container_vector_it_end_arg)) {
LeafContainerT& container = **child_leaf;
- container = ***leaf_container_vector_it_arg;
+ LeafContainerT* src_container_ptr = **leaf_container_vector_it_arg;
+ container = *src_container_ptr;
++*leaf_container_vector_it_arg;
}
// bounding box cannot be changed once the octree contains elements
assert(this->leaf_count_ == 0);
- assert(max_x_arg >= min_x_arg);
- assert(max_y_arg >= min_y_arg);
- assert(max_z_arg >= min_z_arg);
+ min_x_ = std::min(min_x_arg, max_x_arg);
+ min_y_ = std::min(min_y_arg, max_y_arg);
+ min_z_ = std::min(min_z_arg, max_z_arg);
- min_x_ = min_x_arg;
- max_x_ = max_x_arg;
-
- min_y_ = min_y_arg;
- max_y_ = max_y_arg;
-
- min_z_ = min_z_arg;
- max_z_ = max_z_arg;
-
- min_x_ = std::min(min_x_, max_x_);
- min_y_ = std::min(min_y_, max_y_);
- min_z_ = std::min(min_z_, max_z_);
-
- max_x_ = std::max(min_x_, max_x_);
- max_y_ = std::max(min_y_, max_y_);
- max_z_ = std::max(min_z_, max_z_);
+ max_x_ = std::max(min_x_arg, max_x_arg);
+ max_y_ = std::max(min_y_arg, max_y_arg);
+ max_z_ = std::max(min_z_arg, max_z_arg);
// generate bit masks for octree
getKeyBitSize();
// bounding box cannot be changed once the octree contains elements
assert(this->leaf_count_ == 0);
- assert(max_x_arg >= 0.0f);
- assert(max_y_arg >= 0.0f);
- assert(max_z_arg >= 0.0f);
-
- min_x_ = 0.0f;
- max_x_ = max_x_arg;
-
- min_y_ = 0.0f;
- max_y_ = max_y_arg;
+ min_x_ = std::min(0.0, max_x_arg);
+ min_y_ = std::min(0.0, max_y_arg);
+ min_z_ = std::min(0.0, max_z_arg);
- min_z_ = 0.0f;
- max_z_ = max_z_arg;
-
- min_x_ = std::min(min_x_, max_x_);
- min_y_ = std::min(min_y_, max_y_);
- min_z_ = std::min(min_z_, max_z_);
-
- max_x_ = std::max(min_x_, max_x_);
- max_y_ = std::max(min_y_, max_y_);
- max_z_ = std::max(min_z_, max_z_);
+ max_x_ = std::max(0.0, max_x_arg);
+ max_y_ = std::max(0.0, max_y_arg);
+ max_z_ = std::max(0.0, max_z_arg);
// generate bit masks for octree
getKeyBitSize();
// bounding box cannot be changed once the octree contains elements
assert(this->leaf_count_ == 0);
- assert(cubeLen_arg >= 0.0f);
-
- min_x_ = 0.0f;
- max_x_ = cubeLen_arg;
-
- min_y_ = 0.0f;
- max_y_ = cubeLen_arg;
-
- min_z_ = 0.0f;
- max_z_ = cubeLen_arg;
-
- min_x_ = std::min(min_x_, max_x_);
- min_y_ = std::min(min_y_, max_y_);
- min_z_ = std::min(min_z_, max_z_);
+ min_x_ = std::min(0.0, cubeLen_arg);
+ min_y_ = std::min(0.0, cubeLen_arg);
+ min_z_ = std::min(0.0, cubeLen_arg);
- max_x_ = std::max(min_x_, max_x_);
- max_y_ = std::max(min_y_, max_y_);
- max_z_ = std::max(min_z_, max_z_);
+ max_x_ = std::max(0.0, cubeLen_arg);
+ max_y_ = std::max(0.0, cubeLen_arg);
+ max_z_ = std::max(0.0, cubeLen_arg);
// generate bit masks for octree
getKeyBitSize();
typename OctreeT>
void
pcl::octree::OctreePointCloud<PointT, LeafContainerT, BranchContainerT, OctreeT>::
- adoptBoundingBoxToPoint(const PointT& point_idx_arg)
+ adoptBoundingBoxToPoint(const PointT& point_arg)
{
const float minValue = std::numeric_limits<float>::epsilon();
// increase octree size until point fits into bounding box
while (true) {
- bool bLowerBoundViolationX = (point_idx_arg.x < min_x_);
- bool bLowerBoundViolationY = (point_idx_arg.y < min_y_);
- bool bLowerBoundViolationZ = (point_idx_arg.z < min_z_);
+ bool bLowerBoundViolationX = (point_arg.x < min_x_);
+ bool bLowerBoundViolationY = (point_arg.y < min_y_);
+ bool bLowerBoundViolationZ = (point_arg.z < min_z_);
- bool bUpperBoundViolationX = (point_idx_arg.x >= max_x_);
- bool bUpperBoundViolationY = (point_idx_arg.y >= max_y_);
- bool bUpperBoundViolationZ = (point_idx_arg.z >= max_z_);
+ bool bUpperBoundViolationX = (point_arg.x >= max_x_);
+ bool bUpperBoundViolationY = (point_arg.y >= max_y_);
+ bool bUpperBoundViolationZ = (point_arg.z >= max_z_);
// do we violate any bounds?
if (bLowerBoundViolationX || bLowerBoundViolationY || bLowerBoundViolationZ ||
// bounding box is not defined - set it to point position
else {
// octree is empty - we set the center of the bounding box to our first pixel
- this->min_x_ = point_idx_arg.x - this->resolution_ / 2;
- this->min_y_ = point_idx_arg.y - this->resolution_ / 2;
- this->min_z_ = point_idx_arg.z - this->resolution_ / 2;
+ this->min_x_ = point_arg.x - this->resolution_ / 2;
+ this->min_y_ = point_arg.y - this->resolution_ / 2;
+ this->min_z_ = point_arg.z - this->resolution_ / 2;
- this->max_x_ = point_idx_arg.x + this->resolution_ / 2;
- this->max_y_ = point_idx_arg.y + this->resolution_ / 2;
- this->max_z_ = point_idx_arg.z + this->resolution_ / 2;
+ this->max_x_ = point_arg.x + this->resolution_ / 2;
+ this->max_y_ = point_arg.y + this->resolution_ / 2;
+ this->max_z_ = point_arg.z + this->resolution_ / 2;
getKeyBitSize();
}
// Iterate through and add edges to adjacency graph
- for (typename std::vector<LeafContainerT*>::iterator leaf_itr = leaf_vector_.begin();
- leaf_itr != leaf_vector_.end();
+ for (auto leaf_itr = leaf_vector_.begin(); leaf_itr != leaf_vector_.end();
++leaf_itr) {
VoxelID u = (leaf_vertex_id_map.find(*leaf_itr))->second;
PointT p_u = voxel_adjacency_graph[u];
case LEAF_NODE: {
PointT new_centroid;
- LeafNode* container = static_cast<LeafNode*>(child_node);
+ auto* container = static_cast<LeafNode*>(child_node);
container->getContainer().getCentroid(new_centroid);
// we reached leaf node level
Indices decoded_point_vector;
- const LeafNode* child_leaf = static_cast<const LeafNode*>(child_node);
+ const auto* child_leaf = static_cast<const LeafNode*>(child_node);
// decode leaf node into decoded_point_vector
(*child_leaf)->getPointIndices(decoded_point_vector);
}
else {
// we reached leaf node level
- const LeafNode* child_leaf = static_cast<const LeafNode*>(child_node);
+ const auto* child_leaf = static_cast<const LeafNode*>(child_node);
Indices decoded_point_vector;
// decode leaf node into decoded_point_vector
// we reached leaf node level
Indices decoded_point_vector;
- const LeafNode* child_leaf = static_cast<const LeafNode*>(child_node);
+ const auto* child_leaf = static_cast<const LeafNode*>(child_node);
float smallest_squared_dist = std::numeric_limits<float>::max();
// we reached leaf node level
Indices decoded_point_vector;
- const LeafNode* child_leaf = static_cast<const LeafNode*>(child_node);
+ const auto* child_leaf = static_cast<const LeafNode*>(child_node);
// decode leaf node into decoded_point_vector
(**child_leaf).getPointIndices(decoded_point_vector);
// If leaf node, get voxel center and increment intersection count
if (node->getNodeType() == LEAF_NODE) {
- const LeafNode* leaf = static_cast<const LeafNode*>(node);
+ const auto* leaf = static_cast<const LeafNode*>(node);
// decode leaf node into k_indices
(*leaf)->getPointIndices(k_indices);
#include <pcl/octree/octree_nodes.h>
#include <pcl/pcl_macros.h>
+#include <array>
#include <vector>
namespace pcl {
inline BufferedBranchNode&
operator=(const BufferedBranchNode& source_arg)
{
- memset(child_node_array_, 0, sizeof(child_node_array_));
-
- for (unsigned char b = 0; b < 2; ++b)
- for (unsigned char i = 0; i < 8; ++i)
- if (source_arg.child_node_array_[b][i])
+ child_node_array_ = {};
+ for (unsigned char b = 0; b < 2; ++b) {
+ for (unsigned char i = 0; i < 8; ++i) {
+ if (source_arg.child_node_array_[b][i]) {
child_node_array_[b][i] = source_arg.child_node_array_[b][i]->deepCopy();
-
+ }
+ }
+ }
return (*this);
}
/** \brief Empty constructor. */
- ~BufferedBranchNode() {}
+ ~BufferedBranchNode() override = default;
/** \brief Method to perform a deep copy of the octree */
BufferedBranchNode*
inline void
reset()
{
- memset(&child_node_array_[0][0], 0, sizeof(OctreeNode*) * 8 * 2);
+ child_node_array_ = {};
}
/** \brief Get const pointer to container */
protected:
ContainerT container_;
- OctreeNode* child_node_array_[2][8];
+ template <typename T, std::size_t ROW, std::size_t COL>
+ using OctreeMatrix = std::array<std::array<T, COL>, ROW>;
+
+ OctreeMatrix<OctreeNode*, 2, 8> child_node_array_{};
};
/** \brief @b Octree double buffer class
inline BranchNode*
createBranchChild(BranchNode& branch_arg, unsigned char child_idx_arg)
{
- BranchNode* new_branch_child = new BranchNode();
+ auto* new_branch_child = new BranchNode();
branch_arg.setChildPtr(
buffer_selector_, child_idx_arg, static_cast<OctreeNode*>(new_branch_child));
inline LeafNode*
createLeafChild(BranchNode& branch_arg, unsigned char child_idx_arg)
{
- LeafNode* new_leaf_child = new LeafNode();
+ auto* new_leaf_child = new LeafNode();
branch_arg.setChildPtr(buffer_selector_, child_idx_arg, new_leaf_child);
friend class OctreeFixedDepthIterator<OctreeT>;
friend class OctreeLeafNodeDepthFirstIterator<OctreeT>;
friend class OctreeLeafNodeBreadthFirstIterator<OctreeT>;
+ friend class OctreeIteratorBase<const OctreeT>;
+ friend class OctreeDepthFirstIterator<const OctreeT>;
+ friend class OctreeBreadthFirstIterator<const OctreeT>;
+ friend class OctreeFixedDepthIterator<const OctreeT>;
+ friend class OctreeLeafNodeDepthFirstIterator<const OctreeT>;
+ friend class OctreeLeafNodeBreadthFirstIterator<const OctreeT>;
// Octree default iterators
using Iterator = OctreeDepthFirstIterator<OctreeT>;
- using ConstIterator = const OctreeDepthFirstIterator<OctreeT>;
+ using ConstIterator = OctreeDepthFirstIterator<const OctreeT>;
Iterator
begin(uindex_t max_depth_arg = 0u)
return Iterator(this, max_depth_arg ? max_depth_arg : this->octree_depth_);
};
+ ConstIterator
+ begin(uindex_t max_depth_arg = 0u) const
+ {
+ return ConstIterator(this, max_depth_arg ? max_depth_arg : this->octree_depth_);
+ };
+
+ ConstIterator
+ cbegin(uindex_t max_depth_arg = 0u) const
+ {
+ return ConstIterator(this, max_depth_arg ? max_depth_arg : this->octree_depth_);
+ };
+
const Iterator
end()
{
return Iterator(this, 0, nullptr);
};
+ const ConstIterator
+ end() const
+ {
+ return ConstIterator(this, 0, nullptr);
+ };
+
+ const ConstIterator
+ cend() const
+ {
+ return ConstIterator(this, 0, nullptr);
+ };
+
// Octree leaf node iterators
// The previous deprecated names
// LeafNodeIterator and ConstLeafNodeIterator are deprecated.
// Please use LeafNodeDepthFirstIterator and ConstLeafNodeDepthFirstIterator instead.
using LeafNodeIterator = OctreeLeafNodeDepthFirstIterator<OctreeT>;
- using ConstLeafNodeIterator = const OctreeLeafNodeDepthFirstIterator<OctreeT>;
+ using ConstLeafNodeIterator = OctreeLeafNodeDepthFirstIterator<const OctreeT>;
- // The currently valide names
+ // The currently valid names
using LeafNodeDepthFirstIterator = OctreeLeafNodeDepthFirstIterator<OctreeT>;
using ConstLeafNodeDepthFirstIterator =
- const OctreeLeafNodeDepthFirstIterator<OctreeT>;
+ OctreeLeafNodeDepthFirstIterator<const OctreeT>;
LeafNodeDepthFirstIterator
leaf_depth_begin(uindex_t max_depth_arg = 0u)
this, max_depth_arg ? max_depth_arg : this->octree_depth_);
};
+ ConstLeafNodeDepthFirstIterator
+ leaf_depth_begin(uindex_t max_depth_arg = 0u) const
+ {
+ return ConstLeafNodeDepthFirstIterator(
+ this, max_depth_arg ? max_depth_arg : this->octree_depth_);
+ };
+
const LeafNodeDepthFirstIterator
leaf_depth_end()
{
return LeafNodeDepthFirstIterator(this, 0, nullptr);
};
+ const ConstLeafNodeDepthFirstIterator
+ leaf_depth_end() const
+ {
+ return ConstLeafNodeDepthFirstIterator(this, 0, nullptr);
+ };
+
// Octree depth-first iterators
using DepthFirstIterator = OctreeDepthFirstIterator<OctreeT>;
- using ConstDepthFirstIterator = const OctreeDepthFirstIterator<OctreeT>;
+ using ConstDepthFirstIterator = OctreeDepthFirstIterator<const OctreeT>;
DepthFirstIterator
depth_begin(uindex_t max_depth_arg = 0u)
max_depth_arg ? max_depth_arg : this->octree_depth_);
};
+ ConstDepthFirstIterator
+ depth_begin(uindex_t max_depth_arg = 0u) const
+ {
+ return ConstDepthFirstIterator(this,
+ max_depth_arg ? max_depth_arg : this->octree_depth_);
+ };
+
const DepthFirstIterator
depth_end()
{
return DepthFirstIterator(this, 0, nullptr);
};
+ const ConstDepthFirstIterator
+ depth_end() const
+ {
+ return ConstDepthFirstIterator(this, 0, nullptr);
+ };
+
// Octree breadth-first iterators
using BreadthFirstIterator = OctreeBreadthFirstIterator<OctreeT>;
- using ConstBreadthFirstIterator = const OctreeBreadthFirstIterator<OctreeT>;
+ using ConstBreadthFirstIterator = OctreeBreadthFirstIterator<const OctreeT>;
BreadthFirstIterator
breadth_begin(uindex_t max_depth_arg = 0u)
max_depth_arg ? max_depth_arg : this->octree_depth_);
};
+ ConstBreadthFirstIterator
+ breadth_begin(uindex_t max_depth_arg = 0u) const
+ {
+ return ConstBreadthFirstIterator(
+ this, max_depth_arg ? max_depth_arg : this->octree_depth_);
+ };
+
const BreadthFirstIterator
breadth_end()
{
return BreadthFirstIterator(this, 0, nullptr);
};
+ const ConstBreadthFirstIterator
+ breadth_end() const
+ {
+ return ConstBreadthFirstIterator(this, 0, nullptr);
+ };
+
// Octree breadth iterators at a given depth
using FixedDepthIterator = OctreeFixedDepthIterator<OctreeT>;
- using ConstFixedDepthIterator = const OctreeFixedDepthIterator<OctreeT>;
+ using ConstFixedDepthIterator = OctreeFixedDepthIterator<const OctreeT>;
FixedDepthIterator
fixed_depth_begin(uindex_t fixed_depth_arg = 0u)
return FixedDepthIterator(this, fixed_depth_arg);
};
+ ConstFixedDepthIterator
+ fixed_depth_begin(uindex_t fixed_depth_arg = 0u) const
+ {
+ return ConstFixedDepthIterator(this, fixed_depth_arg);
+ };
+
const FixedDepthIterator
fixed_depth_end()
{
return FixedDepthIterator(this, 0, nullptr);
};
+ const ConstFixedDepthIterator
+ fixed_depth_end() const
+ {
+ return ConstFixedDepthIterator(this, 0, nullptr);
+ };
+
// Octree leaf node iterators
using LeafNodeBreadthFirstIterator = OctreeLeafNodeBreadthFirstIterator<OctreeT>;
using ConstLeafNodeBreadthFirstIterator =
- const OctreeLeafNodeBreadthFirstIterator<OctreeT>;
+ OctreeLeafNodeBreadthFirstIterator<const OctreeT>;
LeafNodeBreadthFirstIterator
leaf_breadth_begin(uindex_t max_depth_arg = 0u)
this, max_depth_arg ? max_depth_arg : this->octree_depth_);
};
+ ConstLeafNodeBreadthFirstIterator
+ leaf_breadth_begin(uindex_t max_depth_arg = 0u) const
+ {
+ return ConstLeafNodeBreadthFirstIterator(
+ this, max_depth_arg ? max_depth_arg : this->octree_depth_);
+ };
+
const LeafNodeBreadthFirstIterator
leaf_breadth_end()
{
return LeafNodeBreadthFirstIterator(this, 0, nullptr);
};
+ const ConstLeafNodeBreadthFirstIterator
+ leaf_breadth_end() const
+ {
+ return ConstLeafNodeBreadthFirstIterator(this, 0, nullptr);
+ };
+
/** \brief Empty constructor. */
OctreeBase();
depth_mask_ = source.depth_mask_;
max_key_ = source.max_key_;
octree_depth_ = source.octree_depth_;
+ dynamic_depth_enabled_ = source.dynamic_depth_enabled_;
return (*this);
}
* \return pointer to leaf node container if found, null pointer otherwise.
*/
LeafContainerT*
- findLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg);
+ findLeaf(uindex_t idx_x_arg, uindex_t idx_y_arg, uindex_t idx_z_arg) const;
/** \brief idx_x_arg for the existence of leaf node at (idx_x_arg, idx_y_arg,
* idx_z_arg).
* structure.
*/
void
- serializeTree(std::vector<char>& binary_tree_out_arg);
+ serializeTree(std::vector<char>& binary_tree_out_arg) const;
/** \brief Serialize octree into a binary output vector describing its branch node
* structure and push all LeafContainerT elements stored in the octree to a vector.
*/
void
serializeTree(std::vector<char>& binary_tree_out_arg,
- std::vector<LeafContainerT*>& leaf_container_vector_arg);
+ std::vector<LeafContainerT*>& leaf_container_vector_arg) const;
/** \brief Outputs a vector of all LeafContainerT elements that are stored within the
* octree leaf nodes.
BranchNode*
createBranchChild(BranchNode& branch_arg, unsigned char child_idx_arg)
{
- BranchNode* new_branch_child = new BranchNode();
+ auto* new_branch_child = new BranchNode();
branch_arg[child_idx_arg] = static_cast<OctreeNode*>(new_branch_child);
return new_branch_child;
LeafNode*
createLeafChild(BranchNode& branch_arg, unsigned char child_idx_arg)
{
- LeafNode* new_leaf_child = new LeafNode();
+ auto* new_leaf_child = new LeafNode();
branch_arg[child_idx_arg] = static_cast<OctreeNode*>(new_leaf_child);
return new_leaf_child;
* \param depth_mask_arg: depth mask used for octree key analysis and branch depth
* indicator
* \param branch_arg: current branch node
- * \return "true" if branch does not contain any childs; "false" otherwise. This
- * indicates if current branch can be deleted, too.
+ * \return "true" if current branch contains child(ren); "false" otherwise. If it's
+ * true, current branch cannot be deleted.
**/
bool
deleteLeafRecursive(const OctreeKey& key_arg,
* \return "true"
**/
bool
- octreeCanResize()
+ octreeCanResize() const
{
return (true);
}
/** \brief Empty addPointIndex implementation. This leaf node does not store any point
* indices.
*/
- void
- addPointIndex(const index_t&)
+ virtual void
+ addPointIndex(index_t)
{}
/** \brief Empty getPointIndex implementation as this leaf node does not store any
getPointIndex(index_t&) const
{}
+ /** \brief Empty getPointIndex implementation as this leaf node does not store any
+ * point indices.
+ */
+ virtual index_t
+ getPointIndex() const
+ {
+ assert("getPointIndex: undefined point index");
+ return -1;
+ }
+
/** \brief Empty getPointIndices implementation as this leaf node does not store any
* data. \
*/
- void
+ virtual void
getPointIndices(Indices&) const
{}
};
/** \brief Empty addPointIndex implementation. This leaf node does not store any point
* indices.
*/
- void addPointIndex(index_t) {}
+ void
+ addPointIndex(index_t) override
+ {}
/** \brief Empty getPointIndex implementation as this leaf node does not store any
* point indices.
*/
index_t
- getPointIndex() const
+ getPointIndex() const override
{
assert("getPointIndex: undefined point index");
return -1;
* data.
*/
void
- getPointIndices(Indices&) const
+ getPointIndices(Indices&) const override
{}
};
bool
operator==(const OctreeContainerBase& other) const override
{
- const OctreeContainerPointIndex* otherConDataT =
- dynamic_cast<const OctreeContainerPointIndex*>(&other);
+ const auto* otherConDataT = dynamic_cast<const OctreeContainerPointIndex*>(&other);
return (this->data_ == otherConDataT->data_);
}
* \param[in] data_arg index to be stored within leaf node.
*/
void
- addPointIndex(index_t data_arg)
+ addPointIndex(index_t data_arg) override
{
data_ = data_arg;
}
* \return index stored within container.
*/
index_t
- getPointIndex() const
+ getPointIndex() const override
{
return data_;
}
* data vector
*/
void
- getPointIndices(Indices& data_vector_arg) const
+ getPointIndices(Indices& data_vector_arg) const override
{
if (data_ != static_cast<index_t>(-1))
data_vector_arg.push_back(data_);
uindex_t
getSize() const override
{
- return data_ != static_cast<index_t>(-1) ? 0 : 1;
+ return data_ == static_cast<index_t>(-1) ? 0 : 1;
}
/** \brief Reset leaf node memory to zero. */
bool
operator==(const OctreeContainerBase& other) const override
{
- const OctreeContainerPointIndices* otherConDataTVec =
+ const auto* otherConDataTVec =
dynamic_cast<const OctreeContainerPointIndices*>(&other);
return (this->leafDataTVector_ == otherConDataTVec->leafDataTVector_);
* \param[in] data_arg index to be stored within leaf node.
*/
void
- addPointIndex(index_t data_arg)
+ addPointIndex(index_t data_arg) override
{
leafDataTVector_.push_back(data_arg);
}
* \return index stored within container.
*/
index_t
- getPointIndex() const
+ getPointIndex() const override
{
return leafDataTVector_.back();
}
* within data vector
*/
void
- getPointIndices(Indices& data_vector_arg) const
+ getPointIndices(Indices& data_vector_arg) const override
{
data_vector_arg.insert(
data_vector_arg.end(), leafDataTVector_.begin(), leafDataTVector_.end());
* \author Julius Kammerl (julius@kammerl.de)
*/
template <typename OctreeT>
-class OctreeIteratorBase : public std::iterator<std::forward_iterator_tag,
- const OctreeNode,
- void,
- const OctreeNode*,
- const OctreeNode&> {
+class OctreeIteratorBase {
public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const OctreeNode;
+ using difference_type = void;
+ using pointer = const OctreeNode*;
+ using reference = const OctreeNode&;
+
using LeafNode = typename OctreeT::LeafNode;
using BranchNode = typename OctreeT::BranchNode;
{}
/** \brief Empty deconstructor. */
- virtual ~OctreeIteratorBase() {}
+ virtual ~OctreeIteratorBase() = default;
/** \brief Equal comparison operator
* \param[in] other OctreeIteratorBase to compare with
}
}
+ /** \brief Preincrement operator.
+ * \note step to next octree node
+ */
+ virtual OctreeIteratorBase&
+ operator++() = 0;
+
/** \brief Get octree key for the current iterator octree node
* \return octree key of current node
*/
/** \brief *operator.
* \return pointer to the current octree node
*/
- inline OctreeNode*
+ virtual OctreeNode*
operator*() const
{ // return designated object
if (octree_ && current_state_) {
* root node.
* \param[in] max_depth_arg Depth limitation during traversal
* \param[in] current_state A pointer to the current iterator state
+ * \param[in] stack A stack structure used for depth first search
*
* \warning For advanced users only.
*/
* \return pointer to the current octree leaf node
*/
OctreeNode*
- operator*() const
+ operator*() const override
{
// return designated object
OctreeNode* ret = 0;
*/
inline OctreeLeafNodeBreadthFirstIterator
operator++(int);
+
+ /** \brief *operator.
+ * \return pointer to the current octree leaf node
+ */
+ OctreeNode*
+ operator*() const override
+ {
+ // return designated object
+ OctreeNode* ret = 0;
+
+ if (this->current_state_ &&
+ (this->current_state_->node_->getNodeType() == LEAF_NODE))
+ ret = this->current_state_->node_;
+ return (ret);
+ }
};
} // namespace octree
#pragma once
+#include <pcl/types.h> // for uindex_t
+
#include <cstdint>
#include <cstring> // for memcpy
#include <pcl/memory.h>
#include <pcl/pcl_macros.h>
+#include <array>
#include <cassert>
namespace pcl {
*/
class PCL_EXPORTS OctreeNode {
public:
- OctreeNode() {}
+ OctreeNode() = default;
- virtual ~OctreeNode() {}
- /** \brief Pure virtual method for receiving the type of octree node (branch or leaf)
+ virtual ~OctreeNode() = default;
+ /** \brief Pure virtual method for retrieving the type of octree node (branch or leaf)
*/
virtual node_type_t
getNodeType() const = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** \brief @b Abstract octree leaf class
- * \note Octree leafs may collect data of type DataT
+ * \note Octree leaves may collect data of type ContainerT
* \author Julius Kammerl (julius@kammerl.de)
*/
/** \brief Empty deconstructor. */
- ~OctreeLeafNode() {}
+ ~OctreeLeafNode() override = default;
/** \brief Method to perform a deep copy of the octree */
OctreeLeafNode<ContainerT>*
OctreeBranchNode() : OctreeNode()
{
// reset pointer to child node vectors
- memset(child_node_array_, 0, sizeof(child_node_array_));
+ child_node_array_ = {};
}
/** \brief Empty constructor. */
OctreeBranchNode(const OctreeBranchNode& source) : OctreeNode()
{
- memset(child_node_array_, 0, sizeof(child_node_array_));
+ child_node_array_ = {};
for (unsigned char i = 0; i < 8; ++i)
- if (source.child_node_array_[i])
+ if (source.child_node_array_[i]) {
child_node_array_[i] = source.child_node_array_[i]->deepCopy();
+ }
}
/** \brief Copy operator. */
inline OctreeBranchNode&
operator=(const OctreeBranchNode& source)
{
- memset(child_node_array_, 0, sizeof(child_node_array_));
+ child_node_array_ = {};
- for (unsigned char i = 0; i < 8; ++i)
- if (source.child_node_array_[i])
+ for (unsigned char i = 0; i < 8; ++i) {
+ if (source.child_node_array_[i]) {
child_node_array_[i] = source.child_node_array_[i]->deepCopy();
+ }
+ }
return (*this);
}
/** \brief Empty deconstructor. */
- ~OctreeBranchNode() {}
+ ~OctreeBranchNode() override = default;
/** \brief Access operator.
* \param child_idx_arg: index to child node
void
reset()
{
- memset(child_node_array_, 0, sizeof(child_node_array_));
+ child_node_array_ = {};
container_.reset();
}
}
protected:
- OctreeNode* child_node_array_[8];
+ std::array<OctreeNode*, 8> child_node_array_{};
ContainerT container_;
};
deleteTree()
{
// reset bounding box
- min_x_ = min_y_ = max_y_ = min_z_ = max_z_ = 0;
+ min_x_ = max_x_ = min_y_ = max_y_ = min_z_ = max_z_ = 0;
this->bounding_box_defined_ = false;
OctreeT::deleteTree();
OctreePointCloudAdjacencyContainer() : OctreeContainerBase() { this->reset(); }
/** \brief Empty class deconstructor. */
- ~OctreePointCloudAdjacencyContainer() {}
+ ~OctreePointCloudAdjacencyContainer() override = default;
/** \brief Returns the number of neighbors this leaf has
* \returns number of neighbors
virtual OctreePointCloudAdjacencyContainer*
deepCopy() const
{
- OctreePointCloudAdjacencyContainer* new_container =
- new OctreePointCloudAdjacencyContainer;
+ auto* new_container = new OctreePointCloudAdjacencyContainer;
new_container->setNeighbors(this->neighbors_);
new_container->setPointCounter(this->num_points_);
return new_container;
void
removeNeighbor(OctreePointCloudAdjacencyContainer* neighbor)
{
- for (iterator neighb_it = neighbors_.begin(); neighb_it != neighbors_.end();
+ for (auto neighb_it = neighbors_.begin(); neighb_it != neighbors_.end();
++neighb_it) {
if (*neighb_it == neighbor) {
neighbors_.erase(neighb_it);
OctreePointCloudDensityContainer() : point_counter_(0) {}
/** \brief Empty class deconstructor. */
- ~OctreePointCloudDensityContainer() {}
+ ~OctreePointCloudDensityContainer() override = default;
/** \brief deep copy function */
virtual OctreePointCloudDensityContainer*
bool
operator==(const OctreeContainerBase& other) const override
{
- const OctreePointCloudDensityContainer* otherContainer =
+ const auto* otherContainer =
dynamic_cast<const OctreePointCloudDensityContainer*>(&other);
return (this->point_counter_ == otherContainer->point_counter_);
/** \brief Read input data. Only an internal counter is increased.
*/
- void addPointIndex(uindex_t) { point_counter_++; }
+ void
+ addPointIndex(index_t) override
+ {
+ point_counter_++;
+ }
/** \brief Return point counter.
* \return Amount of points
/** \brief Empty class deconstructor. */
- ~OctreePointCloudDensity() {}
+ ~OctreePointCloudDensity() override = default;
/** \brief Get the amount of points within a leaf node voxel which is addressed by a
* point
/** \brief Empty class constructor. */
- ~OctreePointCloudOccupancy() {}
+ ~OctreePointCloudOccupancy() override = default;
/** \brief Set occupied voxel at point.
* \param point_arg: input point
{}
/** \brief Empty class constructor. */
- ~OctreePointCloudPointVector() {}
+ ~OctreePointCloudPointVector() override = default;
};
} // namespace octree
} // namespace pcl
{}
/** \brief Empty class constructor. */
- ~OctreePointCloudSinglePoint() {}
+ ~OctreePointCloudSinglePoint() override = default;
};
} // namespace octree
OctreePointCloudVoxelCentroidContainer() { this->reset(); }
/** \brief Empty class deconstructor. */
- ~OctreePointCloudVoxelCentroidContainer() {}
+ ~OctreePointCloudVoxelCentroidContainer() override = default;
/** \brief deep copy function */
virtual OctreePointCloudVoxelCentroidContainer*
/** \brief Empty class deconstructor. */
- ~OctreePointCloudVoxelCentroid() {}
+ ~OctreePointCloudVoxelCentroid() override = default;
/** \brief Add DataT object to leaf node at octree key.
* \param pointIdx_arg
/** \brief Get indices of all voxels that are intersected by a ray (origin,
* direction).
- * \param[in] origin ray origin \param[in] direction ray direction vector
+ * \param[in] origin ray origin
+ * \param[in] direction ray direction vector
* \param[out] k_indices resulting point indices from intersected voxels
* \param[in] max_voxel_count stop raycasting when this many voxels intersected (0:
* disable)
/** \brief Recursive search method that explores the octree and finds neighbors within
* a given radius
- * \param[in] point query point \param[in] radiusSquared squared search radius
+ * \param[in] point query point
+ * \param[in] radiusSquared squared search radius
* \param[in] node current octree node to be explored
* \param[in] key octree key addressing a leaf node.
* \param[in] tree_depth current depth/level in the octree
* \param[in] max_x octree nodes X coordinate of upper bounding box corner
* \param[in] max_y octree nodes Y coordinate of upper bounding box corner
* \param[in] max_z octree nodes Z coordinate of upper bounding box corner
- * \param[in] a
+ * \param[in] a number used for voxel child index remapping
* \param[in] node current octree node to be explored
* \param[in] key octree key addressing a leaf node.
* \param[out] voxel_center_list results are written to this vector of PointT elements
* \param[in] max_x octree nodes X coordinate of upper bounding box corner
* \param[in] max_y octree nodes Y coordinate of upper bounding box corner
* \param[in] max_z octree nodes Z coordinate of upper bounding box corner
- * \param[in] a
+ * \param[in] a number used for voxel child index remapping
* \param[in] node current octree node to be explored
* \param[in] key octree key addressing a leaf node.
* \param[out] k_indices resulting indices
uindex_t max_voxel_count) const;
/** \brief Initialize raytracing algorithm
- * \param origin
- * \param direction
- * \param[in] min_x octree nodes X coordinate of lower bounding box corner
- * \param[in] min_y octree nodes Y coordinate of lower bounding box corner
- * \param[in] min_z octree nodes Z coordinate of lower bounding box corner
- * \param[in] max_x octree nodes X coordinate of upper bounding box corner
- * \param[in] max_y octree nodes Y coordinate of upper bounding box corner
- * \param[in] max_z octree nodes Z coordinate of upper bounding box corner
- * \param a
+ * \param[in] origin ray origin
+ * \param[in] direction ray direction vector
+ * \param[out] min_x octree nodes X coordinate of lower bounding box corner
+ * \param[out] min_y octree nodes Y coordinate of lower bounding box corner
+ * \param[out] min_z octree nodes Z coordinate of lower bounding box corner
+ * \param[out] max_x octree nodes X coordinate of upper bounding box corner
+ * \param[out] max_y octree nodes Y coordinate of upper bounding box corner
+ * \param[out] max_z octree nodes Z coordinate of upper bounding box corner
+ * \param[out] a number used for voxel child index remapping
*/
inline void
initIntersectedVoxel(Eigen::Vector3f& origin,
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
"include/pcl/${SUBSYS_NAME}/visualization/viewport.h"
)
-# Code in subdirectory `visualization` may use deprecated declarations when using OpenGLv1
-# Add the GCC exclusive rules for -Werror only for OpenGLv1 compile to avoid build interruption
-if(VTK_RENDERING_BACKEND_OPENGL_VERSION VERSION_LESS 2)
- if(CMAKE_COMPILER_IS_GNUCXX)
- add_compile_options("-Wno-error=deprecated-declarations")
- endif()
-endif()
-
set(LIB_NAME "pcl_${SUBSYS_NAME}")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
#if defined __GNUC__
# pragma GCC system_header
#endif
+PCL_DEPRECATED_HEADER(1, 16, "Please include the needed boost headers directly.")
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#define cJSON_IsReference 256
/* The cJSON structure: */
-typedef struct cJSON {
+typedef struct cJSON { // NOLINT
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
-typedef struct cJSON_Hooks {
+typedef struct cJSON_Hooks { // NOLINT
void *(*malloc_fn)(std::size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;
}
virtual
- ~LRUCacheItem () { }
+ ~LRUCacheItem () = default;
T item;
std::size_t timestamp;
int evict_count = 0;
// Get LRU key iterator
- KeyIndexIterator key_it = key_index_.begin ();
+ auto key_it = key_index_.begin ();
while (size + item_size >= capacity_)
{
size_ += item_size;
// Insert most-recently-used key at the end of our key index
- KeyIndexIterator it = key_index_.insert (key_index_.end (), key);
+ auto it = key_index_.insert (key_index_.end (), key);
// Add to cache
cache_.insert (std::make_pair (key, std::make_pair (value, it)));
////////////////////////////////////////////////////////////////////////////////
template<typename ContainerT, typename PointT> void
- OutofcoreOctreeBase<ContainerT, PointT>::writeVPythonVisual (const boost::filesystem::path filename)
+ OutofcoreOctreeBase<ContainerT, PointT>::writeVPythonVisual (const boost::filesystem::path& filename)
{
std::ofstream f (filename.c_str ());
std::vector<BranchNode*> current_branch (number_of_nodes, static_cast<BranchNode*>(nullptr));
current_branch[0] = root_node_;
- assert (current_branch.back () != 0);
+ assert (current_branch.back () != nullptr);
this->buildLODRecursive (current_branch);
}
assert (leaf_input_cloud->width*leaf_input_cloud->height > 0);
//go up the tree, re-downsampling the full resolution leaf cloud at lower and lower resolution
- for (std::int64_t level = static_cast<std::int64_t>(current_branch.size ()-1); level >= 1; level--)
+ for (auto level = static_cast<std::int64_t>(current_branch.size ()-1); level >= 1; level--)
{
BranchNode* target_parent = current_branch[level-1];
- assert (target_parent != 0);
+ assert (target_parent != nullptr);
double exponent = static_cast<double>(current_branch.size () - target_parent->getDepth ());
double current_depth_sample_percent = pow (sample_percent_, exponent);
lod_filter_ptr_->setInputCloud (leaf_input_cloud);
//set sample size to 1/8 of total points (12.5%)
- std::uint64_t sample_size = static_cast<std::uint64_t> (static_cast<double> (leaf_input_cloud->width*leaf_input_cloud->height) * current_depth_sample_percent);
+ auto sample_size = static_cast<std::uint64_t> (static_cast<double> (leaf_input_cloud->width*leaf_input_cloud->height) * current_depth_sample_percent);
if (sample_size == 0)
sample_size = 1;
if (side_length < leaf_resolution)
return (0);
- std::uint64_t res = static_cast<std::uint64_t> (std::ceil (std::log2 (side_length / leaf_resolution)));
+ auto res = static_cast<std::uint64_t> (std::ceil (std::log2 (side_length / leaf_resolution)));
PCL_DEBUG ("[pcl::outofcore::OutofcoreOctreeBase::calculateDepth] Setting depth to %d\n",res);
return (res);
, payload_ ()
, node_metadata_ (new OutofcoreOctreeNodeMetadata ())
{
- assert (tree != NULL);
+ assert (tree != nullptr);
node_metadata_->setOutofcoreVersion (3);
init_root_node (bb_min, bb_max, tree, root_name);
}
template<typename ContainerT, typename PointT> void
OutofcoreOctreeBaseNode<ContainerT, PointT>::init_root_node (const Eigen::Vector3d& bb_min, const Eigen::Vector3d& bb_max, OutofcoreOctreeBase<ContainerT, PointT> * const tree, const boost::filesystem::path& root_name)
{
- assert (tree != NULL);
+ assert (tree != nullptr);
parent_ = nullptr;
root_node_ = this;
num_children_ = 0;
Eigen::Vector3d tmp_max = bb_max;
- Eigen::Vector3d tmp_min = bb_min;
// Need to make the bounding box slightly bigger so points that fall on the max side aren't excluded
double epsilon = 1e-8;
tmp_max += epsilon*Eigen::Vector3d (1.0, 1.0, 1.0);
- node_metadata_->setBoundingBox (tmp_min, tmp_max);
+ node_metadata_->setBoundingBox (bb_min, tmp_max);
node_metadata_->setDirectoryPathname (root_name.parent_path ());
node_metadata_->setOutofcoreVersion (3);
template<typename ContainerT, typename PointT> std::uint64_t
OutofcoreOctreeBaseNode<ContainerT, PointT>::addPointCloud (const typename pcl::PCLPointCloud2::Ptr& input_cloud, const bool skip_bb_check)
{
- assert (this->root_node_->m_tree_ != NULL);
+ assert (this->root_node_->m_tree_ != nullptr);
if (input_cloud->height*input_cloud->width == 0)
return (0);
template<typename ContainerT, typename PointT> void
OutofcoreOctreeBaseNode<ContainerT, PointT>::randomSample(const AlignedPointTVector& p, AlignedPointTVector& insertBuff, const bool skip_bb_check)
{
- assert (this->root_node_->m_tree_ != NULL);
+ assert (this->root_node_->m_tree_ != nullptr);
AlignedPointTVector sampleBuff;
if (!skip_bb_check)
// Derive percentage from specified sample_percent and tree depth
const double percent = pow(sample_percent_, double((this->root_node_->m_tree_->getDepth () - depth_)));
- const std::uint64_t samplesize = static_cast<std::uint64_t>(percent * static_cast<double>(sampleBuff.size()));
+ const auto samplesize = static_cast<std::uint64_t>(percent * static_cast<double>(sampleBuff.size()));
const std::uint64_t inputsize = sampleBuff.size();
if(samplesize > 0)
template<typename ContainerT, typename PointT> std::uint64_t
OutofcoreOctreeBaseNode<ContainerT, PointT>::addDataAtMaxDepth (const AlignedPointTVector& p, const bool skip_bb_check)
{
- assert (this->root_node_->m_tree_ != NULL);
+ assert (this->root_node_->m_tree_ != nullptr);
// Trust me, just add the points
if (skip_bb_check)
// when adding data and generating sampled LOD
// If the max depth has been reached
- assert (this->root_node_->m_tree_ != NULL );
+ assert (this->root_node_->m_tree_ != nullptr );
if (this->depth_ == this->root_node_->m_tree_->getDepth ())
{
template<typename ContainerT, typename PointT> void
OutofcoreOctreeBaseNode<ContainerT, PointT>::queryBBIntersects (const Eigen::Vector3d& min_bb, const Eigen::Vector3d& max_bb, const std::uint32_t query_depth, std::list<std::string>& file_names)
{
-
- Eigen::Vector3d my_min = min_bb;
- Eigen::Vector3d my_max = max_bb;
-
- if (intersectsWithBoundingBox (my_min, my_max))
+ if (intersectsWithBoundingBox (min_bb, max_bb))
{
if (this->depth_ < query_depth)
{
for (std::size_t i = 0; i < 8; i++)
{
if (children_[i])
- children_[i]->queryBBIntersects (my_min, my_max, query_depth, file_names);
+ children_[i]->queryBBIntersects (min_bb, max_bb, query_depth, file_names);
}
}
else if (hasUnloadedChildren ())
for (std::size_t i = 0; i < 8; i++)
{
if (children_[i])
- children_[i]->queryBBIntersects (my_min, my_max, query_depth, file_names);
+ children_[i]->queryBBIntersects (min_bb, max_bb, query_depth, file_names);
}
}
return;
//use STL random_shuffle and push back a random selection of the points onto our list
std::shuffle (payload_cache_within_region.begin (), payload_cache_within_region.end (), std::mt19937(std::random_device()()));
- std::size_t numpick = static_cast<std::size_t> (percent * static_cast<double> (payload_cache_within_region.size ()));;
+ auto numpick = static_cast<std::size_t> (percent * static_cast<double> (payload_cache_within_region.size ()));;
for (std::size_t i = 0; i < numpick; i++)
{
this->parent_ = super;
root_node_ = super->root_node_;
m_tree_ = super->root_node_->m_tree_;
- assert (m_tree_ != NULL);
+ assert (m_tree_ != nullptr);
depth_ = super->depth_ + 1;
num_children_ = 0;
#include <ctime>
// Boost
-#include <pcl/outofcore/boost.h>
#include <boost/random/bernoulli_distribution.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/uuid/uuid_io.hpp>
PointT temp;
//open our file
FILE* f = fopen (disk_storage_filename_.c_str (), "rbe");
- assert (f != NULL);
+ assert (f != nullptr);
//seek the right length;
int seekret = _fseeki64 (f, idx * sizeof(PointT), SEEK_SET);
std::sort (offsets.begin (), offsets.end ());
FILE* f = fopen (disk_storage_filename_.c_str (), "rbe");
- assert (f != NULL);
+ assert (f != nullptr);
PointT p;
char* loc = reinterpret_cast<char*> (&p);
buffcount = count - filecount;
}
- std::uint64_t filesamp = static_cast<std::uint64_t> (percent * static_cast<double> (filecount));
+ auto filesamp = static_cast<std::uint64_t> (percent * static_cast<double> (filecount));
std::uint64_t buffsamp = (buffcount > 0) ? (static_cast<std::uint64_t > (percent * static_cast<double> (buffcount))) : 0;
std::sort (offsets.begin (), offsets.end ());
FILE* f = fopen (disk_storage_filename_.c_str (), "rbe");
- assert (f != NULL);
+ assert (f != nullptr);
PointT p;
char* loc = reinterpret_cast<char*> (&p);
for (std::uint64_t i = 0; i < filesamp; i++)
AlignedPointTVector& v)
{
v.resize (count);
- memcpy (v.data (), container_.data () + start, count * sizeof(PointT));
+ std::copy(container_.cbegin() + start, container_.cbegin() + start + count, v.begin());
}
////////////////////////////////////////////////////////////////////////////////
const double percent,
AlignedPointTVector& v)
{
- std::uint64_t samplesize = static_cast<std::uint64_t> (percent * static_cast<double> (count));
+ auto samplesize = static_cast<std::uint64_t> (percent * static_cast<double> (count));
std::lock_guard<std::mutex> lock (rng_mutex_);
////////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename ContainerT>
- OutofcoreBreadthFirstIterator<PointT, ContainerT>::~OutofcoreBreadthFirstIterator ()
- {
- }
+ OutofcoreBreadthFirstIterator<PointT, ContainerT>::~OutofcoreBreadthFirstIterator () = default;
////////////////////////////////////////////////////////////////////////////////
if (!skip_child_voxels_ && node->getDepth () < this->max_depth_ && node->getNodeType () == pcl::octree::BRANCH_NODE)
{
// Get the branch node
- BranchNode* branch = static_cast<BranchNode*> (node);
+ auto* branch = static_cast<BranchNode*> (node);
OctreeDiskNode* child = nullptr;
// Iterate over the branches children
////////////////////////////////////////////////////////////////////////////////
template<typename PointT, typename ContainerT>
- OutofcoreDepthFirstIterator<PointT, ContainerT>::~OutofcoreDepthFirstIterator ()
- {
- }
+ OutofcoreDepthFirstIterator<PointT, ContainerT>::~OutofcoreDepthFirstIterator () = default;
////////////////////////////////////////////////////////////////////////////////
if (this->currentNode_->getNodeType () == pcl::octree::BRANCH_NODE)
{
- BranchNode* currentBranch = static_cast<BranchNode*> (this->currentNode_);
+ auto* currentBranch = static_cast<BranchNode*> (this->currentNode_);
if (currentChildIdx_ < 8)
{
#pragma once
-#include <pcl/outofcore/boost.h>
+#include <boost/filesystem.hpp>
#include <vector>
#include <ostream>
public:
/** \brief Empty constructor */
- OutofcoreAbstractMetadata ()
- {
- }
+ OutofcoreAbstractMetadata () = default;
virtual
- ~OutofcoreAbstractMetadata ()
- {}
+ ~OutofcoreAbstractMetadata () = default;
/** \brief Write the metadata in the on-disk format, e.g. JSON. */
virtual void
#pragma once
+#include <boost/filesystem.hpp>
+
#include <mutex>
#include <vector>
-#include <pcl/outofcore/boost.h>
-
namespace pcl
{
namespace outofcore
OutofcoreAbstractNodeContainer (const boost::filesystem::path&) {}
virtual
- ~OutofcoreAbstractNodeContainer () {}
+ ~OutofcoreAbstractNodeContainer () = default;
virtual void
insertRange (const PointT* start, const std::uint64_t count)=0;
#pragma once
-#include <pcl/outofcore/boost.h>
#include <pcl/common/io.h>
//outofcore classes
/** \brief Write a python script using the vpython module containing all
* the bounding boxes */
void
- writeVPythonVisual (const boost::filesystem::path filename);
+ writeVPythonVisual (const boost::filesystem::path& filename);
OutofcoreNodeType*
getBranchChildPtr (const BranchNode& branch_arg, unsigned char childIdx_arg) const;
#include <pcl/common/io.h>
#include <pcl/PCLPointCloud2.h>
-#include <pcl/outofcore/boost.h>
#include <pcl/outofcore/octree_base.h>
#include <pcl/outofcore/octree_disk_container.h>
#include <pcl/outofcore/outofcore_node_data.h>
/** \brief Will recursively delete all children calling recFreeChildrein */
- ~OutofcoreOctreeBaseNode ();
+ ~OutofcoreOctreeBaseNode () override;
//query
/** \brief gets the minimum and maximum corner of the bounding box represented by this node
#include <boost/uuid/random_generator.hpp>
#include <pcl/common/utils.h> // pcl::utils::ignore
-#include <pcl/outofcore/boost.h>
#include <pcl/outofcore/octree_abstract_node_container.h>
#include <pcl/io/pcd_io.h>
#include <pcl/PCLPointCloud2.h>
OutofcoreOctreeDiskContainer (const boost::filesystem::path &dir);
/** \brief flushes write buffer, then frees memory */
- ~OutofcoreOctreeDiskContainer ();
+ ~OutofcoreOctreeDiskContainer () override;
/** \brief provides random access to points based on a linear index
*/
FILE* fxyz = fopen (path.string ().c_str (), "we");
FILE* f = fopen (disk_storage_filename_.c_str (), "rbe");
- assert (f != NULL);
+ assert (f != nullptr);
std::uint64_t num = size ();
PointT p;
#include <mutex>
#include <random>
-#include <pcl/outofcore/boost.h>
#include <pcl/outofcore/octree_abstract_node_container.h>
namespace pcl
#include <pcl/memory.h>
#include <pcl/pcl_macros.h>
-#include <pcl/outofcore/boost.h>
#include <pcl/outofcore/cJSON.h>
#include <pcl/outofcore/metadata.h>
*/
OutofcoreOctreeBaseMetadata (const boost::filesystem::path& path_arg);
/** \brief Default destructor*/
- ~OutofcoreOctreeBaseMetadata ();
+ ~OutofcoreOctreeBaseMetadata () override;
/** \brief Copy constructor */
OutofcoreOctreeBaseMetadata (const OutofcoreOctreeBaseMetadata& orig);
virtual void
setCoordinateSystem (const std::string& coordinate_system);
/** \brief Get metadata information about the coordinate system */
- virtual std::string
+ virtual const std::string&
getCoordinateSystem () const;
/** \brief Set the depth of the tree corresponding to JSON "lod:number". This should always be equal to LOD_num_points_.size()-1 */
OutofcoreBreadthFirstIterator (OctreeDisk& octree_arg);
- ~OutofcoreBreadthFirstIterator ();
+ ~OutofcoreBreadthFirstIterator () override;
OutofcoreBreadthFirstIterator&
operator++ ();
OutofcoreDepthFirstIterator (OctreeDisk& octree_arg);
- ~OutofcoreDepthFirstIterator ();
+ ~OutofcoreDepthFirstIterator () override;
OutofcoreDepthFirstIterator&
operator++ ();
* \author Stephen Fox (foxstephend@gmail.com)
*/
template<typename PointT, typename ContainerT>
- class OutofcoreIteratorBase : public std::iterator<std::forward_iterator_tag, /*iterator type*/
- const OutofcoreOctreeBaseNode<ContainerT, PointT>,
- void, /*no defined distance between iterator*/
- const OutofcoreOctreeBaseNode<ContainerT, PointT>*,/*Pointer type*/
- const OutofcoreOctreeBaseNode<ContainerT, PointT>&>/*Reference type*/
+ class OutofcoreIteratorBase
{
public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = const OutofcoreOctreeBaseNode<ContainerT, PointT>;
+ using difference_type = void;
+ using pointer = const OutofcoreOctreeBaseNode<ContainerT, PointT>*;
+ using reference = const OutofcoreOctreeBaseNode<ContainerT, PointT>&;
+
using OctreeDisk = pcl::outofcore::OutofcoreOctreeBase<ContainerT, PointT>;
using OctreeDiskNode = pcl::outofcore::OutofcoreOctreeBaseNode<ContainerT, PointT>;
}
virtual
- ~OutofcoreIteratorBase ()
- {
- }
+ ~OutofcoreIteratorBase () = default;
OutofcoreIteratorBase (const OutofcoreIteratorBase& src)
: octree_ (src.octree_), currentNode_ (src.currentNode_)
#include <pcl/memory.h>
#include <pcl/pcl_macros.h>
-#include <pcl/outofcore/boost.h>
#include <pcl/outofcore/cJSON.h>
#include <pcl/common/eigen.h>
+#include <boost/filesystem.hpp>
+
#include <ostream>
namespace pcl
// Operators
// -----------------------------------------------------------------------------
Axes (std::string name, float size = 1.0) :
- Object (name)
+ Object (name), axes_ (vtkSmartPointer<vtkAxes>::New ())
{
- axes_ = vtkSmartPointer<vtkAxes>::New ();
axes_->SetOrigin (0, 0, 0);
axes_->SetScaleFactor (size);
axes_->Update ();
addActor (axes_actor_);
}
- //~Axes () { }
// Accessors
// -----------------------------------------------------------------------------
public:
- ~Geometry () { }
+ ~Geometry () override = default;
public:
// Operators
// -----------------------------------------------------------------------------
Grid (std::string name, int size = 10, double spacing = 1.0);
- ~Grid () { }
+ ~Grid () override = default;
// Accessors
// -----------------------------------------------------------------------------
Object (std::string name);
virtual
- ~Object () { }
+ ~Object () = default;
// Accessors
static Scene *instance_;
+
+public:
+
Scene ();
Scene (const Scene& op) = delete;
Scene&
operator= (const Scene& op) = delete;
-public:
-
// Singleton
static Scene*
instance ()
getCamera (vtkCamera *camera);
Camera*
- getCamera (std::string name);
+ getCamera (const std::string& name);
// Accessors - Objects
// -----------------------------------------------------------------------------
addObject (Object *object);
Object*
- getObjectByName (std::string name);
+ getObjectByName (const std::string& name);
std::vector<Object*>
getObjects ();
#include <pcl/outofcore/cJSON.h>
#include <pcl/pcl_macros.h>
-#include <cstring>
+#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
-#include <cfloat>
-#include <climits>
+#include <cstring>
#include <cctype>
+#include <limits>
static const char *ep;
{
return (nullptr);
}
-
- memcpy(copy,str,len);
+
+ std::copy(str, str + len, copy);
return (copy);
}
static cJSON *cJSON_New_Item()
{
cJSON* node = static_cast<cJSON*> (cJSON_malloc(sizeof(cJSON)));
- if (node) memset(node,0,sizeof(cJSON));
+ if (node) {
+ *node = cJSON{};
+ }
return node;
}
{
char *str;
double d=item->valuedouble;
- if (std::abs((static_cast<double>(item->valueint)-d))<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
+ if (std::abs((static_cast<double>(item->valueint)-d))<=std::numeric_limits<double>::epsilon() &&
+ d <= std::numeric_limits<int>::max() && d >= std::numeric_limits<int>::min())
{
str=static_cast<char*>(cJSON_malloc(21)); /* 2^64+1 can be represented in 21 chars. */
if (str) sprintf(str,"%d",item->valueint);
str=static_cast<char*>(cJSON_malloc(64)); /* This is a nice tradeoff. */
if (str)
{
- if (std::abs(std::floor(d)-d)<=DBL_EPSILON) sprintf(str,"%.0f",d);
+ if (std::abs(std::floor(d)-d)<=std::numeric_limits<double>::epsilon()) sprintf(str,"%.0f",d);
else sprintf(str,"%.16g",d);
}
}
/* Allocate an array to hold the values for each */
entries=static_cast<char**>(cJSON_malloc(numentries*sizeof(char*)));
if (!entries) return nullptr;
- memset(entries,0,numentries*sizeof(char*));
+ std::fill_n(entries, numentries, nullptr);
/* Retrieve all the results: */
child=item->child;
while (child && !fail)
if (!entries) return nullptr;
char **names=static_cast<char**>(cJSON_malloc(numentries*sizeof(char*)));
if (!names) {cJSON_free(entries);return nullptr;}
- memset(entries,0,sizeof(char*)*numentries);
- memset(names,0,sizeof(char*)*numentries);
+ std::fill_n(entries, numentries, nullptr);
+ std::fill_n(names, numentries, nullptr);
/* Collect all the results into our arrays: */
child=item->child;depth++;if (fmt) len+=depth;
/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
-static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return nullptr;memcpy(ref,item,sizeof(cJSON));ref->string=nullptr;ref->type|=cJSON_IsReference;ref->next=ref->prev=nullptr;return ref;}
+static cJSON*
+create_reference(cJSON* item)
+{
+ cJSON* ref = cJSON_New_Item();
+ if (!ref) {
+ return nullptr;
+ }
+ *ref = *item;
+ ref->string = nullptr;
+ ref->type |= cJSON_IsReference;
+ ref->next = ref->prev = nullptr;
+ return ref;
+}
/* Add item to array/object. */
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
////////////////////////////////////////////////////////////////////////////////
- std::string
+ const std::string&
OutofcoreOctreeBaseMetadata::getCoordinateSystem () const
{
return (this->coordinate_system_);
////////////////////////////////////////////////////////////////////////////////
- OutofcoreOctreeNodeMetadata::~OutofcoreOctreeNodeMetadata ()
- {
- }
+ OutofcoreOctreeNodeMetadata::~OutofcoreOctreeNodeMetadata () = default;
////////////////////////////////////////////////////////////////////////////////
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkCameraActor.h>
-#include <vtkHull.h>
#include <vtkPlanes.h>
-#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkSmartPointer.h>
#include <pcl/outofcore/visualization/grid.h>
// VTK
-#include <vtkVersion.h>
#include <vtkActor.h>
#include <vtkRectilinearGrid.h>
#include <vtkDoubleArray.h>
// Operators
// -----------------------------------------------------------------------------
Grid::Grid (std::string name, int size/*=10*/, double spacing/*=1.0*/) :
- Object (name)
+ Object (name), grid_ (vtkSmartPointer<vtkRectilinearGrid>::New ()), grid_actor_ (vtkSmartPointer<vtkActor>::New ())
{
- grid_ = vtkSmartPointer<vtkRectilinearGrid>::New ();
- grid_actor_ = vtkSmartPointer<vtkActor>::New ();
-
vtkSmartPointer<vtkDataSetMapper> grid_mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
vtkSmartPointer<vtkDoubleArray> xz_array = vtkSmartPointer<vtkDoubleArray>::New ();
// Operators
// -----------------------------------------------------------------------------
-Object::Object (std::string name)
+Object::Object (std::string name): actors_(vtkSmartPointer<vtkActorCollection>::New ()), name_(name)
{
- name_ = name;
-
- actors_ = vtkSmartPointer<vtkActorCollection>::New ();
}
// Accessors
// PCL - visualziation
#include <pcl/visualization/common/common.h>
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
-#include <pcl/visualization/vtk/vtkVertexBufferObjectMapper.h>
-#endif
-
// VTK
#include <vtkVersion.h>
#include <vtkActor.h>
vtkSmartPointer<vtkActor> cloud_actor = vtkSmartPointer<vtkActor>::New ();
CloudDataCacheItem *cloud_data_cache_item = &cloud_data_cache.get(pcd_file);
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- vtkSmartPointer<vtkVertexBufferObjectMapper> mapper = vtkSmartPointer<vtkVertexBufferObjectMapper>::New ();
- mapper->SetInput (cloud_data_cache_item->item);
-#else
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
// Usually we choose between SetInput and SetInputData based on VTK version. But OpenGL ≥ 2 automatically
// means VTK version is ≥ 6.3
mapper->SetInputData (cloud_data_cache_item->item);
-#endif
cloud_actor->SetMapper (mapper);
cloud_actor->GetProperty ()->SetColor (0.0, 0.0, 1.0);
Scene* Scene::instance_ = nullptr;
-Scene::Scene ()
-{
-
-}
+Scene::Scene () = default;
// Accessors - Cameras
// -----------------------------------------------------------------------------
}
Camera*
-Scene::getCamera (std::string name)
+Scene::getCamera (const std::string& name)
{
for (const auto &camera : cameras_)
if (camera->getName () == name)
}
Object*
-Scene::getObjectByName (std::string name)
+Scene::getObjectByName (const std::string& name)
{
for (const auto &object : objects_)
if (object->getName () == name)
Viewport::viewportModifiedCallback (vtkObject* vtkNotUsed (caller), unsigned long int vtkNotUsed (eventId),
void* clientData, void* vtkNotUsed (callData))
{
- Viewport *viewport = reinterpret_cast<Viewport*> (clientData);
+ auto *viewport = reinterpret_cast<Viewport*> (clientData);
viewport->viewportModified ();
}
Viewport::viewportActorUpdateCallback (vtkObject* /*caller*/, unsigned long int vtkNotUsed (eventId), void* clientData,
void* vtkNotUsed (callData))
{
- Viewport *viewport = reinterpret_cast<Viewport*> (clientData);
+ auto *viewport = reinterpret_cast<Viewport*> (clientData);
viewport->viewportActorUpdate ();
}
Viewport::viewportHudUpdateCallback (vtkObject* vtkNotUsed (caller), unsigned long int vtkNotUsed (eventId),
void* clientData, void* vtkNotUsed (callData))
{
- Viewport *viewport = reinterpret_cast<Viewport*> (clientData);
+ auto *viewport = reinterpret_cast<Viewport*> (clientData);
viewport->viewportHudUpdate ();
}
* \author Stephen Fox
*/
+#include <limits>
+
#include <pcl/common/time.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
console::setVerbosityLevel (console::L_DEBUG);
// Defaults
- int depth = INT_MAX;
+ int depth = std::numeric_limits<int>::max();
bool breadth_first = find_switch (argc, argv, "-breadth");
bool bounding_box = find_switch (argc, argv, "-bounding_box");
bool pcd = find_switch (argc, argv, "-pcd");
// PCL - visualziation
//#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/common/common.h>
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
-#include <pcl/visualization/vtk/vtkVertexBufferObjectMapper.h>
-#endif
//#include "vtkVBOPolyDataMapper.h"
#include <vtkParallelCoordinatesInteractorStyle.h>
// Boost
-#include <boost/date_time.hpp>
#include <boost/filesystem.hpp>
// Globals
std::cout << "Key Pressed: " << key << std::endl;
Scene *scene = Scene::instance ();
- OutofcoreCloud *cloud = static_cast<OutofcoreCloud*> (scene->getObjectByName ("my_octree"));
+ OutofcoreCloud *cloud = dynamic_cast<OutofcoreCloud*> (scene->getObjectByName ("my_octree"));
if (key == "Up" || key == "Down")
{
Scene *scene = Scene::instance ();
// Clouds
- OutofcoreCloud *cloud = new OutofcoreCloud ("my_octree", tree_root);
+ auto *cloud = new OutofcoreCloud ("my_octree", tree_root);
cloud->setDisplayDepth (depth);
cloud->setDisplayVoxels (display_octree);
OutofcoreCloud::cloud_data_cache.setCapacity(gpu_cache_size*1024);
set(SUBSYS_NAME people)
set(SUBSYS_DESC "Point cloud people library")
-set(SUBSYS_DEPS common kdtree search features sample_consensus filters io visualization geometry segmentation octree)
+set(SUBSYS_DEPS common kdtree search sample_consensus filters io visualization geometry segmentation octree)
if(NOT VTK_FOUND)
set(DEFAULT FALSE)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
if(WITH_OPENNI)
PCL_ADD_EXECUTABLE(pcl_ground_based_rgbd_people_detector COMPONENT ${SUBSYS_NAME} SOURCES apps/main_ground_based_people_detection.cpp BUNDLE)
- target_link_libraries(pcl_ground_based_rgbd_people_detector pcl_common pcl_kdtree pcl_search pcl_features pcl_sample_consensus pcl_filters pcl_io pcl_visualization pcl_segmentation pcl_people)
+ target_link_libraries(pcl_ground_based_rgbd_people_detector pcl_common pcl_kdtree pcl_search pcl_sample_consensus pcl_filters pcl_io pcl_visualization pcl_segmentation pcl_people)
endif()
void
pp_callback (const pcl::visualization::PointPickingEvent& event, void* args)
{
- struct callback_args* data = (struct callback_args *)args;
+ auto* data = reinterpret_cast<struct callback_args *>(args);
if (event.getPointIndex () == -1)
return;
PointT current_point;
/**
* \brief Platform independent aligned memory allocation (see also alFree).
- */
- void*
+ */
+ void*
alMalloc ( std::size_t size, int alignment ) const;
/**
* \brief Platform independent aligned memory de-allocation (see also alMalloc).
*/
- void
+ void
alFree (void* aligned) const;
protected:
{
swapDimensions(rgb_image_);
}
- for(typename std::vector<pcl::people::PersonCluster<PointT> >::iterator it = clusters.begin(); it != clusters.end(); ++it)
+ for(auto it = clusters.begin(); it != clusters.end(); ++it)
{
//Evaluate confidence for the current PersonCluster:
Eigen::Vector3f centroid = intrinsics_matrix_transformed_ * (it->getTCenter());
}
template <typename PointT>
-pcl::people::GroundBasedPeopleDetectionApp<PointT>::~GroundBasedPeopleDetectionApp ()
-{
- // TODO Auto-generated destructor stub
-}
+pcl::people::GroundBasedPeopleDetectionApp<PointT>::~GroundBasedPeopleDetectionApp () = default;
#endif /* PCL_PEOPLE_GROUND_BASED_PEOPLE_DETECTION_APP_HPP_ */
height_map_obj.setInputCloud(cloud_);
height_map_obj.setSensorPortraitOrientation(vertical_);
height_map_obj.setMinimumDistanceBetweenMaxima(heads_minimum_distance_);
- for(typename std::vector<pcl::people::PersonCluster<PointT> >::iterator it = clusters.begin(); it != clusters.end(); ++it) // for every cluster
+ for(auto it = clusters.begin(); it != clusters.end(); ++it) // for every cluster
{
float height = it->getHeight();
int number_of_points = it->getNumberPoints();
}
template <typename PointT>
-pcl::people::HeadBasedSubclustering<PointT>::~HeadBasedSubclustering ()
-{
- // TODO Auto-generated destructor stub
-}
+pcl::people::HeadBasedSubclustering<PointT>::~HeadBasedSubclustering () = default;
#endif /* PCL_PEOPLE_HEAD_BASED_SUBCLUSTER_HPP_ */
}
template <typename PointT>
-pcl::people::HeightMap2D<PointT>::~HeightMap2D ()
-{
- // TODO Auto-generated destructor stub
-}
+pcl::people::HeightMap2D<PointT>::~HeightMap2D () = default;
#endif /* PCL_PEOPLE_HEIGHT_MAP_2D_HPP_ */
#define PCL_PEOPLE_PERSON_CLASSIFIER_HPP_
template <typename PointT>
-pcl::people::PersonClassifier<PointT>::PersonClassifier () {}
+pcl::people::PersonClassifier<PointT>::PersonClassifier () = default;
template <typename PointT>
-pcl::people::PersonClassifier<PointT>::~PersonClassifier () {}
+pcl::people::PersonClassifier<PointT>::~PersonClassifier () = default;
template <typename PointT> bool
-pcl::people::PersonClassifier<PointT>::loadSVMFromFile (std::string svm_filename)
+pcl::people::PersonClassifier<PointT>::loadSVMFromFile (const std::string& svm_filename)
{
std::string line;
std::ifstream SVM_file;
// Calculate HOG descriptor:
pcl::people::HOG hog;
- float *descriptor = (float*) calloc(SVM_weights_.size(), sizeof(float));
+ float *descriptor = new float[SVM_weights_.size()];
+ std::fill_n(descriptor, SVM_weights_.size(), 0.0f);
hog.compute(sample_float, descriptor);
// Calculate confidence value by dot product:
}
template <typename PointT>
-pcl::people::PersonCluster<PointT>::~PersonCluster ()
-{
- // Auto-generated destructor stub
-}
+pcl::people::PersonCluster<PointT>::~PersonCluster () = default;
#endif /* PCL_PEOPLE_PERSON_CLUSTER_HPP_ */
* \return true if SVM has been correctly set, false otherwise.
*/
bool
- loadSVMFromFile (std::string svm_filename);
+ loadSVMFromFile (const std::string& svm_filename);
/**
* \brief Set trained SVM for person confidence estimation.
}
/** \brief Destructor. */
-pcl::people::HOG::~HOG () {}
+pcl::people::HOG::~HOG () = default;
void
pcl::people::HOG::gradMag( float *I, int h, int w, int d, float *M, float *O ) const
// allocate memory for storing one column of output (padded so h4%4==0)
h4=(h%4==0) ? h : h-(h%4)+4; s=d*h4*sizeof(float);
- M2=(float*) alMalloc(s,16);
- _M2=(__m128*) M2;
- Gx=(float*) alMalloc(s,16); _Gx=(__m128*) Gx;
- Gy=(float*) alMalloc(s,16); _Gy=(__m128*) Gy;
+ M2=reinterpret_cast<float*>(alMalloc(s,16));
+ _M2=reinterpret_cast<__m128*>(M2);
+ Gx=reinterpret_cast<float*>(alMalloc(s,16)); _Gx=reinterpret_cast<__m128*>(Gx);
+ Gy=reinterpret_cast<float*>(alMalloc(s,16)); _Gy=reinterpret_cast<__m128*>(Gy);
// compute gradient magnitude and orientation for each column
for( x=0; x<w; x++ ) {
_Gx[y] = pcl::sse_xor( _Gx[y], pcl::sse_and(_Gy[y], pcl::sse_set(-0.f)) );
};
- memcpy( M+x*h, M2, h*sizeof(float) );
+ std::copy(M2, M2 + h, M + x * h);
// compute and store gradient orientation (O) via table lookup
if(O!=nullptr) for( y=0; y<h; y++ ) O[x*h+y] = acost[(int)Gx[y]];
}
// allocate memory for storing one column of output (padded so h4%4==0)
h4=(h%4==0) ? h : h-(h%4)+4; s=d*h4*sizeof(float);
- M2=(float*) alMalloc(s,16);
- Gx=(float*) alMalloc(s,16);
- Gy=(float*) alMalloc(s,16);
+ M2=reinterpret_cast<float*>(alMalloc(s,16));
+ Gx=reinterpret_cast<float*>(alMalloc(s,16));
+ Gy=reinterpret_cast<float*>(alMalloc(s,16));
float m;
// compute gradient magnitude and orientation for each column
Gx[y] = -Gx[y];
}
- memcpy( M+x*h, M2, h*sizeof(float) );
+ std::copy(M2, M2 + h, M + x * h);
// compute and store gradient orientation (O) via table lookup
if(O!=0) for( y=0; y<h; y++ ) O[x*h+y] = acost[(int)Gx[y]];
}
const int hb=h/bin_size, wb=w/bin_size, h0=hb*bin_size, w0=wb*bin_size, nb=wb*hb;
const float s=(float)bin_size, sInv=1/s, sInv2=1/s/s;
float *H0, *H1, *M0, *M1; int *O0, *O1;
- O0=(int*)alMalloc(h*sizeof(int),16); M0=(float*) alMalloc(h*sizeof(float),16);
- O1=(int*)alMalloc(h*sizeof(int),16); M1=(float*) alMalloc(h*sizeof(float),16);
+ O0=reinterpret_cast<int*>(alMalloc(h*sizeof(int),16)); M0=reinterpret_cast<float*>(alMalloc(h*sizeof(float),16));
+ O1=reinterpret_cast<int*>(alMalloc(h*sizeof(int),16)); M1=reinterpret_cast<float*>(alMalloc(h*sizeof(float),16));
// main loop
float xb = 0;
float *N, *N1, *H1; int o, x, y, hb=h/bin_size, wb=w/bin_size, nb=wb*hb;
float eps = 1e-4f/4/bin_size/bin_size/bin_size/bin_size; // precise backward equality
// compute 2x2 block normalization values
- N = (float*) calloc(nb,sizeof(float));
+ N = reinterpret_cast<float*>(calloc(nb,sizeof(float)));
for( o=0; o<n_orients; o++ ) for( x=0; x<nb; x++ ) N[x]+=H[x+o*nb]*H[x+o*nb];
for( x=0; x<wb-1; x++ ) for( y=0; y<hb-1; y++ ) {
N1=N+x*hb+y; *N1=1/float(std::sqrt( N1[0] + N1[1] + N1[hb] + N1[hb+1] +eps )); }
if(md) for( y=1; y<hb-1; y++ ) { U(0,0); U(1,1); U(2,hb); U(3,hb+1); }
if(rt) for( y=1; y<hb-1; y++ ) { U(2,hb); U(3,hb+1); }
y=hb-1; if(!rt) U(1,1); if(!lf) U(3,hb+1);
- } free(N);
+ }
+ free(N);
}
void
for( y = 0; y < h; y++ )
*Gx++ = (*In++ - *Ip++) * r;
} else {
- _G = (__m128*) Gx;
- __m128 *_Ip = (__m128*) Ip;
- __m128 *_In = (__m128*) In;
+ _G = reinterpret_cast<__m128*>(Gx);
+ __m128 *_Ip = reinterpret_cast<__m128*>(Ip);
+ __m128 *_In = reinterpret_cast<__m128*>(In);
_r = pcl::sse_set(r);
for(y = 0; y < h; y += 4)
*_G++ = pcl::sse_mul(pcl::sse_sub(*_In++,*_Ip++), _r);
Ip = I;
In = Ip + 1;
// GRADY(1); Ip--; for(y = 1; y < h-1; y++) GRADY(.5f); In--; GRADY(1);
- y1 = ((~((std::size_t) Gy) + 1) & 15)/4;
+ y1 = ((~(reinterpret_cast<std::size_t>(Gy)) + 1) & 15)/4;
if(y1 == 0) y1 = 4;
if(y1 > h-1) y1 = h-1;
GRADY(1);
Ip--;
for(y = 1; y < y1; y++) GRADY(.5f);
_r = pcl::sse_set(.5f);
- _G = (__m128*) Gy;
+ _G = reinterpret_cast<__m128*>(Gy);
for(; y+4 < h-1; y += 4, Ip += 4, In += 4, Gy += 4)
*_G++ = pcl::sse_mul(pcl::sse_sub(pcl::sse_ldu(*In),pcl::sse_ldu(*Ip)), _r);
for(; y < h-1; y++) GRADY(.5f);
const __m128i _nb = pcl::sse_set(nb);
// perform the majority of the work with sse
- _O0=(__m128i*) O0;
- _O1=(__m128i*) O1;
- _M0=(__m128*) M0;
- _M1=(__m128*) M1;
+ _O0=reinterpret_cast<__m128i*>(O0);
+ _O1=reinterpret_cast<__m128i*>(O1);
+ _M0=reinterpret_cast<__m128*>(M0);
+ _M1=reinterpret_cast<__m128*>(M1);
for( ; i <= n-4; i += 4 ) {
_o = pcl::sse_mul(pcl::sse_ldu(O[i]),_oMult);
_o0f = pcl::sse_cvt(pcl::sse_cvt(_o));
{
const std::size_t pSize = sizeof(void*), a = alignment-1;
void *raw = malloc(size + a + pSize);
- void *aligned = (void*) (((std::size_t) raw + pSize + a) & ~a);
- *(void**) ((std::size_t) aligned-pSize) = raw;
+ void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(raw) + pSize + a) & ~a);
+ *reinterpret_cast<void**>(reinterpret_cast<std::size_t>(aligned)-pSize) = raw;
return aligned;
}
inline void
pcl::people::HOG::alFree (void* aligned) const
{
- void* raw = *(void**)((char*)aligned-sizeof(void*));
+ void* raw = *reinterpret_cast<void**>(reinterpret_cast<char*>(aligned)-sizeof(void*));
free(raw);
}
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
class solution_recorder {
public:
/// @brief Default ctor.
- solution_recorder() {}
+ solution_recorder() = default;
/// @brief Unimplemented copy ctor.
solution_recorder(const solution_recorder&);
/// @brief Unimplemented assignment operator.
abstract_search& operator==(const abstract_search<move_manager_type>&);
/// @brief Virtual destructor.
- virtual
- ~abstract_search()
- { };
+
+ ~abstract_search() override = default;
enum {
/// @brief We just made a move.
/// @brief Accept is called at the end of each iteration for an
/// opportunity to record the best solution found during the
/// search.
- bool accept(const feasible_solution& sol);
+ bool accept(const feasible_solution& sol) override;
/// @brief Returns the best solution found since the beginning.
const evaluable_solution& best_seen() const
{ return best_ever_m; }
/// @brief Best cost seen.
- gol_type best_cost() const
+ gol_type best_cost() const override
{ return best_ever_m.cost_function(); }
protected:
/// @brief Records the best solution
/// @brief Virtual destructor
virtual
- ~search_listener()
- { }
+ ~search_listener() = default;
/// @brief This is the callback method called by searches
/// when a move, an improvement or something else happens
if(as->step() == mets::abstract_search<neighborhood_t>::MOVE_MADE)
{
os << iteration++ << "\t"
- << static_cast<const mets::evaluable_solution&>(p).cost_function()
+ << dynamic_cast<const mets::evaluable_solution&>(p).cost_function()
<< "\n";
}
}
if(as->step() == mets::abstract_search<neighborhood_t>::MOVE_MADE)
{
iteration_m++;
- double val = static_cast<const mets::evaluable_solution&>(p)
+ double val = dynamic_cast<const mets::evaluable_solution&>(p)
.cost_function();
if(val < best_m - epsilon_m)
{
}
-inline mets::solution_recorder::~solution_recorder()
-{ }
+inline mets::solution_recorder::~solution_recorder() = default;
inline bool
mets::best_ever_solution::accept(const mets::feasible_solution& sol)
{
- const evaluable_solution& s = dynamic_cast<const mets::evaluable_solution&>(sol);
+ const auto& s = dynamic_cast<const mets::evaluable_solution&>(sol);
if(s.cost_function() < best_ever_m.cost_function())
{
best_ever_m.copy_from(s);
class clonable {
public:
virtual
- ~clonable() {};
+ ~clonable() = default;
virtual clonable*
clone() const = 0;
};
class hashable {
public:
virtual
- ~hashable() {};
+ ~hashable() = default;
virtual std::size_t
hash() const = 0;
};
class copyable {
public:
virtual
- ~copyable() {};
+ ~copyable() = default;
virtual void
copy_from(const copyable&) = 0;
};
class printable {
public:
virtual
- ~printable() {}
+ ~printable() = default;
virtual void
print(std::ostream& /*os*/) const { };
};
public:
/// @brief Virtual dtor.
virtual
- ~feasible_solution()
- { }
+ ~feasible_solution() = default;
};
/// permutation_problem::copy_from in the overriding code.
///
/// @param other the problem to copy from
- void copy_from(const copyable& other);
+ void copy_from(const copyable& other) override;
/// @brief: Compute cost of the whole solution.
///
/// implementation provided returns the protected
/// mets::permutation_problem::cost_m member variable. Do not
/// override unless you know what you are doing.
- gol_type cost_function() const
+ gol_type cost_function() const override
{ return cost_m; }
/// @brief Updates the cost with the one computed by the subclass.
public:
virtual
- ~move()
- { };
+ ~move() = default;
///
/// @brief Evaluate the cost after the move.
/// (if we moved a to b we can declare tabu moving b to a).
virtual mana_move*
opposite_of() const
- { return static_cast<mana_move*>(clone()); }
+ { return dynamic_cast<mana_move*>(clone()); }
/// @brief Tell if this move equals another w.r.t. the tabu list
/// management (for mets::simple_tabu_list)
/// @brief Virtual method that applies the move on a point
gol_type
- evaluate(const mets::feasible_solution& s) const
- { const permutation_problem& sol =
- static_cast<const permutation_problem&>(s);
+ evaluate(const mets::feasible_solution& s) const override
+ { const auto& sol =
+ dynamic_cast<const permutation_problem&>(s);
return sol.cost_function() + sol.evaluate_swap(p1, p2); }
/// @brief Virtual method that applies the move on a point
void
- apply(mets::feasible_solution& s) const
- { permutation_problem& sol = static_cast<permutation_problem&>(s);
+ apply(mets::feasible_solution& s) const override
+ { auto& sol = dynamic_cast<permutation_problem&>(s);
sol.apply_swap(p1, p2); }
/// @brief Clones this move (so that the tabu list can store it)
clonable*
- clone() const
+ clone() const override
{ return new swap_elements(p1, p2); }
/// @brief An hash function used by the tabu list (the hash value is
/// used to insert the move in an hash set).
std::size_t
- hash() const
+ hash() const override
{ return (p1)<<16^(p2); }
/// @brief Comparison operator used to tell if this move is equal to
/// a move in the simple tabu list move set.
bool
- operator==(const mets::mana_move& o) const;
+ operator==(const mets::mana_move& o) const override;
/// @brief Modify this swap move.
void change(int from, int to)
/// @brief Virtual method that applies the move on a point
gol_type
- evaluate(const mets::feasible_solution& s) const;
+ evaluate(const mets::feasible_solution& s) const override;
/// @brief Virtual method that applies the move on a point
void
- apply(mets::feasible_solution& s) const;
+ apply(mets::feasible_solution& s) const override;
clonable*
- clone() const
+ clone() const override
{ return new invert_subsequence(p1, p2); }
/// @brief An hash function used by the tabu list (the hash value is
/// used to insert the move in an hash set).
std::size_t
- hash() const
+ hash() const override
{ return (p1)<<16^(p2); }
/// @brief Comparison operator used to tell if this move is equal to
/// a move in the tabu list.
bool
- operator==(const mets::mana_move& o) const;
+ operator==(const mets::mana_move& o) const override;
void change(int from, int to)
{ p1 = from; p2 = to; }
{ }
/// @brief Virtual destructor
- virtual ~move_manager()
- { }
+ virtual ~move_manager() = default;
/// @brief Selects a different set of moves at each iteration.
virtual void
unsigned int moves);
/// @brief Dtor.
- ~swap_neighborhood();
+ ~swap_neighborhood() override;
/// @brief Selects a different set of moves at each iteration.
- void refresh(mets::feasible_solution& s);
+ void refresh(mets::feasible_solution& s) override;
protected:
random_generator& rng;
mets::swap_neighborhood<random_generator>::~swap_neighborhood()
{
// delete all moves
- for(iterator ii = begin(); ii != end(); ++ii)
+ for(auto ii = begin(); ii != end(); ++ii)
delete (*ii);
}
void
mets::swap_neighborhood<random_generator>::refresh(mets::feasible_solution& s)
{
- permutation_problem& sol = dynamic_cast<permutation_problem&>(s);
- iterator ii = begin();
+ auto& sol = dynamic_cast<permutation_problem&>(s);
+ auto ii = begin();
// the first n are simple qap_moveS
for(unsigned int cnt = 0; cnt != n; ++cnt)
{
- swap_elements* m = static_cast<swap_elements*>(*ii);
+ auto* m = static_cast<swap_elements*>(*ii);
randomize_move(*m, sol.size());
++ii;
}
}
/// @brief Dtor.
- ~swap_full_neighborhood() {
- for(move_manager::iterator it = moves_m.begin();
+ ~swap_full_neighborhood() override {
+ for(auto it = moves_m.begin();
it != moves_m.end(); ++it)
delete *it;
}
/// @brief Use the same set set of moves at each iteration.
- void refresh(mets::feasible_solution& /*s*/) { }
+ void refresh(mets::feasible_solution& /*s*/) override { }
};
}
/// @brief Dtor.
- ~invert_full_neighborhood() {
- for(std::deque<move*>::iterator it = moves_m.begin();
+ ~invert_full_neighborhood() override {
+ for(auto it = moves_m.begin();
it != moves_m.end(); ++it)
delete *it;
}
/// @brief This is a static neighborhood
void
- refresh(mets::feasible_solution& /*s*/)
+ refresh(mets::feasible_solution& /*s*/) override
{ }
};
inline void
mets::permutation_problem::copy_from(const mets::copyable& other)
{
- const mets::permutation_problem& o =
+ const auto& o =
dynamic_cast<const mets::permutation_problem&>(other);
pi_m = o.pi_m;
cost_m = o.cost_m;
mets::swap_elements::operator==(const mets::mana_move& o) const
{
try {
- const mets::swap_elements& other =
+ const auto& other =
dynamic_cast<const mets::swap_elements&>(o);
return (this->p1 == other.p1 && this->p2 == other.p2);
} catch (std::bad_cast& e) {
inline void
mets::invert_subsequence::apply(mets::feasible_solution& s) const
{
- mets::permutation_problem& sol =
- static_cast<mets::permutation_problem&>(s);
+ auto& sol =
+ dynamic_cast<mets::permutation_problem&>(s);
int size = static_cast<int>(sol.size());
int top = p1 < p2 ? (p2-p1+1) : (size+p2-p1+1);
for(int ii(0); ii!=top/2; ++ii)
inline mets::gol_type
mets::invert_subsequence::evaluate(const mets::feasible_solution& s) const
{
- const mets::permutation_problem& sol =
- static_cast<const mets::permutation_problem&>(s);
+ const auto& sol =
+ dynamic_cast<const mets::permutation_problem&>(s);
int size = static_cast<int>(sol.size());
int top = p1 < p2 ? (p2-p1+1) : (size+p2-p1+1);
mets::gol_type eval = 0.0;
mets::invert_subsequence::operator==(const mets::mana_move& o) const
{
try {
- const mets::invert_subsequence& other =
+ const auto& other =
dynamic_cast<const mets::invert_subsequence&>(o);
return (this->p1 == other.p1 && this->p2 == other.p2);
} catch (std::bad_cast& e) {
public:
/// @brief Ctor.
update_observer(observed_subject* who) : who_m(who) {}
+ update_observer() = delete;
/// @brief Subscript operator to update an observer.
void
operator()(observer<observed_subject>* o) { o->update(who_m); }
private:
- update_observer();
observed_subject* who_m;
};
{
public:
virtual
- ~subject() {};
+ ~subject() = default;;
/// @brief Attach a new observer to this subject.
///
/// @param o: a new observer for this subject.
{
public:
virtual
- ~observer() {};
+ ~observer() = default;;
/// @brief This method is automatically called when this
/// observer is attached to a "notified" subject.
///
virtual void
update(observed_subject*) = 0;
protected:
- observer() {};
+ observer() = default;;
};
subject<observed_subject>::notify()
{
// upcast the object to the real observer_subject type
- observed_subject* real_subject = static_cast<observed_subject*>(this);
+ auto* real_subject = static_cast<observed_subject*>(this);
std::for_each(observers_m.begin(), observers_m.end(),
update_observer<observed_subject>(real_subject));
}
{
public:
/// @brief Constructor
- abstract_cooling_schedule()
- { }
+ abstract_cooling_schedule() = default;
/// @brief Virtual destructor
- virtual
- ~abstract_cooling_schedule()
- { }
+ virtual ~abstract_cooling_schedule() = default;
/// @brief The function that updates the SA temperature.
///
///
/// Remember that this is a minimization process.
///
- virtual void
- search();
+ void
+ search() override;
void setApplyAndEvaluate(bool b) {
apply_and_evaluate = b;
: abstract_cooling_schedule(), factor_m(alpha)
{ if(alpha >= 1) throw std::runtime_error("alpha must be < 1"); }
double
- operator()(double temp, feasible_solution& /*fs*/)
+ operator()(double temp, feasible_solution& /*fs*/) override
{ return temp*factor_m; }
protected:
double factor_m;
: abstract_cooling_schedule(), decrement_m(delta)
{ if(delta <= 0) throw std::runtime_error("delta must be > 0"); }
double
- operator()(double temp, feasible_solution& /*fs*/)
+ operator()(double temp, feasible_solution& /*fs*/) override
{ return std::max(0.0, temp-decrement_m); }
protected:
double decrement_m;
.cost_function();*/
base_t::moves_m.refresh(base_t::working_solution_m);
- for(typename move_manager_t::iterator movit = base_t::moves_m.begin();
+ for(auto movit = base_t::moves_m.begin();
movit != base_t::moves_m.end(); ++movit)
{
// apply move and record proposed cost function
///
/// @param next Optional next criteria in the chain.
explicit
- aspiration_criteria_chain(aspiration_criteria_chain *next = 0)
+ aspiration_criteria_chain(aspiration_criteria_chain *next = nullptr)
: next_m(next)
{ }
/// @brief Virtual destructor.
virtual
- ~aspiration_criteria_chain()
- { }
+ ~aspiration_criteria_chain() = default;
/// @brief A method to reset this aspiration criteria chain to its
/// original state.
/// Create an abstract tabu list with a certain tenure
explicit
tabu_list_chain(unsigned int tenure)
- : next_m(0), tenure_m(tenure)
+ : next_m(nullptr), tenure_m(tenure)
{ }
/// @brief Create an abstract tabu list with a certain tenure and
/// @brief Virtual destructor
virtual
- ~tabu_list_chain()
- { }
+ ~tabu_list_chain() = default;
///
/// @brief Make a move tabu when starting from a certain solution.
search_type& operator=(const search_type&);
virtual
- ~tabu_search() {}
+ ~tabu_search() = default;
/// @brief This method starts the tabu search process.
///
tabu_hash_m(tenure) {}
/// @brief Destructor
- ~simple_tabu_list();
+ ~simple_tabu_list() override;
/// @brief Make move a tabu.
///
/// @param sol The current working solution
/// @param mov The move to make tabu
void
- tabu(feasible_solution& sol, /* const */ move& mov);
+ tabu(feasible_solution& sol, /* const */ move& mov) override;
/// @brief True if the move is tabu for the given solution.
///
/// @return True if this move was already made during the last
/// tenure iterations
bool
- is_tabu(feasible_solution& sol, move& mov) const;
+ is_tabu(feasible_solution& sol, move& mov) const override;
protected:
using move_list_type = std::deque<move *>;
#if defined (METSLIB_TR1_BOOST)
- typedef boost::unordered_map<
- mana_move*, // Key type
- int, //insert a move and the number of times it's present in the list
- mana_move_hash,
- dereferenced_equal_to<mana_move*> > move_map_type;
+ using move_map_type = boost::unordered_map<mana_move *, int, mana_move_hash, dereferenced_equal_to<mana_move *> >;
#elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
typedef std::unordered_map<
mana_move*, // Key type
double min_improvement = 1e-6);
void
- reset();
+ reset() override;
void
- accept(feasible_solution& fs, move& mov, gol_type evaluation);
+ accept(feasible_solution& fs, move& mov, gol_type evaluation) override;
bool
- operator()(feasible_solution& fs, move& mov, gol_type evaluation) const;
+ operator()(feasible_solution& fs, move& mov, gol_type evaluation) const override;
protected:
gol_type best_m;
///
/// @param next Optional next criterium in the chain.
explicit
- termination_criteria_chain(termination_criteria_chain* next = 0)
+ termination_criteria_chain(termination_criteria_chain* next = nullptr)
: next_m(next)
{ }
/// purposely not implemented (see Effective C++)
/// @brief Virtual destructor.
virtual
- ~termination_criteria_chain()
- { }
+ ~termination_criteria_chain() = default;
/// @brief Alternate function that decides if we shoud terminate the
/// search process
iterations_m(max) {}
bool
- operator()(const feasible_solution& fs)
+ operator()(const feasible_solution& fs) override
{
if (iterations_m <= 0)
return true;
}
void
- reset()
+ reset() override
{ iterations_m = max_m; termination_criteria_chain::reset(); }
protected:
{ }
bool
- operator()(const feasible_solution& fs);
- void reset()
+ operator()(const feasible_solution& fs) override;
+ void reset() override
{ iterations_left_m = max_noimprove_m;
second_guess_m = total_iterations_m = resets_m = 0;
best_cost_m = std::numeric_limits<gol_type>::max();
{ }
bool
- operator()(const feasible_solution& fs)
+ operator()(const feasible_solution& fs) override
{
mets::gol_type current_cost =
dynamic_cast<const evaluable_solution&>(fs).cost_function();
return termination_criteria_chain::operator()(fs);
}
- void reset()
+ void reset() override
{ termination_criteria_chain::reset(); }
protected:
public:
forever() : termination_criteria_chain() {}
bool
- operator()(const feasible_solution& /*fs*/)
+ operator()(const feasible_solution& /*fs*/) override
{ return false; }
- void reset()
+ void reset() override
{ termination_criteria_chain::reset(); }
};
CorrespondenceGrouping () : scene_ () {}
/** \brief destructor. */
- ~CorrespondenceGrouping()
+ ~CorrespondenceGrouping() override
{
scene_.reset ();
model_scene_corrs_.reset ();
ColorGradientDOTModality (std::size_t bin_size);
- virtual ~ColorGradientDOTModality ();
+ virtual ~ColorGradientDOTModality () = default;
inline void
setGradientMagnitudeThreshold (const float threshold)
{
}
-//////////////////////////////////////////////////////////////////////////////////////////////
-template <typename PointInT>
-pcl::ColorGradientDOTModality<PointInT>::
-~ColorGradientDOTModality ()
-{
-}
-
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT>
void
constexpr float divisor = 180.0f / (num_gradient_bins - 1.0f);
unsigned char * peak_pointer = dominant_quantized_color_gradients_.getData ();
- memset (peak_pointer, 0, output_width*output_height);
+ std::fill_n(peak_pointer, output_width*output_height, 0);
for (std::size_t row_bin_index = 0; row_bin_index < output_height; ++row_bin_index)
{
/** \brief Constructor. */
ColorGradientModality ();
/** \brief Destructor. */
- ~ColorGradientModality ();
+ ~ColorGradientModality () override;
/** \brief Sets the threshold for the gradient magnitude which is used when quantizing the data.
* Gradients with a smaller magnitude are ignored.
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT>
pcl::ColorGradientModality<PointInT>::
-~ColorGradientModality ()
-{
-}
+~ColorGradientModality () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT> void
while (!feature_selection_finished)
{
float best_score = 0.0f;
- typename std::list<Candidate>::iterator best_iter = list1.end ();
- for (typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
+ auto best_iter = list1.end ();
+ for (auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
{
// find smallest distance
float smallest_distance = std::numeric_limits<float>::max ();
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
const float dx = static_cast<float> (iter1->x) - static_cast<float> (iter2->x);
const float dy = static_cast<float> (iter1->y) - static_cast<float> (iter2->y);
float min_min_sqr_distance = std::numeric_limits<float>::max ();
float max_min_sqr_distance = 0;
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
float min_sqr_distance = std::numeric_limits<float>::max ();
- for (typename std::list<Candidate>::iterator iter3 = list2.begin (); iter3 != list2.end (); ++iter3)
+ for (auto iter3 = list2.begin (); iter3 != list2.end (); ++iter3)
{
if (iter2 == iter3)
continue;
{
if (list1.size () <= nr_features)
{
- for (typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
+ for (auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
{
QuantizedMultiModFeature feature;
while (list2.size () != nr_features)
{
float best_score = 0.0f;
- typename std::list<Candidate>::iterator best_iter = list1.end ();
- for (typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
+ auto best_iter = list1.end ();
+ for (auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
{
// find smallest distance
float smallest_distance = std::numeric_limits<float>::max ();
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
const float dx = static_cast<float> (iter1->x) - static_cast<float> (iter2->x);
const float dy = static_cast<float> (iter1->y) - static_cast<float> (iter2->y);
if (list1.size () <= nr_features)
{
- for (typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
+ for (auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
{
QuantizedMultiModFeature feature;
while (list2.size () != nr_features)
{
const std::size_t sqr_distance = distance*distance;
- for (typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
+ for (auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
{
bool candidate_accepted = true;
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
const int dx = iter1->x - iter2->x;
const int dy = iter1->y - iter2->y;
}
}
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
QuantizedMultiModFeature feature;
list1.sort();
- for (typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
+ for (auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
{
QuantizedMultiModFeature feature;
color_gradients_.width = width;
color_gradients_.height = height;
- const float pi = tan (1.0f) * 2;
+ const float pi = std::tan (1.0f) * 2;
for (int row_index = 0; row_index < height-2; ++row_index)
{
for (int col_index = 0; col_index < width-2; ++col_index)
if (sqr_mag_r > sqr_mag_g && sqr_mag_r > sqr_mag_b)
{
GradientXY gradient;
- gradient.magnitude = sqrt (sqr_mag_r);
+ gradient.magnitude = std::sqrt (sqr_mag_r);
gradient.angle = std::atan2 (r_dy, r_dx) * 180.0f / pi;
gradient.x = static_cast<float> (col_index);
gradient.y = static_cast<float> (row_index);
else if (sqr_mag_g > sqr_mag_b)
{
GradientXY gradient;
- gradient.magnitude = sqrt (sqr_mag_g);
+ gradient.magnitude = std::sqrt (sqr_mag_g);
gradient.angle = std::atan2 (g_dy, g_dx) * 180.0f / pi;
gradient.x = static_cast<float> (col_index);
gradient.y = static_cast<float> (row_index);
else
{
GradientXY gradient;
- gradient.magnitude = sqrt (sqr_mag_b);
+ gradient.magnitude = std::sqrt (sqr_mag_b);
gradient.angle = std::atan2 (b_dy, b_dx) * 180.0f / pi;
gradient.x = static_cast<float> (col_index);
gradient.y = static_cast<float> (row_index);
ColorModality ();
- virtual ~ColorModality ();
+ virtual ~ColorModality () = default;
inline QuantizedMap &
getQuantizedMap ()
{
}
-//////////////////////////////////////////////////////////////////////////////////////////////
-template <typename PointInT>
-pcl::ColorModality<PointInT>::~ColorModality ()
-{
-}
-
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT>
void
for (std::size_t map_index = 0; map_index < 8; ++map_index)
mask_maps[map_index].resize (width, height);
- unsigned char map[255];
- memset(map, 0, 255);
+ unsigned char map[255]{};
map[0x1<<0] = 0;
map[0x1<<1] = 1;
void
serialize (std::ostream & stream) const
{
- const std::size_t num_of_features = static_cast<std::size_t> (features.size ());
+ const auto num_of_features = static_cast<std::size_t> (features.size ());
write (stream, num_of_features);
for (std::size_t feature_index = 0; feature_index < num_of_features; ++feature_index)
{
void
serialize (std::ostream & stream) const
{
- const std::size_t num_of_modalities = static_cast<std::size_t> (modalities.size ());
+ const auto num_of_modalities = static_cast<std::size_t> (modalities.size ());
write (stream, num_of_modalities);
for (std::size_t modality_index = 0; modality_index < num_of_modalities; ++modality_index)
{
/** \brief Constructor. */
DistanceMap () : data_ (0), width_ (0), height_ (0) {}
/** \brief Destructor. */
- virtual ~DistanceMap () {}
+ virtual ~DistanceMap () = default;
/** \brief Returns the width of the map. */
inline std::size_t
{
public:
- virtual ~DOTModality () {};
+ virtual ~DOTModality () = default;
//virtual QuantizedMap &
//getDominantQuantizedMap () = 0;
}
}
- inline bool readMatrixFromFile(std::string file, Eigen::Matrix4f & matrix)
+ inline bool readMatrixFromFile(const std::string& file, Eigen::Matrix4f & matrix)
{
std::ifstream in;
min_images_per_bin_ = -1;
}
- virtual ~FaceDetectorDataProvider()
- {
-
- }
-
void setPatchesPerImage(int n)
{
patches_per_image_ = n;
res_ = 0.005f;
}
- virtual ~RFFaceDetectorTrainer()
- {
-
- }
+ virtual ~RFFaceDetectorTrainer() = default;
/*
* Common parameters
}
/** \brief Destructor. */
- ~PoseClassRegressionVarianceStatsEstimator()
- {
- }
+ ~PoseClassRegressionVarianceStatsEstimator() override = default;
/** \brief Returns the number of branches the corresponding tree has. */
inline std::size_t getNumOfBranches() const override
Eigen::Vector3d & centroid) const
{
Eigen::Matrix<double, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<double, 1, 9, Eigen::RowMajor>::Zero ();
- unsigned int point_count = static_cast<unsigned int> (examples.size ());
+ auto point_count = static_cast<unsigned int> (examples.size ());
for (std::size_t i = 0; i < point_count; ++i)
{
Eigen::Vector3d & centroid) const
{
Eigen::Matrix<double, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<double, 1, 9, Eigen::RowMajor>::Zero ();
- unsigned int point_count = static_cast<unsigned int> (examples.size ());
+ auto point_count = static_cast<unsigned int> (examples.size ());
for (std::size_t i = 0; i < point_count; ++i)
{
/** \brief A hypothesis verification method proposed in
* "A Global Hypotheses Verification Method for 3D Object Recognition", A. Aldoma and F. Tombari and L. Di Stefano and Markus Vincze, ECCV 2012
* \author Aitor Aldoma
+ * \ingroup recognition
*/
template<typename ModelT, typename SceneT>
class PCL_EXPORTS GlobalHypothesesVerification: public HypothesisVerification<ModelT, SceneT>
void copy_from(const mets::copyable& o) override
{
- const SAModel& s = dynamic_cast<const SAModel&> (o);
+ const auto& s = dynamic_cast<const SAModel&> (o);
solution_ = s.solution_;
opt_ = s.opt_;
cost_ = s.cost_;
mets::gol_type apply_and_evaluate(mets::feasible_solution& cs)
{
- SAModel& model = dynamic_cast<SAModel&> (cs);
+ auto& model = dynamic_cast<SAModel&> (cs);
return model.apply_and_evaluate (index_, !model.solution_[index_]);
}
void unapply(mets::feasible_solution& s) const
{
- SAModel& model = dynamic_cast<SAModel&> (s);
+ auto& model = dynamic_cast<SAModel&> (s);
model.unapply (index_, !model.solution_[index_]);
}
};
~move_manager()
{
// delete all moves
- for (iterator ii = begin (); ii != end (); ++ii)
+ for (auto ii = begin (); ii != end (); ++ii)
delete (*ii);
}
/** \brief A hypothesis verification method proposed in
* "An Efficient RANSAC for 3D Object Recognition in Noisy and Occluded Scenes", C. Papazov and D. Burschka, ACCV 2010
* \author Aitor Aldoma, Federico Tombari
+ * \ingroup recognition
*/
template<typename ModelT, typename SceneT>
std::sort (sorted_corrs->begin (), sorted_corrs->end (), gcCorrespSorter);
model_scene_corrs_ = sorted_corrs;
+ PCL_DEBUG_STREAM("[pcl::GeometricConsistencyGrouping::clusterCorrespondences] Five best correspondences: ");
+ for(std::size_t i=0; i<std::min<std::size_t>(model_scene_corrs_->size(), 5); ++i)
+ PCL_DEBUG_STREAM("[" << (*input_)[(*model_scene_corrs_)[i].index_query] << " " << (*scene_)[(*model_scene_corrs_)[i].index_match] << " " << (*model_scene_corrs_)[i].distance << "] ");
+ PCL_DEBUG_STREAM(std::endl);
std::vector<int> consensus_set;
std::vector<bool> taken_corresps (model_scene_corrs_->size (), false);
}
}
- memcpy (depth_, depth_smooth, sizeof(float) * cx_ * cy_);
+ std::copy(depth_smooth, depth_smooth + cx_ * cy_, depth_);
delete[] depth_smooth;
}
}
pcl::features::ISMVoteList<PointT>::getColoredCloud (typename pcl::PointCloud<PointT>::Ptr cloud)
{
pcl::PointXYZRGB point;
- pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
+ pcl::PointCloud<pcl::PointXYZRGB>::Ptr colored_cloud (new pcl::PointCloud<pcl::PointXYZRGB>);
colored_cloud->height = 0;
colored_cloud->width = 1;
estimateFeatures (sampled_point_cloud, sampled_normal_cloud, feature_cloud);
//find nearest cluster
- const unsigned int n_key_points = static_cast<unsigned int> (sampled_point_cloud->size ());
+ const auto n_key_points = static_cast<unsigned int> (sampled_point_cloud->size ());
std::vector<int> min_dist_inds (n_key_points, -1);
for (unsigned int i_point = 0; i_point < n_key_points; i_point++)
{
if (min_dist_idx == -1)
continue;
- const unsigned int n_words = static_cast<unsigned int> (model->clusters_[min_dist_idx].size ());
+ const auto n_words = static_cast<unsigned int> (model->clusters_[min_dist_idx].size ());
//compute coord system transform
Eigen::Matrix3f transform = alignYCoordWithNormal ((*sampled_normal_cloud)[i_point]);
for (unsigned int i_word = 0; i_word < n_words; i_word++)
histograms.clear ();
locations.clear ();
- int n_key_points = 0;
-
if (training_clouds_.empty () || training_classes_.empty () || feature_estimator_ == nullptr)
return (false);
shiftCloud (training_clouds_[i_cloud], models_center);
shiftCloud (sampled_point_cloud, models_center);
- n_key_points += static_cast<int> (sampled_point_cloud->size ());
-
typename pcl::PointCloud<pcl::Histogram<FeatureSize> >::Ptr feature_cloud (new pcl::PointCloud<pcl::Histogram<FeatureSize> > ());
estimateFeatures (sampled_point_cloud, sampled_normal_cloud, feature_cloud);
std::vector<std::vector<float> > objects_sigmas;
objects_sigmas.resize (number_of_classes, vec);
- unsigned int number_of_objects = static_cast<unsigned int> (training_clouds_.size ());
+ auto number_of_objects = static_cast<unsigned int> (training_clouds_.size ());
for (unsigned int i_object = 0; i_object < number_of_objects; i_object++)
{
float max_distance = 0.0f;
if (curr_distance > max_distance)
max_distance = curr_distance;
}
- max_distance = static_cast<float> (sqrt (max_distance));
+ max_distance = static_cast<float> (std::sqrt (max_distance));
unsigned int i_class = training_classes_[i_object];
objects_sigmas[i_class].push_back (max_distance);
}
for (unsigned int i_class = 0; i_class < number_of_classes; i_class++)
{
float sig = 0.0f;
- unsigned int number_of_objects_in_class = static_cast<unsigned int> (objects_sigmas[i_class].size ());
+ auto number_of_objects_in_class = static_cast<unsigned int> (objects_sigmas[i_class].size ());
for (unsigned int i_object = 0; i_object < number_of_objects_in_class; i_object++)
sig += objects_sigmas[i_class][i_object];
sig /= (static_cast<float> (number_of_objects_in_class) * 10.0f);
learned_weights.resize (locations.size (), 0.0);
for (unsigned int i_cluster = 0; i_cluster < number_of_clusters_; i_cluster++)
{
- unsigned int number_of_words_in_cluster = static_cast<unsigned int> (clusters[i_cluster].size ());
+ auto number_of_words_in_cluster = static_cast<unsigned int> (clusters[i_cluster].size ());
for (unsigned int i_visual_word = 0; i_visual_word < number_of_words_in_cluster; i_visual_word++)
{
unsigned int i_index = clusters[i_cluster][i_visual_word];
float B = 0.0f;
float sign = -1.0f;
- float denom_X = static_cast<float> (sqrt (in_normal.normal_z * in_normal.normal_z + in_normal.normal_y * in_normal.normal_y));
+ float denom_X = static_cast<float> (std::sqrt (in_normal.normal_z * in_normal.normal_z + in_normal.normal_y * in_normal.normal_y));
A = in_normal.normal_y / denom_X;
B = sign * in_normal.normal_z / denom_X;
rotation_matrix_X << 1.0f, 0.0f, 0.0f,
0.0f, A, -B,
0.0f, B, A;
- float denom_Z = static_cast<float> (sqrt (in_normal.normal_x * in_normal.normal_x + in_normal.normal_y * in_normal.normal_y));
+ float denom_Z = static_cast<float> (std::sqrt (in_normal.normal_x * in_normal.normal_x + in_normal.normal_y * in_normal.normal_y));
A = in_normal.normal_y / denom_Z;
B = sign * in_normal.normal_x / denom_Z;
rotation_matrix_Z << A, -B, 0.0f,
int trials)
{
std::size_t dimension = data.cols ();
- unsigned int number_of_points = static_cast<unsigned int> (data.rows ());
+ auto number_of_points = static_cast<unsigned int> (data.rows ());
std::vector<int> centers_vec (number_of_clusters);
int* centers = ¢ers_vec[0];
std::vector<double> dist (number_of_points);
LineRGBD<PointXYZT, PointRGBT>::readLTMHeader (int fd, pcl::io::TARHeader &header)
{
// Read in the header
- int result = static_cast<int> (io::raw_read (fd, reinterpret_cast<char*> (&header.file_name[0]), 512));
+ int result = static_cast<int> (io::raw_read (fd, reinterpret_cast<char*> (&header), 512));
if (result == -1)
return (false);
if (/*std::isfinite (point.x) && std::isfinite (point.y) && */std::isfinite (point.z))
{
- const std::size_t bin_index = static_cast<std::size_t> ((point.z - min_depth) / step_size);
+ const auto bin_index = static_cast<std::size_t> ((point.z - min_depth) / step_size);
++depth_bins[bin_index];
}
}
integral_depth_bins[bin_index] = depth_bins[bin_index] + integral_depth_bins[bin_index-1];
}
- const std::size_t bb_depth_range = static_cast<std::size_t> (detection.bounding_box.depth / step_size);
+ const auto bb_depth_range = static_cast<std::size_t> (detection.bounding_box.depth / step_size);
std::size_t max_nr_points = 0;
std::size_t max_index = 0;
#include <pcl/point_types.h>
#include <pcl/point_representation.h>
#include <pcl/features/feature.h>
-#include <pcl/features/spin_image.h>
#include <pcl/kdtree/kdtree_flann.h> // for KdTreeFLANN
namespace pcl
* by Jan Knopp, Mukta Prasad, Geert Willems, Radu Timofte, and Luc Van Gool
*
* Authors: Roman Shapovalov, Alexander Velizhev, Sergey Ushakov
+ * \ingroup recognition
*/
template <int FeatureSize, typename PointT, typename NormalT = pcl::Normal>
class PCL_EXPORTS ImplicitShapeModelEstimation
}
/** \brief Destructor. */
- virtual ~EnergyMaps ()
- {
- }
+ virtual ~EnergyMaps () = default;
/** \brief Returns the width of the energy maps. */
inline std::size_t
{
//maps_[map_index] = new unsigned char[mapsSize];
map = reinterpret_cast<unsigned char*> (aligned_malloc (mapsSize));
- memset (map, 0, mapsSize);
+ std::fill_n(map, mapsSize, 0);
}
}
}
/** \brief Destructor. */
- virtual ~LinearizedMaps ()
- {
- }
+ virtual ~LinearizedMaps () = default;
/** \brief Returns the width of the linearized map. */
inline std::size_t
{
//maps_[map_index] = new unsigned char[2*mapsSize];
map = reinterpret_cast<unsigned char*> (aligned_malloc (2*mapsSize));
- memset (map, 0, 2*mapsSize);
+ std::fill_n(map, 2*mapsSize, 0);
}
}
/**
* \brief Template matching using the LINEMOD approach.
* \author Stefan Holzer, Stefan Hinterstoisser
+ * \ingroup recognition
*/
class PCL_EXPORTS LINEMOD
{
}
/** \brief Destructor */
- virtual ~LineRGBD ()
- {
- }
+ virtual ~LineRGBD () = default;
/** \brief Loads templates from a LMT (LineMod Template) file. Overrides old templates.
*
{
/** \brief Interface for a quantizable modality.
* \author Stefan Holzer
+ * \ingroup recognition
*/
class PCL_EXPORTS QuantizableModality
{
{
}
- virtual ~BoundedObject ()
- {
- }
+ virtual ~BoundedObject () = default;
/** \brief This method is for std::sort. */
inline static bool
Node (std::vector<BoundedObject*>& sorted_objects, int first_id, int last_id)
{
// Initialize the bounds of the node
- memcpy (bounds_, sorted_objects[first_id]->getBounds (), 6*sizeof (float));
+ auto firstBounds = sorted_objects[first_id]->getBounds();
+ std::copy(firstBounds, firstBounds + 6, bounds_);
// Expand the bounds of the node
for ( int i = first_id + 1 ; i <= last_id ; ++i )
+ {
aux::expandBoundingBox(bounds_, sorted_objects[i]->getBounds());
+ }
// Shall we create children?
if ( first_id != last_id )
HypothesisBase (const ModelLibrary::Model* obj_model, const float* rigid_transform)
: obj_model_ (obj_model)
{
- memcpy (rigid_transform_, rigid_transform, 12*sizeof (float));
+ std::copy(rigid_transform, rigid_transform + 12, rigid_transform_);
}
- virtual ~HypothesisBase (){}
+ virtual ~HypothesisBase () = default;
void
setModel (const ModelLibrary::Model* model)
{
}
- ~Hypothesis (){}
+ ~Hypothesis () override = default;
const Hypothesis&
operator =(const Hypothesis& src)
{
- memcpy (this->rigid_transform_, src.rigid_transform_, 12*sizeof (float));
+ std::copy(src.rigid_transform_, src.rigid_transform_ + 12, this->rigid_transform_);
this->obj_model_ = src.obj_model_;
this->match_confidence_ = src.match_confidence_;
this->explained_pixels_ = src.explained_pixels_;
return;
// Initialize
- std::vector<ORROctree::Node*>::const_iterator it = full_leaves.begin ();
+ auto it = full_leaves.begin ();
const float *p = (*it)->getData ()->getPoint ();
aux::copy3 (p, octree_center_of_mass_);
bounds_of_octree_points_[0] = bounds_of_octree_points_[1] = p[0];
}
}
- virtual ~Model ()
- {
- }
+ virtual ~Model () = default;
inline const std::string&
getObjectName () const
inline const Model*
getModel (const std::string& name) const
{
- std::map<std::string,Model*>::const_iterator it = models_.find (name);
+ auto it = models_.find (name);
if ( it != models_.end () )
return (it->second);
match_confidence_ (match_confidence),
user_data_ (user_data)
{
- memcpy(this->rigid_transform_, rigid_transform, 12*sizeof (float));
+ std::copy(rigid_transform, rigid_transform + 12, this->rigid_transform_);
}
- virtual ~Output (){}
+ virtual ~Output () = default;
public:
std::string object_name_;
{
}
- virtual ~OrientedPointPair (){}
+ virtual ~OrientedPointPair () = default;
public:
const float *p1_, *n1_, *p2_, *n2_;
class HypothesisCreator
{
public:
- HypothesisCreator (){}
- virtual ~HypothesisCreator (){}
+ HypothesisCreator () = default;
+ virtual ~HypothesisCreator () = default;
Hypothesis* create (const SimpleOctree<Hypothesis, HypothesisCreator, float>::Node* ) const { return new Hypothesis ();}
};
state_(UNDEF)
{}
- virtual ~Node (){}
+ virtual ~Node () = default;
inline const std::set<Node*>&
getNeighbors () const
};
public:
- ORRGraph (){}
+ ORRGraph () = default;
virtual ~ORRGraph (){ this->clear ();}
inline void
clear ()
{
- for ( typename std::vector<Node*>::iterator nit = nodes_.begin () ; nit != nodes_.end () ; ++nit )
+ for ( auto nit = nodes_.begin () ; nit != nodes_.end () ; ++nit )
delete *nit;
nodes_.clear ();
if ( !n )
return;
- for ( typename std::vector<Node*>::iterator nit = nodes_.begin () ; nit != nodes_.end () ; ++nit )
+ for ( auto nit = nodes_.begin () ; nit != nodes_.end () ; ++nit )
delete *nit;
nodes_.resize (static_cast<std::size_t> (n));
int i = 0;
// Set all nodes to undefined
- for ( typename std::vector<Node*>::iterator it = nodes_.begin () ; it != nodes_.end () ; ++it )
+ for ( auto it = nodes_.begin () ; it != nodes_.end () ; ++it )
{
sorted_nodes[i++] = *it;
(*it)->state_ = Node::UNDEF;
std::sort (sorted_nodes.begin (), sorted_nodes.end (), Node::compare);
// Now run through the array and start switching nodes on and off
- for ( typename std::vector<Node*>::iterator it = sorted_nodes.begin () ; it != sorted_nodes.end () ; ++it )
+ for ( auto it = sorted_nodes.begin () ; it != sorted_nodes.end () ; ++it )
{
// Ignore graph nodes which are already OFF
if ( (*it)->state_ == Node::OFF )
(*it)->state_ = Node::ON;
// Set all its neighbors to OFF
- for ( typename std::set<Node*>::iterator neigh = (*it)->neighbors_.begin () ; neigh != (*it)->neighbors_.end () ; ++neigh )
+ for ( auto neigh = (*it)->neighbors_.begin () ; neigh != (*it)->neighbors_.end () ; ++neigh )
{
(*neigh)->state_ = Node::OFF;
off_nodes.push_back (*neigh);
n_[0] = n_[1] = n_[2] = p_[0] = p_[1] = p_[2] = 0.0f;
}
- virtual~ Data (){}
+ virtual~ Data () = default;
inline void
addToPoint (float x, float y, float z)
inline void
getBounds(float b[6]) const
{
- memcpy (b, bounds_, 6*sizeof (float));
+ std::copy(bounds_, bounds_ + 6, b);
}
inline Node*
if ( !node->getData () )
{
- Node::Data* data = new Node::Data (
+ auto* data = new Node::Data (
static_cast<int> ((node->getCenter ()[0] - bounds_[0])/voxel_size_),
static_cast<int> ((node->getCenter ()[1] - bounds_[2])/voxel_size_),
static_cast<int> ((node->getCenter ()[2] - bounds_[4])/voxel_size_),
inline void
getBounds (float b[6]) const
{
- memcpy (b, bounds_, 6*sizeof (float));
+ std::copy(bounds_, bounds_ + 6, b);
}
inline float
};// class Entry
public:
- RotationSpaceCell (){}
+ RotationSpaceCell () = default;
virtual ~RotationSpaceCell ()
{
model_to_entry_.clear ();
inline const RotationSpaceCell::Entry*
getEntry (const ModelLibrary::Model* model) const
{
- std::map<const ModelLibrary::Model*, Entry>::const_iterator res = model_to_entry_.find (model);
+ auto res = model_to_entry_.find (model);
if ( res != model_to_entry_.end () )
return (&res->second);
class RotationSpaceCellCreator
{
public:
- RotationSpaceCellCreator (){}
- virtual ~RotationSpaceCellCreator (){}
+ RotationSpaceCellCreator () = default;
+ virtual ~RotationSpaceCellCreator () = default;
RotationSpaceCell* create (const SimpleOctree<RotationSpaceCell, RotationSpaceCellCreator, float>::Node* )
{
: counter_ (0)
{}
- virtual ~RotationSpaceCreator(){}
+ virtual ~RotationSpaceCreator() = default;
RotationSpace* create(const SimpleOctree<RotationSpace, RotationSpaceCreator, float>::Node* leaf)
{
- RotationSpace *rot_space = new RotationSpace (discretization_);
+ auto *rot_space = new RotationSpace (discretization_);
rot_space->setCenter (leaf->getCenter ());
rotation_spaces_.push_back (rot_space);
class PCL_EXPORTS RigidTransformSpace
{
public:
- RigidTransformSpace (){}
+ RigidTransformSpace () = default;
virtual ~RigidTransformSpace (){ this->clear ();}
inline void
getBounds () const { return bounds_;}
inline void
- getBounds (Scalar b[6]) const { memcpy (b, bounds_, 6*sizeof (Scalar));}
+ getBounds (Scalar b[6]) const { std::copy(bounds_, bounds_ + 6, b); }
inline Node*
getChild (int id) { return &children_[id];}
getBounds () const { return (bounds_);}
inline void
- getBounds (Scalar b[6]) const { memcpy (b, bounds_, 6*sizeof (Scalar));}
+ getBounds (Scalar b[6]) const { std::copy(bounds_, bounds_ + 6, b); }
inline Scalar
getVoxelSize () const { return voxel_size_;}
: new_to_old_energy_ratio_ (0.99f)
{}
- ~TrimmedICP ()
- {}
+ ~TrimmedICP () override = default;
/** \brief Call this method before calling align().
*
struct SparseQuantizedMultiModTemplate
{
/** \brief Constructor. */
- SparseQuantizedMultiModTemplate () {}
+ SparseQuantizedMultiModTemplate () = default;
/** \brief The storage for the multi-modality features. */
std::vector<QuantizedMultiModFeature> features;
/** \brief Constructor. */
inline LINEMOD_OrientationMap () : width_ (0), height_ (0) {}
/** \brief Destructor. */
- inline ~LINEMOD_OrientationMap () {}
+ inline ~LINEMOD_OrientationMap () = default;
/** \brief Returns the width of the modality data map. */
inline std::size_t
inline unsigned char
operator() (const float x, const float y, const float z) const
{
- const std::size_t x_index = static_cast<std::size_t> (x * static_cast<float> (offset_x) + static_cast<float> (offset_x));
- const std::size_t y_index = static_cast<std::size_t> (y * static_cast<float> (offset_y) + static_cast<float> (offset_y));
- const std::size_t z_index = static_cast<std::size_t> (z * static_cast<float> (range_z) + static_cast<float> (range_z));
+ const auto x_index = static_cast<std::size_t> (x * static_cast<float> (offset_x) + static_cast<float> (offset_x));
+ const auto y_index = static_cast<std::size_t> (y * static_cast<float> (offset_y) + static_cast<float> (offset_y));
+ const auto z_index = static_cast<std::size_t> (z * static_cast<float> (range_z) + static_cast<float> (range_z));
const std::size_t index = z_index*size_y*size_x + y_index*size_x + x_index;
/** \brief Modality based on surface normals.
* \author Stefan Holzer
+ * \ingroup recognition
*/
template <typename PointInT>
class SurfaceNormalModality : public QuantizableModality, public PCLBase<PointInT>
/** \brief Constructor. */
SurfaceNormalModality ();
/** \brief Destructor. */
- ~SurfaceNormalModality ();
+ ~SurfaceNormalModality () override;
/** \brief Sets the spreading size.
* \param[in] spreading_size the spreading size.
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT>
-pcl::SurfaceNormalModality<PointInT>::~SurfaceNormalModality ()
-{
-}
+pcl::SurfaceNormalModality<PointInT>::~SurfaceNormalModality () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT> void
if (angle < 0.0f) angle += 360.0f;
if (angle >= 360.0f) angle -= 360.0f;
- int bin_index = static_cast<int> (angle*8.0f/360.0f) & 7;
+ int bin_index = static_cast<int> (angle*8.0f/360.0f + 1);
+ bin_index = (bin_index < 1) ? 1 : (8 < bin_index) ? 8 : bin_index;
quantized_surface_normals_ (x, y) = static_cast<unsigned char> (bin_index);
}
const int width = input_->width;
const int height = input_->height;
- unsigned short * lp_depth = new unsigned short[width*height];
- unsigned char * lp_normals = new unsigned char[width*height];
- memset (lp_normals, 0, width*height);
+ auto * lp_depth = new unsigned short[width*height]{};
+ auto * lp_normals = new unsigned char[width*height]{};
surface_normal_orientations_.resize (width, height, 0.0f);
l_ny *= l_norminv;
l_nz *= l_norminv;
- float angle = 22.5f + std::atan2 (l_ny, l_nx) * 180.0f / 3.14f;
+ float angle = 11.25f + std::atan2 (l_ny, l_nx) * 180.0f / 3.14f;
if (angle < 0.0f) angle += 360.0f;
if (angle >= 360.0f) angle -= 360.0f;
- int bin_index = static_cast<int> (angle*8.0f/360.0f) & 7;
+ int bin_index = static_cast<int> (angle*8.0f/360.0f);
surface_normal_orientations_ (l_x, l_y) = angle;
}
/*cvSmooth(m_dep[0], m_dep[0], CV_MEDIAN, 5, 5);*/
- unsigned char map[255];
- memset(map, 0, 255);
+ unsigned char map[255]{};
- map[0x1<<0] = 0;
- map[0x1<<1] = 1;
- map[0x1<<2] = 2;
- map[0x1<<3] = 3;
- map[0x1<<4] = 4;
- map[0x1<<5] = 5;
- map[0x1<<6] = 6;
- map[0x1<<7] = 7;
+ map[0x1<<0] = 1;
+ map[0x1<<1] = 2;
+ map[0x1<<2] = 3;
+ map[0x1<<3] = 4;
+ map[0x1<<4] = 5;
+ map[0x1<<5] = 6;
+ map[0x1<<6] = 7;
+ map[0x1<<7] = 8;
quantized_surface_normals_.resize (width, height);
for (int row_index = 0; row_index < height; ++row_index)
for (auto &mask_map : mask_maps)
mask_map.resize (width, height);
- unsigned char map[255];
- memset(map, 0, 255);
+ unsigned char map[255]{};
map[0x1<<0] = 0;
map[0x1<<1] = 1;
}
}
- for (typename std::list<Candidate>::iterator iter = list1.begin (); iter != list1.end (); ++iter)
+ for (auto iter = list1.begin (); iter != list1.end (); ++iter)
iter->distance *= 1.0f / weights[iter->bin_index];
list1.sort ();
while (!feature_selection_finished)
{
const int sqr_distance = distance*distance;
- for (typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
+ for (auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
{
bool candidate_accepted = true;
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
const int dx = static_cast<int> (iter1->x) - static_cast<int> (iter2->x);
const int dy = static_cast<int> (iter1->y) - static_cast<int> (iter2->y);
float min_min_sqr_distance = std::numeric_limits<float>::max ();
float max_min_sqr_distance = 0;
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
float min_sqr_distance = std::numeric_limits<float>::max ();
- for (typename std::list<Candidate>::iterator iter3 = list2.begin (); iter3 != list2.end (); ++iter3)
+ for (auto iter3 = list2.begin (); iter3 != list2.end (); ++iter3)
{
if (iter2 == iter3)
continue;
if (list1.size () <= nr_features)
{
features.reserve (list1.size ());
- for (typename std::list<Candidate>::iterator iter = list1.begin (); iter != list1.end (); ++iter)
+ for (auto iter = list1.begin (); iter != list1.end (); ++iter)
{
QuantizedMultiModFeature feature;
while (list2.size () != nr_features)
{
const int sqr_distance = distance*distance;
- for (typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
+ for (auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
{
bool candidate_accepted = true;
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
const int dx = static_cast<int> (iter1->x) - static_cast<int> (iter2->x);
const int dy = static_cast<int> (iter1->y) - static_cast<int> (iter2->y);
}
}
- for (typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
+ for (auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
{
QuantizedMultiModFeature feature;
for (auto &mask_map : mask_maps)
mask_map.resize (width, height);
- unsigned char map[255];
- memset(map, 0, 255);
+ unsigned char map[255]{};
map[0x1<<0] = 0;
map[0x1<<1] = 1;
}
}
- for (typename std::list<Candidate>::iterator iter = list1.begin (); iter != list1.end (); ++iter)
+ for (auto iter = list1.begin (); iter != list1.end (); ++iter)
iter->distance *= 1.0f / weights[iter->bin_index];
list1.sort ();
features.reserve (list1.size ());
- for (typename std::list<Candidate>::iterator iter = list1.begin (); iter != list1.end (); ++iter)
+ for (auto iter = list1.begin (); iter != list1.end (); ++iter)
{
QuantizedMultiModFeature feature;
const float normal_y = surface_normals_ (col_index, row_index).normal_y;
const float normal_z = surface_normals_ (col_index, row_index).normal_z;
- if (std::isnan(normal_x) || std::isnan(normal_y) || std::isnan(normal_z) || normal_z > 0)
+ if (std::isnan(normal_x) || std::isnan(normal_y) || std::isnan(normal_z) || normal_z > 0 || (normal_x == 0 && normal_y == 0))
{
quantized_surface_normals_ (col_index, row_index) = 0;
continue;
if (angle < 0.0f) angle += 360.0f;
if (angle >= 360.0f) angle -= 360.0f;
- int bin_index = static_cast<int> (angle*8.0f/360.0f);
+ int bin_index = static_cast<int> (angle*8.0f/360.0f + 1);
+ bin_index = (bin_index < 1) ? 1 : (8 < bin_index) ? 8 : bin_index;
//quantized_surface_normals_.data[row_index*width+col_index] = 0x1 << bin_index;
quantized_surface_normals_ (col_index, row_index) = static_cast<unsigned char> (bin_index);
//////////////////////////////////////////////////////////////////////////////////////////////
pcl::DOTMOD::
-~DOTMOD()
-{
-}
+~DOTMOD() = default;
//////////////////////////////////////////////////////////////////////////////////////////////
size_t
if (use_normals_)
fhda.setNumChannels (4);
- pcl::TernaryTreeMissingDataBranchEstimator * btt = new pcl::TernaryTreeMissingDataBranchEstimator ();
+ auto * btt = new pcl::TernaryTreeMissingDataBranchEstimator ();
pcl::face_detection::PoseClassRegressionVarianceStatsEstimator<float, NodeType, std::vector<face_detection::TrainingExample>, int> rse (btt);
std::vector<float> thresholds_;
fhda.setNumChannels (4);
//pcl::BinaryTreeThresholdBasedBranchEstimator * btt = new pcl::BinaryTreeThresholdBasedBranchEstimator ();
- pcl::TernaryTreeMissingDataBranchEstimator * btt = new pcl::TernaryTreeMissingDataBranchEstimator ();
+ auto * btt = new pcl::TernaryTreeMissingDataBranchEstimator ();
face_detection::PoseClassRegressionVarianceStatsEstimator<float, NodeType, std::vector<face_detection::TrainingExample>, int> rse (btt);
std::vector<float> weights(cloud->size(), 0.f);
}
//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::LINEMOD::~LINEMOD()
-{
-}
+pcl::LINEMOD::~LINEMOD() = default;
//////////////////////////////////////////////////////////////////////////////////////////////
int
//energy_maps[bin_index] = new unsigned char[width*height];
//memset (energy_maps[bin_index], 0, width*height);
- const unsigned char base_bit = static_cast<unsigned char> (0x1);
- unsigned char val0 = static_cast<unsigned char> (base_bit << bin_index); // e.g. 00100000
- unsigned char val1 = static_cast<unsigned char> (val0 | (base_bit << (bin_index+1)&7) | (base_bit << (bin_index+7)&7)); // e.g. 01110000
- unsigned char val2 = static_cast<unsigned char> (val1 | (base_bit << (bin_index+2)&7) | (base_bit << (bin_index+6)&7)); // e.g. 11111000
- unsigned char val3 = static_cast<unsigned char> (val2 | (base_bit << (bin_index+3)&7) | (base_bit << (bin_index+5)&7)); // e.g. 11111101
+ const auto base_bit = static_cast<unsigned char> (0x1);
+ auto val0 = static_cast<unsigned char> (base_bit << bin_index); // e.g. 00100000
+ auto val1 = static_cast<unsigned char> (val0 | (base_bit << (bin_index+1)&7) | (base_bit << (bin_index+7)&7)); // e.g. 01110000
+ auto val2 = static_cast<unsigned char> (val1 | (base_bit << (bin_index+2)&7) | (base_bit << (bin_index+6)&7)); // e.g. 11111000
+ auto val3 = static_cast<unsigned char> (val2 | (base_bit << (bin_index+3)&7) | (base_bit << (bin_index+5)&7)); // e.g. 11111101
for (std::size_t index = 0; index < width*height; ++index)
{
if ((val0 & quantized_data[index]) != 0)
const std::size_t mem_size = mem_width * mem_height;
#ifdef __SSE2__
- unsigned short * score_sums = reinterpret_cast<unsigned short*> (aligned_malloc (mem_size*sizeof(unsigned short)));
- unsigned char * tmp_score_sums = reinterpret_cast<unsigned char*> (aligned_malloc (mem_size*sizeof(unsigned char)));
- memset (score_sums, 0, mem_size*sizeof (score_sums[0]));
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+ auto * score_sums = reinterpret_cast<unsigned short*> (aligned_malloc (mem_size*sizeof(unsigned short)));
+ auto * tmp_score_sums = reinterpret_cast<unsigned char*> (aligned_malloc (mem_size*sizeof(unsigned char)));
+ std::fill_n(score_sums, mem_size, 0);
+ std::fill_n(tmp_score_sums, mem_size, 0);
//__m128i * score_sums_m128i = reinterpret_cast<__m128i*> (score_sums);
- __m128i * tmp_score_sums_m128i = reinterpret_cast<__m128i*> (tmp_score_sums);
+ auto * tmp_score_sums_m128i = reinterpret_cast<__m128i*> (tmp_score_sums);
const std::size_t mem_size_16 = mem_size / 16;
//const std::size_t mem_size_mod_16 = mem_size & 15;
max_score += 4;
unsigned char * data = modality_linearized_maps[feature.modality_index][bin_index].getOffsetMap (feature.x, feature.y);
- __m128i * data_m128i = reinterpret_cast<__m128i*> (data);
+ auto * data_m128i = reinterpret_cast<__m128i*> (data);
for (std::size_t mem_index = 0; mem_index < mem_size_16; ++mem_index)
{
score_sums[mem_index] = static_cast<unsigned short> (score_sums[mem_index] + tmp_score_sums[mem_index]);
}
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+ std::fill_n(tmp_score_sums, mem_size, 0);
}
}
{
{
score_sums[mem_index] = static_cast<unsigned short> (score_sums[mem_index] + tmp_score_sums[mem_index]);
}
-
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+
+ std::fill_n(tmp_score_sums, mem_size, 0);
}
#else
- unsigned short * score_sums = new unsigned short[mem_size];
- //unsigned char * score_sums = new unsigned char[mem_size];
- memset (score_sums, 0, mem_size*sizeof (score_sums[0]));
+ unsigned short * score_sums = new unsigned short[mem_size]{};
std::size_t max_score = 0;
for (std::size_t feature_index = 0; feature_index < templates_[template_index].features.size (); ++feature_index)
//energy_maps[bin_index] = new unsigned char[width*height];
//memset (energy_maps[bin_index], 0, width*height);
- const unsigned char base_bit = static_cast<unsigned char> (0x1);
- unsigned char val0 = static_cast<unsigned char> (base_bit << bin_index); // e.g. 00100000
- unsigned char val1 = static_cast<unsigned char> (val0 | (base_bit << ((bin_index+1)%8)) | (base_bit << ((bin_index+7)%8))); // e.g. 01110000
- unsigned char val2 = static_cast<unsigned char> (val1 | (base_bit << ((bin_index+2)%8)) | (base_bit << ((bin_index+6)%8))); // e.g. 11111000
- unsigned char val3 = static_cast<unsigned char> (val2 | (base_bit << ((bin_index+3)%8)) | (base_bit << ((bin_index+5)%8))); // e.g. 11111101
+ const auto base_bit = static_cast<unsigned char> (0x1);
+ auto val0 = static_cast<unsigned char> (base_bit << bin_index); // e.g. 00100000
+ auto val1 = static_cast<unsigned char> (val0 | (base_bit << ((bin_index+1)%8)) | (base_bit << ((bin_index+7)%8))); // e.g. 01110000
+ auto val2 = static_cast<unsigned char> (val1 | (base_bit << ((bin_index+2)%8)) | (base_bit << ((bin_index+6)%8))); // e.g. 11111000
+ auto val3 = static_cast<unsigned char> (val2 | (base_bit << ((bin_index+3)%8)) | (base_bit << ((bin_index+5)%8))); // e.g. 11111101
for (std::size_t index = 0; index < width*height; ++index)
{
if ((val0 & quantized_data[index]) != 0)
const std::size_t mem_size = mem_width * mem_height;
#ifdef __SSE2__
- unsigned short * score_sums = reinterpret_cast<unsigned short*> (aligned_malloc (mem_size*sizeof(unsigned short)));
- unsigned char * tmp_score_sums = reinterpret_cast<unsigned char*> (aligned_malloc (mem_size*sizeof(unsigned char)));
- memset (score_sums, 0, mem_size*sizeof (score_sums[0]));
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+ auto * score_sums = reinterpret_cast<unsigned short*> (aligned_malloc (mem_size*sizeof(unsigned short)));
+ auto * tmp_score_sums = reinterpret_cast<unsigned char*> (aligned_malloc (mem_size*sizeof(unsigned char)));
+ std::fill_n(score_sums, mem_size, 0);
+ std::fill_n(tmp_score_sums, mem_size, 0);
//__m128i * score_sums_m128i = reinterpret_cast<__m128i*> (score_sums);
- __m128i * tmp_score_sums_m128i = reinterpret_cast<__m128i*> (tmp_score_sums);
+ auto * tmp_score_sums_m128i = reinterpret_cast<__m128i*> (tmp_score_sums);
const std::size_t mem_size_16 = mem_size / 16;
//const std::size_t mem_size_mod_16 = mem_size & 15;
max_score += 4;
unsigned char * data = modality_linearized_maps[feature.modality_index][bin_index].getOffsetMap (feature.x, feature.y);
- __m128i * data_m128i = reinterpret_cast<__m128i*> (data);
+ auto * data_m128i = reinterpret_cast<__m128i*> (data);
for (std::size_t mem_index = 0; mem_index < mem_size_16; ++mem_index)
{
score_sums[mem_index] = static_cast<unsigned short> (score_sums[mem_index] + tmp_score_sums[mem_index]);
}
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+ std::fill_n(tmp_score_sums, mem_size, 0);
}
}
{
{
score_sums[mem_index] = static_cast<unsigned short> (score_sums[mem_index] + tmp_score_sums[mem_index]);
}
-
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+
+ std::fill_n(tmp_score_sums, mem_size, 0);
}
#else
- unsigned short * score_sums = new unsigned short[mem_size];
- //unsigned char * score_sums = new unsigned char[mem_size];
- memset (score_sums, 0, mem_size*sizeof (score_sums[0]));
+ unsigned short * score_sums = new unsigned short[mem_size]{};
#ifdef LINEMOD_USE_SEPARATE_ENERGY_MAPS
- unsigned short * score_sums_1 = new unsigned short[mem_size];
- unsigned short * score_sums_2 = new unsigned short[mem_size];
- unsigned short * score_sums_3 = new unsigned short[mem_size];
- memset (score_sums_1, 0, mem_size*sizeof (score_sums_1[0]));
- memset (score_sums_2, 0, mem_size*sizeof (score_sums_2[0]));
- memset (score_sums_3, 0, mem_size*sizeof (score_sums_3[0]));
+ unsigned short * score_sums_1 = new unsigned short[mem_size]{};
+ unsigned short * score_sums_2 = new unsigned short[mem_size]{};
+ unsigned short * score_sums_3 = new unsigned short[mem_size]{};
#endif
int max_score = 0;
if (sup_col_index >= mem_width)
continue;
- const std::size_t weight = static_cast<std::size_t> (score_sums[sup_row_index*mem_width + sup_col_index]);
+ const auto weight = static_cast<std::size_t> (score_sums[sup_row_index*mem_width + sup_col_index]);
average_col += sup_col_index * weight;
average_row += sup_row_index * weight;
sum += weight;
//energy_maps[bin_index] = new unsigned char[width*height];
//memset (energy_maps[bin_index], 0, width*height);
- const unsigned char base_bit = static_cast<unsigned char> (0x1);
- unsigned char val0 = static_cast<unsigned char> (base_bit << bin_index); // e.g. 00100000
- unsigned char val1 = static_cast<unsigned char> (val0 | (base_bit << ((bin_index+1)%8)) | (base_bit << ((bin_index+7)%8))); // e.g. 01110000
- unsigned char val2 = static_cast<unsigned char> (val1 | (base_bit << ((bin_index+2)%8)) | (base_bit << ((bin_index+6)%8))); // e.g. 11111000
- unsigned char val3 = static_cast<unsigned char> (val2 | (base_bit << ((bin_index+3)%8)) | (base_bit << ((bin_index+5)%8))); // e.g. 11111101
+ const auto base_bit = static_cast<unsigned char> (0x1);
+ auto val0 = static_cast<unsigned char> (base_bit << bin_index); // e.g. 00100000
+ auto val1 = static_cast<unsigned char> (val0 | (base_bit << ((bin_index+1)%8)) | (base_bit << ((bin_index+7)%8))); // e.g. 01110000
+ auto val2 = static_cast<unsigned char> (val1 | (base_bit << ((bin_index+2)%8)) | (base_bit << ((bin_index+6)%8))); // e.g. 11111000
+ auto val3 = static_cast<unsigned char> (val2 | (base_bit << ((bin_index+3)%8)) | (base_bit << ((bin_index+5)%8))); // e.g. 11111101
for (std::size_t index = 0; index < width*height; ++index)
{
if ((val0 & quantized_data[index]) != 0)
for (float scale = min_scale; scale <= max_scale; scale *= scale_multiplier)
{
#ifdef __SSE2__
- unsigned short * score_sums = reinterpret_cast<unsigned short*> (aligned_malloc (mem_size*sizeof(unsigned short)));
- unsigned char * tmp_score_sums = reinterpret_cast<unsigned char*> (aligned_malloc (mem_size*sizeof(unsigned char)));
- memset (score_sums, 0, mem_size*sizeof (score_sums[0]));
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+ auto * score_sums = reinterpret_cast<unsigned short*> (aligned_malloc (mem_size*sizeof(unsigned short)));
+ auto * tmp_score_sums = reinterpret_cast<unsigned char*> (aligned_malloc (mem_size*sizeof(unsigned char)));
+ std::fill_n(score_sums, mem_size, 0);
+ std::fill_n(tmp_score_sums, mem_size, 0);
//__m128i * score_sums_m128i = reinterpret_cast<__m128i*> (score_sums);
- __m128i * tmp_score_sums_m128i = reinterpret_cast<__m128i*> (tmp_score_sums);
+ auto * tmp_score_sums_m128i = reinterpret_cast<__m128i*> (tmp_score_sums);
const std::size_t mem_size_16 = mem_size / 16;
//const std::size_t mem_size_mod_16 = mem_size & 15;
unsigned char *data = modality_linearized_maps[feature.modality_index][bin_index].getOffsetMap (
std::size_t (float (feature.x) * scale), std::size_t (float (feature.y) * scale));
- __m128i * data_m128i = reinterpret_cast<__m128i*> (data);
+ auto * data_m128i = reinterpret_cast<__m128i*> (data);
for (std::size_t mem_index = 0; mem_index < mem_size_16; ++mem_index)
{
score_sums[mem_index] = static_cast<unsigned short> (score_sums[mem_index] + tmp_score_sums[mem_index]);
}
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+ std::fill_n(tmp_score_sums, mem_size, 0);
}
}
{
{
score_sums[mem_index] = static_cast<unsigned short> (score_sums[mem_index] + tmp_score_sums[mem_index]);
}
-
- memset (tmp_score_sums, 0, mem_size*sizeof (tmp_score_sums[0]));
+
+ std::fill_n(tmp_score_sums, mem_size, 0);
}
#else
- unsigned short * score_sums = new unsigned short[mem_size];
- //unsigned char * score_sums = new unsigned char[mem_size];
- memset (score_sums, 0, mem_size*sizeof (score_sums[0]));
+ unsigned short * score_sums = new unsigned short[mem_size]{};
#ifdef LINEMOD_USE_SEPARATE_ENERGY_MAPS
- unsigned short * score_sums_1 = new unsigned short[mem_size];
- unsigned short * score_sums_2 = new unsigned short[mem_size];
- unsigned short * score_sums_3 = new unsigned short[mem_size];
- memset (score_sums_1, 0, mem_size*sizeof (score_sums_1[0]));
- memset (score_sums_2, 0, mem_size*sizeof (score_sums_2[0]));
- memset (score_sums_3, 0, mem_size*sizeof (score_sums_3[0]));
+ unsigned short * score_sums_1 = new unsigned short[mem_size]{};
+ unsigned short * score_sums_2 = new unsigned short[mem_size]{};
+ unsigned short * score_sums_3 = new unsigned short[mem_size]{};
#endif
int max_score = 0;
if (sup_col_index >= mem_width)
continue;
- const std::size_t weight = static_cast<std::size_t> (score_sums[sup_row_index*mem_width + sup_col_index]);
+ const auto weight = static_cast<std::size_t> (score_sums[sup_row_index*mem_width + sup_col_index]);
average_col += sup_col_index * weight;
average_row += sup_row_index * weight;
sum += weight;
#include <cstddef>
//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::QuantizableModality::QuantizableModality ()
-{
-}
+pcl::QuantizableModality::QuantizableModality () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::QuantizableModality::~QuantizableModality ()
-{
-}
+pcl::QuantizableModality::~QuantizableModality () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
pcl::QuantizedMap::QuantizedMap ()
}
//////////////////////////////////////////////////////////////////////////////////////////////
-pcl::QuantizedMap::~QuantizedMap ()
-{
-}
+pcl::QuantizedMap::~QuantizedMap () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
void
int i = 0;
// Initialize the vector with bounded objects
- for ( std::vector<Hypothesis>::iterator hypo = accepted_hypotheses_.begin () ; hypo != accepted_hypotheses_.end () ; ++hypo, ++i )
+ for ( auto hypo = accepted_hypotheses_.begin () ; hypo != accepted_hypotheses_.end () ; ++hypo, ++i )
{
// Create, initialize and save a bounded object based on the hypothesis
- BVHH::BoundedObject *bounded_object = new BVHH::BoundedObject (&(*hypo));
+ auto *bounded_object = new BVHH::BoundedObject (&(*hypo));
hypo->computeCenterOfMass (bounded_object->getCentroid ());
hypo->computeBounds (bounded_object->getBounds ());
bounded_objects[i] = bounded_object;
graph.resize (static_cast<int> (hypo_leaves.size ()));
- for ( std::vector<HypothesisOctree::Node*>::iterator hypo = hypo_leaves.begin () ; hypo != hypo_leaves.end () ; ++hypo, ++i )
+ for ( auto hypo = hypo_leaves.begin () ; hypo != hypo_leaves.end () ; ++hypo, ++i )
(*hypo)->getData ().setLinearId (i);
i = 0;
graph.resize (static_cast<int> (bounded_objects->size ()));
// Setup the hypotheses' ids
- for ( std::vector<BVHH::BoundedObject*>::const_iterator obj = bounded_objects->begin () ; obj != bounded_objects->end () ; ++obj, ++lin_id )
+ for ( auto obj = bounded_objects->begin () ; obj != bounded_objects->end () ; ++obj, ++lin_id )
{
(*obj)->getData ()->setLinearId (lin_id);
graph.getNodes ()[lin_id]->setData ((*obj)->getData ());
// Compute the match based on the normal agreement
const std::set<ORROctree::Node*, bool(*)(ORROctree::Node*,ORROctree::Node*)>* nodes = scene_octree_proj_.getOctreeNodes (transformed_point);
- std::set<ORROctree::Node*, bool(*)(ORROctree::Node*,ORROctree::Node*)>::const_iterator n = nodes->begin ();
+ auto n = nodes->begin ();
ORROctree::Node *closest_node = *n;
float min_sqr_dist = aux::sqrDistance3 (closest_node->getData ()->getPoint (), transformed_point);
std::size_t i = 0;
// Now iterate over all full leaves and compute the normals and average points
- for ( std::vector<ORROctree::Node*>::const_iterator it = full_leaves_.begin() ; it != full_leaves_.end() ; ++it, ++i )
+ for ( auto it = full_leaves_.begin() ; it != full_leaves_.end() ; ++it, ++i )
{
out[i].x = (*it)->getData ()->getPoint ()[0];
out[i].y = (*it)->getData ()->getPoint ()[1];
std::size_t i = 0;
// Now iterate over all full leaves and compute the normals and average points
- for ( std::vector<ORROctree::Node*>::const_iterator it = full_leaves_.begin() ; it != full_leaves_.end() ; ++it, ++i )
+ for ( auto it = full_leaves_.begin() ; it != full_leaves_.end() ; ++it, ++i )
{
out[i].normal_x = (*it)->getData ()->getNormal ()[0];
out[i].normal_y = (*it)->getData ()->getNormal ()[1];
for (const auto &full_set : full_sets_)
{
// Get the first node in the set
- std::set<ORROctree::Node*, bool(*)(ORROctree::Node*,ORROctree::Node*)>::iterator node = full_set->get_nodes ().begin ();
+ auto node = full_set->get_nodes ().begin ();
// Initialize
float best_min = (*node)->getBounds ()[4];
float best_max = (*node)->getBounds ()[5];
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
EIGEN_POLYNOMIAL_SOLVER_BASE_INHERITED_TYPES(PS_Base)
public:
- virtual ~PolynomialSolver() {}
+ virtual ~PolynomialSolver() = default;
template <typename OtherPolynomial>
inline PolynomialSolver(const OtherPolynomial& poly, bool& hasRealRoot)
BFGSDummyFunctor() : m_inputs(InputsAtCompileTime) {}
BFGSDummyFunctor(int inputs) : m_inputs(inputs) {}
- virtual ~BFGSDummyFunctor() {}
+ virtual ~BFGSDummyFunctor() = default;
int
inputs() const
{
minimizeOneStep(FVectorType& x);
BFGSSpace::Status
testGradient();
- PCL_DEPRECATED(1, 13, "Use `testGradient()` instead")
- BFGSSpace::Status testGradient(Scalar) { return testGradient(); }
void
resetParameters(void)
{
using ConstPtr = shared_ptr<const ConvergenceCriteria>;
/** \brief Empty constructor. */
- ConvergenceCriteria() {}
+ ConvergenceCriteria() = default;
/** \brief Empty destructor. */
- virtual ~ConvergenceCriteria() {}
+ virtual ~ConvergenceCriteria() = default;
/** \brief Check if convergence has been reached. Pure virtual. */
virtual bool
{}
/** \brief Empty destructor */
- ~CorrespondenceEstimationBase() {}
+ ~CorrespondenceEstimationBase() override = default;
/** \brief Provide a pointer to the input source
* (e.g., the point cloud that we want to align to the target)
}
/** \brief Abstract method for setting the source normals */
- virtual void setSourceNormals(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
+ virtual void
+ setSourceNormals(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
{
PCL_WARN("[pcl::registration::%s::setSourceNormals] This class does not require "
"input source normals\n",
}
/** \brief Abstract method for setting the target normals */
- virtual void setTargetNormals(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
+ virtual void
+ setTargetNormals(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
{
PCL_WARN("[pcl::registration::%s::setTargetNormals] This class does not require "
"input target normals\n",
CorrespondenceEstimation() { corr_name_ = "CorrespondenceEstimation"; }
/** \brief Empty destructor */
- ~CorrespondenceEstimation() {}
+ ~CorrespondenceEstimation() override = default;
/** \brief Determine the correspondences between input and target cloud.
* \param[out] correspondences the found correspondences (index of query point, index
}
/** \brief Empty destructor */
- virtual ~CorrespondenceEstimationBackProjection() {}
+ virtual ~CorrespondenceEstimationBackProjection() = default;
/** \brief Set the normals computed on the source point cloud
* \param[in] normals the normals computed for the source cloud
}
/** \brief Empty destructor */
- ~CorrespondenceEstimationNormalShooting() {}
+ ~CorrespondenceEstimationNormalShooting() override = default;
/** \brief Set the normals computed on the source point cloud
* \param[in] normals the normals computed for the source cloud
using ConstPtr = shared_ptr<const CorrespondenceRejector>;
/** \brief Empty constructor. */
- CorrespondenceRejector() {}
+ CorrespondenceRejector() = default;
/** \brief Empty destructor. */
- virtual ~CorrespondenceRejector() {}
+ virtual ~CorrespondenceRejector() = default;
/** \brief Provide a pointer to the vector of the input correspondences.
* \param[in] correspondences the const shared pointer to a correspondence vector
}
/** \brief Abstract method for setting the source cloud */
- virtual void setSourcePoints(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
+ virtual void
+ setSourcePoints(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
{
PCL_WARN("[pcl::registration::%s::setSourcePoints] This class does not require an "
"input source cloud\n",
}
/** \brief Abstract method for setting the source normals */
- virtual void setSourceNormals(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
+ virtual void
+ setSourceNormals(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
{
PCL_WARN("[pcl::registration::%s::setSourceNormals] This class does not require "
"input source normals\n",
}
/** \brief Abstract method for setting the target cloud */
- virtual void setTargetPoints(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
+ virtual void
+ setTargetPoints(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
{
PCL_WARN("[pcl::registration::%s::setTargetPoints] This class does not require an "
"input target cloud\n",
}
/** \brief Abstract method for setting the target normals */
- virtual void setTargetNormals(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
+ virtual void
+ setTargetNormals(pcl::PCLPointCloud2::ConstPtr /*cloud2*/)
{
PCL_WARN("[pcl::registration::%s::setTargetNormals] This class does not require "
"input target normals\n",
{}
/** \brief Empty destructor */
- ~DataContainer() {}
+ ~DataContainer() override = default;
/** \brief Provide a source point cloud dataset (must contain XYZ
* data!), used to compute the correspondence distance.
}
/** \brief Empty destructor */
- ~CorrespondenceRejectorDistance() {}
+ ~CorrespondenceRejectorDistance() override = default;
/** \brief Get a list of valid correspondences after rejection from the original set
* of correspondences. \param[in] original_correspondences the set of initial
}
/** \brief Empty destructor. */
- ~CorrespondenceRejectorFeatures() {}
+ ~CorrespondenceRejectorFeatures() override = default;
/** \brief Get a list of valid correspondences after rejection from the original set
* of correspondences \param[in] original_correspondences the set of initial
{}
/** \brief Empty destructor */
- ~FeatureContainer() {}
+ ~FeatureContainer() override = default;
inline void
setSourceFeature(const FeatureCloudConstPtr& source_features)
}
/** \brief Get a list of valid correspondences after rejection from the original set
- * of correspondences. \param[in] original_correspondences the set of initial
- * correspondences given \param[out] remaining_correspondences the resultant filtered
- * set of remaining correspondences
+ * of correspondences.
+ * \param[in] original_correspondences the set of initial correspondences given
+ * \param[out] remaining_correspondences the resultant filtered set of remaining
+ * correspondences
*/
void
getRemainingCorrespondences(const pcl::Correspondences& original_correspondences,
pcl::Correspondences& remaining_correspondences) override;
/** \brief Provide a source point cloud dataset (must contain XYZ data!), used to
- * compute the correspondence distance. \param[in] cloud a cloud containing XYZ data
+ * compute the correspondence distance.
+ * \param[in] cloud a cloud containing XYZ data
*/
inline void
setInputSource(const PointCloudSourceConstPtr& cloud)
}
/** \brief Provide a target point cloud dataset (must contain XYZ data!), used to
- * compute the correspondence distance. \param[in] target a cloud containing XYZ data
+ * compute the correspondence distance.
+ * \param[in] target a cloud containing XYZ data
*/
inline void
setInputTarget(const PointCloudTargetConstPtr& target)
corr[idx[1]].index_query,
corr[idx[0]].index_match,
corr[idx[1]].index_match,
- cardinality_));
+ similarity_threshold_squared_));
}
// Otherwise check all edges
for (int i = 0; i < cardinality_; ++i) {
/** \brief Polygonal rejection of a single polygon, indexed by two point index vectors
* \param source_indices indices of polygon points in \ref input_, must have a size
- * equal to \ref cardinality_ \param target_indices corresponding indices of polygon
- * points in \ref target_, must have a size equal to \ref cardinality_ \return true if
- * all edge length ratios are larger than or equal to \ref similarity_threshold_
+ * equal to \ref cardinality_
+ * \param target_indices corresponding indices of polygon points in \ref target_, must
+ * have a size equal to \ref cardinality_
+ * \return true if all edge length ratios are larger than or equal to
+ * \ref similarity_threshold_
*/
inline bool
thresholdPolygon(const pcl::Indices& source_indices,
}
/** \brief Get k unique random indices in range {0,...,n-1} (sampling without
- * replacement) \note No check is made to ensure that k <= n. \param n upper index
- * range, exclusive \param k number of unique indices to sample \return k unique
- * random indices in range {0,...,n-1}
+ * replacement) \note No check is made to ensure that k <= n.
+ * \param n upper index range, exclusive
+ * \param k number of unique indices to sample
+ * \return k unique random indices in range {0,...,n-1}
*/
inline std::vector<int>
getUniqueRandomIndices(int n, int k)
/** \brief Compute a linear histogram. This function is equivalent to the MATLAB
* function \b histc, with the edges set as follows: <b>
- * lower:(upper-lower)/bins:upper </b> \param data input samples \param lower lower
- * bound of input samples \param upper upper bound of input samples \param bins number
- * of bins in output \return linear histogram
+ * lower:(upper-lower)/bins:upper </b>
+ * \param data input samples
+ * \param lower lower bound of input samples
+ * \param upper upper bound of input samples
+ * \param bins number of bins in output
+ * \return linear histogram
*/
std::vector<int>
computeHistogram(const std::vector<float>& data, float lower, float upper, int bins);
/** \brief Find the optimal value for binary histogram thresholding using Otsu's
- * method \param histogram input histogram \return threshold value according to Otsu's
+ * method
+ * \param histogram input histogram \return threshold value according to Otsu's
* criterion
*/
int
}
/** \brief Empty destructor. */
- ~CorrespondenceRejectorSampleConsensus() {}
+ ~CorrespondenceRejectorSampleConsensus() override = default;
/** \brief Get a list of valid correspondences after rejection from the original set
* of correspondences. \param[in] original_correspondences the set of initial
}
/** \brief Destructor. */
- ~CorrespondenceRejectorTrimmed() {}
+ ~CorrespondenceRejectorTrimmed() override = default;
/** \brief Set the expected ratio of overlap between point clouds (in
* terms of correspondences).
/** \brief Empty constructor.
* Sets:
- * * the maximum number of iterations to 1000
+ * * the maximum number of iterations to 100
* * the rotation threshold to 0.256 degrees (0.99999)
* * the translation threshold to 0.0003 meters (3e-4^2)
* * the MSE relative / absolute thresholds to 0.001% and 1e-12
{}
/** \brief Empty destructor */
- ~DefaultConvergenceCriteria() {}
+ ~DefaultConvergenceCriteria() override = default;
/** \brief Set the maximum number of consecutive iterations that the internal
* rotation, translation, and MSE differences are allowed to be similar. \param[in]
#include <Eigen/Core>
-#include <string.h>
-
#include <algorithm>
+#include <cstring>
#include <vector>
namespace pcl {
computeMedian(double* fvec, int m)
{
// Copy the values to vectors for faster sorting
- std::vector<double> data(m);
- memcpy(&data[0], fvec, sizeof(double) * m);
+ std::vector<double> data(fvec, fvec + m);
std::nth_element(data.begin(), data.begin() + (data.size() >> 1), data.end());
return (data[data.size() >> 1]);
, vd_(){};
/** \brief Empty destructor */
- ~ELCH() {}
+ ~ELCH() override = default;
/** \brief Add a new point cloud to the internal graph.
* \param[in] cloud the new point cloud
/** \brief GeneralizedIterativeClosestPoint is an ICP variant that implements the
* generalized iterative closest point algorithm as described by Alex Segal et al. in
* http://www.robots.ox.ac.uk/~avsegal/resources/papers/Generalized_ICP.pdf
- * The approach is based on using anistropic cost functions to optimize the alignment
+ * The approach is based on using anisotropic cost functions to optimize the alignment
* after closest point assignments have been made.
* The original code uses GSL and ANN while in ours we use an eigen mapped BFGS and
* FLANN.
* \author Nizar Sallem
* \ingroup registration
*/
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar = float>
class GeneralizedIterativeClosestPoint
-: public IterativeClosestPoint<PointSource, PointTarget> {
+: public IterativeClosestPoint<PointSource, PointTarget, Scalar> {
public:
- using IterativeClosestPoint<PointSource, PointTarget>::reg_name_;
- using IterativeClosestPoint<PointSource, PointTarget>::getClassName;
- using IterativeClosestPoint<PointSource, PointTarget>::indices_;
- using IterativeClosestPoint<PointSource, PointTarget>::target_;
- using IterativeClosestPoint<PointSource, PointTarget>::input_;
- using IterativeClosestPoint<PointSource, PointTarget>::tree_;
- using IterativeClosestPoint<PointSource, PointTarget>::tree_reciprocal_;
- using IterativeClosestPoint<PointSource, PointTarget>::nr_iterations_;
- using IterativeClosestPoint<PointSource, PointTarget>::max_iterations_;
- using IterativeClosestPoint<PointSource, PointTarget>::previous_transformation_;
- using IterativeClosestPoint<PointSource, PointTarget>::final_transformation_;
- using IterativeClosestPoint<PointSource, PointTarget>::transformation_;
- using IterativeClosestPoint<PointSource, PointTarget>::transformation_epsilon_;
- using IterativeClosestPoint<PointSource, PointTarget>::converged_;
- using IterativeClosestPoint<PointSource, PointTarget>::corr_dist_threshold_;
- using IterativeClosestPoint<PointSource, PointTarget>::inlier_threshold_;
- using IterativeClosestPoint<PointSource, PointTarget>::min_number_correspondences_;
- using IterativeClosestPoint<PointSource, PointTarget>::update_visualizer_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::reg_name_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::getClassName;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::indices_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::target_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::input_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::tree_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::tree_reciprocal_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::nr_iterations_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::max_iterations_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::
+ previous_transformation_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::final_transformation_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::transformation_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::
+ transformation_epsilon_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::converged_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::corr_dist_threshold_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::inlier_threshold_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::
+ min_number_correspondences_;
+ using IterativeClosestPoint<PointSource, PointTarget, Scalar>::update_visualizer_;
using PointCloudSource = pcl::PointCloud<PointSource>;
using PointCloudSourcePtr = typename PointCloudSource::Ptr;
using MatricesVectorPtr = shared_ptr<MatricesVector>;
using MatricesVectorConstPtr = shared_ptr<const MatricesVector>;
- using InputKdTree = typename Registration<PointSource, PointTarget>::KdTree;
- using InputKdTreePtr = typename Registration<PointSource, PointTarget>::KdTreePtr;
+ using InputKdTree = typename Registration<PointSource, PointTarget, Scalar>::KdTree;
+ using InputKdTreePtr =
+ typename Registration<PointSource, PointTarget, Scalar>::KdTreePtr;
- using Ptr = shared_ptr<GeneralizedIterativeClosestPoint<PointSource, PointTarget>>;
- using ConstPtr =
- shared_ptr<const GeneralizedIterativeClosestPoint<PointSource, PointTarget>>;
+ using Ptr =
+ shared_ptr<GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>>;
+ using ConstPtr = shared_ptr<
+ const GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>>;
+ using Vector3 = typename Eigen::Matrix<Scalar, 3, 1>;
+ using Vector4 = typename Eigen::Matrix<Scalar, 4, 1>;
using Vector6d = Eigen::Matrix<double, 6, 1>;
+ using Matrix3 = typename Eigen::Matrix<Scalar, 3, 3>;
+ using Matrix4 =
+ typename IterativeClosestPoint<PointSource, PointTarget, Scalar>::Matrix4;
+ using AngleAxis = typename Eigen::AngleAxis<Scalar>;
/** \brief Empty constructor. */
GeneralizedIterativeClosestPoint()
const pcl::Indices& indices_src,
const PointCloudTarget& cloud_tgt,
const pcl::Indices& indices_tgt,
- Eigen::Matrix4f& transformation_matrix) {
+ Matrix4& transformation_matrix) {
estimateRigidTransformationBFGS(
cloud_src, indices_src, cloud_tgt, indices_tgt, transformation_matrix);
};
for (std::size_t i = 0; i < input.size(); ++i)
input[i].data[3] = 1.0;
- pcl::IterativeClosestPoint<PointSource, PointTarget>::setInputSource(cloud);
+ pcl::IterativeClosestPoint<PointSource, PointTarget, Scalar>::setInputSource(cloud);
input_covariances_.reset();
}
inline void
setInputTarget(const PointCloudTargetConstPtr& target) override
{
- pcl::IterativeClosestPoint<PointSource, PointTarget>::setInputTarget(target);
+ pcl::IterativeClosestPoint<PointSource, PointTarget, Scalar>::setInputTarget(
+ target);
target_covariances_.reset();
}
}
/** \brief Estimate a rigid rotation transformation between a source and a target
- * point cloud using an iterative non-linear Levenberg-Marquardt approach. \param[in]
- * cloud_src the source point cloud dataset \param[in] indices_src the vector of
- * indices describing the points of interest in \a cloud_src
+ * point cloud using an iterative non-linear BFGS approach.
+ * \param[in] cloud_src the source point cloud dataset
+ * \param[in] indices_src the vector of indices describing
+ * the points of interest in \a cloud_src
* \param[in] cloud_tgt the target point cloud dataset
* \param[in] indices_tgt the vector of indices describing
* the correspondences of the interest points from \a indices_src
- * \param[out] transformation_matrix the resultant transformation matrix
+ * \param[in,out] transformation_matrix the resultant transformation matrix
*/
void
estimateRigidTransformationBFGS(const PointCloudSource& cloud_src,
const pcl::Indices& indices_src,
const PointCloudTarget& cloud_tgt,
const pcl::Indices& indices_tgt,
- Eigen::Matrix4f& transformation_matrix);
+ Matrix4& transformation_matrix);
/** \brief \return Mahalanobis distance matrix for the given point index */
inline const Eigen::Matrix3d&
return mahalanobis_[index];
}
- /** \brief Computes rotation matrix derivative.
+ /** \brief Computes the derivative of the cost function w.r.t rotation angles.
* rotation matrix is obtainded from rotation angles x[3], x[4] and x[5]
- * \return d/d_rx, d/d_ry and d/d_rz respectively in g[3], g[4] and g[5]
- * param x array representing 3D transformation
- * param R rotation matrix
- * param g gradient vector
+ * \return d/d_Phi, d/d_Theta, d/d_Psi respectively in g[3], g[4] and g[5]
+ * \param[in] x array representing 3D transformation
+ * \param[in] dCost_dR_T the transpose of the derivative of the cost function w.r.t
+ * rotation matrix
+ * \param[out] g gradient vector
*/
void
- computeRDerivative(const Vector6d& x, const Eigen::Matrix3d& R, Vector6d& g) const;
+ computeRDerivative(const Vector6d& x,
+ const Eigen::Matrix3d& dCost_dR_T,
+ Vector6d& g) const;
/** \brief Set the rotation epsilon (maximum allowable difference between two
* consecutive rotations) in order for an optimization to be considered as having
double rotation_epsilon_;
/** \brief base transformation */
- Eigen::Matrix4f base_transformation_;
+ Matrix4 base_transformation_;
/** \brief Temporary pointer to the source dataset. */
const PointCloudSource* tmp_src_;
const typename pcl::search::KdTree<PointT>::Ptr tree,
MatricesVector& cloud_covariances);
- /** \return trace of mat1^t . mat2
+ /** \return trace of mat1 . mat2
* \param mat1 matrix of dimension nxm
- * \param mat2 matrix of dimension nxp
+ * \param mat2 matrix of dimension mxp
*/
inline double
matricesInnerProd(const Eigen::MatrixXd& mat1, const Eigen::MatrixXd& mat2) const
{
- double r = 0.;
- std::size_t n = mat1.rows();
- // tr(mat1^t.mat2)
- for (std::size_t i = 0; i < n; i++)
- for (std::size_t j = 0; j < n; j++)
- r += mat1(j, i) * mat2(i, j);
- return r;
+ if (mat1.cols() != mat2.rows()) {
+ PCL_THROW_EXCEPTION(PCLException,
+ "The two matrices' shapes don't match. "
+ "They are ("
+ << mat1.rows() << ", " << mat1.cols() << ") and ("
+ << mat2.rows() << ", " << mat2.cols() << ")");
+ }
+ return (mat1 * mat2).trace();
}
/** \brief Rigid transformation computation method with initial guess.
* compute
*/
void
- computeTransformation(PointCloudSource& output,
- const Eigen::Matrix4f& guess) override;
+ computeTransformation(PointCloudSource& output, const Matrix4& guess) override;
/** \brief Search for the closest nearest neighbor of a given point.
* \param query the point to search a nearest neighbour for
/// \brief compute transformation matrix from transformation matrix
void
- applyState(Eigen::Matrix4f& t, const Vector6d& x) const;
+ applyState(Matrix4& t, const Vector6d& x) const;
/// \brief optimization functor structure
struct OptimizationFunctorWithIndices : public BFGSDummyFunctor<double, 6> {
const pcl::Indices& src_indices,
const pcl::PointCloud<PointTarget>& cloud_tgt,
const pcl::Indices& tgt_indices,
- Eigen::Matrix4f& transformation_matrix)>
+ Matrix4& transformation_matrix)>
rigid_transformation_estimation_;
};
} // namespace pcl
trivial_ = false;
}
- ~MyPointRepresentation() {}
+ ~MyPointRepresentation() override = default;
inline Ptr
makeShared() const
optimize(GraphHandler<GraphT>& inout_graph) = 0;
/** \brief Empty destructor */
- virtual ~GraphOptimizer() {}
+ virtual ~GraphOptimizer() = default;
};
} // namespace registration
} // namespace pcl
{}
/** \brief Empty destructor */
- virtual ~GraphRegistration() {}
+ virtual ~GraphRegistration() = default;
/** \brief Add a point cloud and the associated camera pose to the graph */
template <typename PointT>
FPCSInitialAlignment();
/** \brief Destructor. */
- ~FPCSInitialAlignment(){};
+ ~FPCSInitialAlignment() override = default;
/** \brief Provide a pointer to the vector of target indices.
* \param[in] target_indices a pointer to the target indices
KFPCSInitialAlignment();
/** \brief Destructor. */
- ~KFPCSInitialAlignment(){};
+ ~KFPCSInitialAlignment() override = default;
/** \brief Set the upper translation threshold used for score evaluation.
* \param[in] upper_trl_boundary upper translation threshold
class HuberPenalty : public ErrorFunctor {
private:
- HuberPenalty() {}
+ HuberPenalty() = default;
public:
HuberPenalty(float threshold) : threshold_(threshold) {}
class TruncatedError : public ErrorFunctor {
private:
- TruncatedError() {}
+ TruncatedError() = default;
public:
- ~TruncatedError() {}
+ ~TruncatedError() override = default;
TruncatedError(float threshold) : threshold_(threshold) {}
float
operator=(IterativeClosestPoint&&) = delete;
/** \brief Empty destructor */
- ~IterativeClosestPoint() {}
+ ~IterativeClosestPoint() override = default;
/** \brief Returns a pointer to the DefaultConvergenceCriteria used by the
* IterativeClosestPoint class. This allows to check the convergence state after the
}
/** \brief Provide a pointer to the input target
- * (e.g., the point cloud that we want to align to the target)
+ * (e.g., the point cloud that we want to align the input source to)
*
* \param[in] cloud the input point cloud target
*/
using IterativeClosestPoint<PointSource, PointTarget, Scalar>::
correspondence_rejectors_;
- using Ptr = shared_ptr<IterativeClosestPoint<PointSource, PointTarget, Scalar>>;
- using ConstPtr =
- shared_ptr<const IterativeClosestPoint<PointSource, PointTarget, Scalar>>;
+ using Ptr =
+ shared_ptr<IterativeClosestPointWithNormals<PointSource, PointTarget, Scalar>>;
+ using ConstPtr = shared_ptr<
+ const IterativeClosestPointWithNormals<PointSource, PointTarget, Scalar>>;
/** \brief Empty constructor. */
IterativeClosestPointWithNormals()
};
/** \brief Empty destructor */
- virtual ~IterativeClosestPointWithNormals() {}
+ ~IterativeClosestPointWithNormals() override = default;
/** \brief Set whether to use a symmetric objective function or not
*
* \param[in] transform a 4x4 rigid transformation
* \note Can be used with cloud_in equal to cloud_out
*/
- virtual void
+ void
transformCloud(const PointCloudSource& input,
PointCloudSource& output,
- const Matrix4& transform);
+ const Matrix4& transform) override;
/** \brief Type of objective function (asymmetric vs. symmetric) used for transform
* estimation */
namespace pcl {
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
template <typename PointT>
void
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::computeCovariances(
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::computeCovariances(
typename pcl::PointCloud<PointT>::ConstPtr cloud,
const typename pcl::search::KdTree<PointT>::Ptr kdtree,
MatricesVector& cloud_covariances)
}
Eigen::Vector3d mean;
- pcl::Indices nn_indecies;
- nn_indecies.reserve(k_correspondences_);
+ pcl::Indices nn_indices;
+ nn_indices.reserve(k_correspondences_);
std::vector<float> nn_dist_sq;
nn_dist_sq.reserve(k_correspondences_);
if (cloud_covariances.size() < cloud->size())
cloud_covariances.resize(cloud->size());
- MatricesVector::iterator matrices_iterator = cloud_covariances.begin();
+ auto matrices_iterator = cloud_covariances.begin();
for (auto points_iterator = cloud->begin(); points_iterator != cloud->end();
++points_iterator, ++matrices_iterator) {
const PointT& query_point = *points_iterator;
mean.setZero();
// Search for the K nearest neighbours
- kdtree->nearestKSearch(query_point, k_correspondences_, nn_indecies, nn_dist_sq);
+ kdtree->nearestKSearch(query_point, k_correspondences_, nn_indices, nn_dist_sq);
// Find the covariance matrix
for (int j = 0; j < k_correspondences_; j++) {
- const PointT& pt = (*cloud)[nn_indecies[j]];
+ const PointT& pt = (*cloud)[nn_indices[j]];
mean[0] += pt.x;
mean[1] += pt.y;
}
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
void
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::computeRDerivative(
- const Vector6d& x, const Eigen::Matrix3d& R, Vector6d& g) const
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::computeRDerivative(
+ const Vector6d& x, const Eigen::Matrix3d& dCost_dR_T, Vector6d& g) const
{
Eigen::Matrix3d dR_dPhi;
Eigen::Matrix3d dR_dTheta;
dR_dPsi(1, 2) = sphi * spsi + cphi * cpsi * stheta;
dR_dPsi(2, 2) = 0.;
- g[3] = matricesInnerProd(dR_dPhi, R);
- g[4] = matricesInnerProd(dR_dTheta, R);
- g[5] = matricesInnerProd(dR_dPsi, R);
+ g[3] = matricesInnerProd(dR_dPhi, dCost_dR_T);
+ g[4] = matricesInnerProd(dR_dTheta, dCost_dR_T);
+ g[5] = matricesInnerProd(dR_dPsi, dCost_dR_T);
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
void
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::
estimateRigidTransformationBFGS(const PointCloudSource& cloud_src,
const pcl::Indices& indices_src,
const PointCloudTarget& cloud_tgt,
const pcl::Indices& indices_tgt,
- Eigen::Matrix4f& transformation_matrix)
+ Matrix4& transformation_matrix)
{
- if (indices_src.size() < 4) // need at least 4 samples
- {
+ // need at least min_number_correspondences_ samples
+ if (indices_src.size() < min_number_correspondences_) {
PCL_THROW_EXCEPTION(
NotEnoughPointsException,
"[pcl::GeneralizedIterativeClosestPoint::estimateRigidTransformationBFGS] Need "
- "at least 4 points to estimate a transform! Source and target have "
+ "at least "
+ << min_number_correspondences_
+ << " points to estimate a transform! "
+ "Source and target have "
<< indices_src.size() << " points!");
return;
}
tmp_idx_src_ = &indices_src;
tmp_idx_tgt_ = &indices_tgt;
- // Optimize using forward-difference approximation LM
+ // Optimize using BFGS
OptimizationFunctorWithIndices functor(this);
BFGS<OptimizationFunctorWithIndices> bfgs(functor);
bfgs.parameters.sigma = 0.01;
"solver didn't converge!");
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
inline double
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::
OptimizationFunctorWithIndices::operator()(const Vector6d& x)
{
- Eigen::Matrix4f transformation_matrix = gicp_->base_transformation_;
+ Matrix4 transformation_matrix = gicp_->base_transformation_;
gicp_->applyState(transformation_matrix, x);
double f = 0;
int m = static_cast<int>(gicp_->tmp_idx_src_->size());
// The last coordinate, p_tgt[3] is guaranteed to be set to 1.0 in registration.hpp
Vector4fMapConst p_tgt =
(*gicp_->tmp_tgt_)[(*gicp_->tmp_idx_tgt_)[i]].getVector4fMap();
- Eigen::Vector4f pp(transformation_matrix * p_src);
+ Eigen::Vector4f p_trans_src(transformation_matrix.template cast<float>() * p_src);
// Estimate the distance (cost function)
// The last coordinate is still guaranteed to be set to 1.0
- Eigen::Vector3d res(pp[0] - p_tgt[0], pp[1] - p_tgt[1], pp[2] - p_tgt[2]);
- Eigen::Vector3d temp(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * res);
- // increment= res'*temp/num_matches = temp'*M*temp/num_matches (we postpone
+ // The d here is the negative of the d in the paper
+ Eigen::Vector3d d(p_trans_src[0] - p_tgt[0],
+ p_trans_src[1] - p_tgt[1],
+ p_trans_src[2] - p_tgt[2]);
+ Eigen::Vector3d Md(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * d);
+ // increment= d'*Md/num_matches = d'*M*d/num_matches (we postpone
// 1/num_matches after the loop closes)
- f += double(res.transpose() * temp);
+ f += double(d.transpose() * Md);
}
return f / m;
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
inline void
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::
OptimizationFunctorWithIndices::df(const Vector6d& x, Vector6d& g)
{
- Eigen::Matrix4f transformation_matrix = gicp_->base_transformation_;
+ Matrix4 transformation_matrix = gicp_->base_transformation_;
gicp_->applyState(transformation_matrix, x);
// Zero out g
g.setZero();
// Eigen::Vector3d g_t = g.head<3> ();
- Eigen::Matrix3d R = Eigen::Matrix3d::Zero();
+ // the transpose of the derivative of the cost function w.r.t rotation matrix
+ Eigen::Matrix3d dCost_dR_T = Eigen::Matrix3d::Zero();
int m = static_cast<int>(gicp_->tmp_idx_src_->size());
for (int i = 0; i < m; ++i) {
// The last coordinate, p_src[3] is guaranteed to be set to 1.0 in registration.hpp
Vector4fMapConst p_tgt =
(*gicp_->tmp_tgt_)[(*gicp_->tmp_idx_tgt_)[i]].getVector4fMap();
- Eigen::Vector4f pp(transformation_matrix * p_src);
+ Eigen::Vector4f p_trans_src(transformation_matrix.template cast<float>() * p_src);
// The last coordinate is still guaranteed to be set to 1.0
- Eigen::Vector3d res(pp[0] - p_tgt[0], pp[1] - p_tgt[1], pp[2] - p_tgt[2]);
- // temp = M*res
- Eigen::Vector3d temp(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * res);
+ // The d here is the negative of the d in the paper
+ Eigen::Vector3d d(p_trans_src[0] - p_tgt[0],
+ p_trans_src[1] - p_tgt[1],
+ p_trans_src[2] - p_tgt[2]);
+ // Md = M*d
+ Eigen::Vector3d Md(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * d);
// Increment translation gradient
- // g.head<3> ()+= 2*M*res/num_matches (we postpone 2/num_matches after the loop
+ // g.head<3> ()+= 2*M*d/num_matches (we postpone 2/num_matches after the loop
// closes)
- g.head<3>() += temp;
+ g.head<3>() += Md;
// Increment rotation gradient
- pp = gicp_->base_transformation_ * p_src;
- Eigen::Vector3d p_src3(pp[0], pp[1], pp[2]);
- R += p_src3 * temp.transpose();
+ p_trans_src = gicp_->base_transformation_.template cast<float>() * p_src;
+ Eigen::Vector3d p_base_src(p_trans_src[0], p_trans_src[1], p_trans_src[2]);
+ dCost_dR_T += p_base_src * Md.transpose();
}
g.head<3>() *= 2.0 / m;
- R *= 2.0 / m;
- gicp_->computeRDerivative(x, R, g);
+ dCost_dR_T *= 2.0 / m;
+ gicp_->computeRDerivative(x, dCost_dR_T, g);
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
inline void
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::
OptimizationFunctorWithIndices::fdf(const Vector6d& x, double& f, Vector6d& g)
{
- Eigen::Matrix4f transformation_matrix = gicp_->base_transformation_;
+ Matrix4 transformation_matrix = gicp_->base_transformation_;
gicp_->applyState(transformation_matrix, x);
f = 0;
g.setZero();
- Eigen::Matrix3d R = Eigen::Matrix3d::Zero();
+ // the transpose of the derivative of the cost function w.r.t rotation matrix
+ Eigen::Matrix3d dCost_dR_T = Eigen::Matrix3d::Zero();
const int m = static_cast<int>(gicp_->tmp_idx_src_->size());
for (int i = 0; i < m; ++i) {
// The last coordinate, p_src[3] is guaranteed to be set to 1.0 in registration.hpp
// The last coordinate, p_tgt[3] is guaranteed to be set to 1.0 in registration.hpp
Vector4fMapConst p_tgt =
(*gicp_->tmp_tgt_)[(*gicp_->tmp_idx_tgt_)[i]].getVector4fMap();
- Eigen::Vector4f pp(transformation_matrix * p_src);
+ Eigen::Vector4f p_trans_src(transformation_matrix.template cast<float>() * p_src);
// The last coordinate is still guaranteed to be set to 1.0
- Eigen::Vector3d res(pp[0] - p_tgt[0], pp[1] - p_tgt[1], pp[2] - p_tgt[2]);
- // temp = M*res
- Eigen::Vector3d temp(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * res);
+ // The d here is the negative of the d in the paper
+ Eigen::Vector3d d(p_trans_src[0] - p_tgt[0],
+ p_trans_src[1] - p_tgt[1],
+ p_trans_src[2] - p_tgt[2]);
+ // Md = M*d
+ Eigen::Vector3d Md(gicp_->mahalanobis((*gicp_->tmp_idx_src_)[i]) * d);
// Increment total error
- f += double(res.transpose() * temp);
+ f += double(d.transpose() * Md);
// Increment translation gradient
- // g.head<3> ()+= 2*M*res/num_matches (we postpone 2/num_matches after the loop
+ // g.head<3> ()+= 2*M*d/num_matches (we postpone 2/num_matches after the loop
// closes)
- g.head<3>() += temp;
- pp = gicp_->base_transformation_ * p_src;
- Eigen::Vector3d p_src3(pp[0], pp[1], pp[2]);
+ g.head<3>() += Md;
+ p_trans_src = gicp_->base_transformation_.template cast<float>() * p_src;
+ Eigen::Vector3d p_base_src(p_trans_src[0], p_trans_src[1], p_trans_src[2]);
// Increment rotation gradient
- R += p_src3 * temp.transpose();
+ dCost_dR_T += p_base_src * Md.transpose();
}
f /= double(m);
g.head<3>() *= double(2.0 / m);
- R *= 2.0 / m;
- gicp_->computeRDerivative(x, R, g);
+ dCost_dR_T *= 2.0 / m;
+ gicp_->computeRDerivative(x, dCost_dR_T, g);
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
inline BFGSSpace::Status
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::
OptimizationFunctorWithIndices::checkGradient(const Vector6d& g)
{
auto translation_epsilon = gicp_->translation_gradient_tolerance_;
return BFGSSpace::Running;
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
inline void
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::computeTransformation(
- PointCloudSource& output, const Eigen::Matrix4f& guess)
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::
+ computeTransformation(PointCloudSource& output, const Matrix4& guess)
{
- pcl::IterativeClosestPoint<PointSource, PointTarget>::initComputeReciprocal();
+ pcl::IterativeClosestPoint<PointSource, PointTarget, Scalar>::initComputeReciprocal();
// Difference between consecutive transforms
double delta = 0;
- // Get the size of the target
+ // Get the size of the source point cloud
const std::size_t N = indices_->size();
// Set the mahalanobis matrices to identity
mahalanobis_.resize(N, Eigen::Matrix3d::Identity());
computeCovariances<PointSource>(input_, tree_reciprocal_, *input_covariances_);
}
- base_transformation_ = Eigen::Matrix4f::Identity();
+ base_transformation_ = Matrix4::Identity();
nr_iterations_ = 0;
converged_ = false;
double dist_threshold = corr_dist_threshold_ * corr_dist_threshold_;
for (std::size_t i = 0; i < N; i++) {
PointSource query = output[i];
- query.getVector4fMap() = transformation_ * query.getVector4fMap();
+ query.getVector4fMap() =
+ transformation_.template cast<float>() * query.getVector4fMap();
if (!searchForNeighbors(query, nn_indices, nn_dists)) {
PCL_ERROR("[pcl::%s::computeTransformation] Unable to find a nearest neighbor "
break;
}
nr_iterations_++;
+
+ if (update_visualizer_ != nullptr) {
+ PointCloudSourcePtr input_transformed(new PointCloudSource);
+ pcl::transformPointCloud(output, *input_transformed, transformation_);
+ update_visualizer_(*input_transformed, source_indices, *target_, target_indices);
+ }
+
// Check for convergence
if (nr_iterations_ >= max_iterations_ || delta < 1) {
converged_ = true;
}
final_transformation_ = previous_transformation_ * guess;
+ PCL_DEBUG("Transformation "
+ "is:\n\t%5f\t%5f\t%5f\t%5f\n\t%5f\t%5f\t%5f\t%5f\n\t%5f\t%5f\t%5f\t%5f\n\t%"
+ "5f\t%5f\t%5f\t%5f\n",
+ final_transformation_(0, 0),
+ final_transformation_(0, 1),
+ final_transformation_(0, 2),
+ final_transformation_(0, 3),
+ final_transformation_(1, 0),
+ final_transformation_(1, 1),
+ final_transformation_(1, 2),
+ final_transformation_(1, 3),
+ final_transformation_(2, 0),
+ final_transformation_(2, 1),
+ final_transformation_(2, 2),
+ final_transformation_(2, 3),
+ final_transformation_(3, 0),
+ final_transformation_(3, 1),
+ final_transformation_(3, 2),
+ final_transformation_(3, 3));
+
// Transform the point cloud
pcl::transformPointCloud(*input_, output, final_transformation_);
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
void
-GeneralizedIterativeClosestPoint<PointSource, PointTarget>::applyState(
- Eigen::Matrix4f& t, const Vector6d& x) const
+GeneralizedIterativeClosestPoint<PointSource, PointTarget, Scalar>::applyState(
+ Matrix4& t, const Vector6d& x) const
{
// Z Y X euler angles convention
- Eigen::Matrix3f R;
- R = Eigen::AngleAxisf(static_cast<float>(x[5]), Eigen::Vector3f::UnitZ()) *
- Eigen::AngleAxisf(static_cast<float>(x[4]), Eigen::Vector3f::UnitY()) *
- Eigen::AngleAxisf(static_cast<float>(x[3]), Eigen::Vector3f::UnitX());
- t.topLeftCorner<3, 3>().matrix() = R * t.topLeftCorner<3, 3>().matrix();
- Eigen::Vector4f T(static_cast<float>(x[0]),
- static_cast<float>(x[1]),
- static_cast<float>(x[2]),
- 0.0f);
- t.col(3) += T;
+ Matrix3 R = (AngleAxis(static_cast<Scalar>(x[5]), Vector3::UnitZ()) *
+ AngleAxis(static_cast<Scalar>(x[4]), Vector3::UnitY()) *
+ AngleAxis(static_cast<Scalar>(x[3]), Vector3::UnitX()))
+ .toRotationMatrix();
+ Matrix4 T = Matrix4::Identity();
+ T.template block<3, 3>(0, 0) = R;
+ T.template block<3, 1>(0, 3) = Vector3(
+ static_cast<Scalar>(x[0]), static_cast<Scalar>(x[1]), static_cast<Scalar>(x[2]));
+ t = T * t;
}
} // namespace pcl
#include <pcl/registration/transformation_estimation_3point.h>
#include <pcl/sample_consensus/sac_model_plane.h>
+#include <limits>
+
///////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
inline float
int nr_threads)
{
const float max_dist_sqr = max_dist * max_dist;
- const std::size_t s = cloud.size();
+ const std::size_t s = cloud->size();
pcl::search::KdTree<PointT> tree;
tree.setInputCloud(cloud);
, nr_threads_(1)
, approx_overlap_(0.5f)
, delta_(1.f)
-, score_threshold_(FLT_MAX)
+, score_threshold_(std::numeric_limits<float>::max())
, nr_samples_(0)
, max_norm_diff_(90.f)
, max_runtime_(0)
-, fitness_score_(FLT_MAX)
+, fitness_score_(std::numeric_limits<float>::max())
, diameter_()
, max_base_diameter_sqr_()
, use_normals_(false)
}
// set further parameter
- if (score_threshold_ == FLT_MAX)
+ if (score_threshold_ == std::numeric_limits<float>::max())
score_threshold_ = 1.f - approx_overlap_;
if (max_iterations_ < 4)
max_iterations_ = 4;
if (max_runtime_ < 1)
- max_runtime_ = INT_MAX;
+ max_runtime_ = std::numeric_limits<int>::max();
// calculate internal parameters based on the the estimated point density
max_pair_diff_ = delta_ * 2.f;
max_inlier_dist_sqr_ = powf(delta_ * 2.f, 2.f);
// reset fitness_score
- fitness_score_ = FLT_MAX;
+ fitness_score_ = std::numeric_limits<float>::max();
return (true);
}
pcl::SampleConsensusModelPlane<PointTarget> plane(target_);
plane.setIndices(target_indices_);
Eigen::Vector4f centre_pt;
- float nearest_to_plane = FLT_MAX;
+ float nearest_to_plane = std::numeric_limits<float>::max();
// repeat base search until valid quadruple was found or ransac_iterations_ number of
// tries were unsuccessful
}
// check if at least one point fulfilled the conditions
- if (nearest_to_plane != FLT_MAX) {
+ if (nearest_to_plane != std::numeric_limits<float>::max()) {
// order points to build largest quadrangle and calcuate intersection ratios of
// diagonals
setupBase(base_indices, ratio);
pcl::registration::FPCSInitialAlignment<PointSource, PointTarget, NormalT, Scalar>::
setupBase(pcl::Indices& base_indices, float (&ratio)[2])
{
- float best_t = FLT_MAX;
+ float best_t = std::numeric_limits<float>::max();
const pcl::Indices copy(base_indices.begin(), base_indices.end());
pcl::Indices temp(base_indices.begin(), base_indices.end());
// point cloud
PointCloudSourcePtr cloud_e(new PointCloudSource);
cloud_e->resize(pairs_a.size() * 2);
- PointCloudSourceIterator it_pt = cloud_e->begin();
+ auto it_pt = cloud_e->begin();
for (const auto& pair : pairs_a) {
const PointSource* pt1 = &((*input_)[pair.index_match]);
const PointSource* pt2 = &((*input_)[pair.index_query]);
MatchingCandidates& candidates)
{
candidates.resize(1);
- float fitness_score = FLT_MAX;
+ float fitness_score = std::numeric_limits<float>::max();
// loop over all Candidate matches
for (auto& match : matches) {
it_base++, it_match_orig++) {
float dist_sqr_1 =
pcl::squaredEuclideanDistance((*target_)[*it_base], centre_pt_base);
- float best_diff_sqr = FLT_MAX;
+ float best_diff_sqr = std::numeric_limits<float>::max();
int best_index = -1;
for (const auto& match_index : copy) {
float inlier_score_temp = 0;
pcl::Indices ids;
std::vector<float> dists_sqr;
- PointCloudSourceIterator it = source_transformed.begin();
+ auto it = source_transformed.begin();
for (std::size_t i = 0; i < nr_points; it++, i++) {
// search for nearest point using kd tree search
// get best fitness_score over all tries
int nr_candidates = static_cast<int>(candidates.size());
int best_index = -1;
- float best_score = FLT_MAX;
+ float best_score = std::numeric_limits<float>::max();
for (int i = 0; i < nr_candidates; i++) {
const float& fitness_score = candidates[i][0].fitness_score;
if (fitness_score < best_score) {
#ifndef PCL_REGISTRATION_IMPL_IA_KFPCS_H_
#define PCL_REGISTRATION_IMPL_IA_KFPCS_H_
+#include <limits>
+
namespace pcl {
namespace registration {
Eigen::Matrix4f transformation_temp;
pcl::Correspondences correspondences_temp;
float fitness_score =
- FLT_MAX; // reset to FLT_MAX to accept all candidates and not only best
+ std::numeric_limits<float>::max(); // reset to std::numeric_limits<float>::max()
+ // to accept all candidates and not only best
// determine corresondences between base and match according to their distance to
// centroid
// residual costs based on mse
pcl::Indices ids;
std::vector<float> dists_sqr;
- for (PointCloudSourceIterator it = source_transformed.begin(),
- it_e = source_transformed.end();
- it != it_e;
- ++it) {
+ for (const auto& source : source_transformed) {
// search for nearest point using kd tree search
- tree_->nearestKSearch(*it, 1, ids, dists_sqr);
+ tree_->nearestKSearch(source, 1, ids, dists_sqr);
score_a += (dists_sqr[0] < max_inlier_dist_sqr_ ? dists_sqr[0]
: max_inlier_dist_sqr_); // MSAC
}
// sort according to score value
std::sort(candidates_.begin(), candidates_.end(), by_score());
- // return here if no score was valid, i.e. all scores are FLT_MAX
- if (candidates_[0].fitness_score == FLT_MAX) {
+ // return here if no score was valid, i.e. all scores are
+ // std::numeric_limits<float>::max()
+ if (candidates_[0].fitness_score == std::numeric_limits<float>::max()) {
converged_ = false;
return;
}
candidates.clear();
// loop over all candidates starting from the best one
- for (MatchingCandidates::iterator it_candidate = candidates_.begin(),
- it_e = candidates_.end();
- it_candidate != it_e;
- ++it_candidate) {
+ for (const auto& candidate : candidates_) {
// stop if current candidate has no valid score
- if (it_candidate->fitness_score == FLT_MAX)
+ if (candidate.fitness_score == std::numeric_limits<float>::max())
return;
// check if current candidate is a unique one compared to previous using the
// min_diff threshold
bool unique = true;
- MatchingCandidates::iterator it = candidates.begin(), it_e2 = candidates.end();
- while (unique && it != it_e2) {
+ for (const auto& c2 : candidates) {
Eigen::Matrix4f diff =
- it_candidate->transformation.colPivHouseholderQr().solve(it->transformation);
+ candidate.transformation.colPivHouseholderQr().solve(c2.transformation);
const float angle3d = Eigen::AngleAxisf(diff.block<3, 3>(0, 0)).angle();
const float translation3d = diff.block<3, 1>(0, 3).norm();
unique = angle3d > min_angle3d && translation3d > min_translation3d;
- ++it;
+ if (!unique) {
+ break;
+ }
}
// add candidate to best candidates
if (unique)
- candidates.push_back(*it_candidate);
+ candidates.push_back(candidate);
// stop if n candidates are reached
if (candidates.size() == n)
candidates.clear();
// loop over all candidates starting from the best one
- for (MatchingCandidates::iterator it_candidate = candidates_.begin(),
- it_e = candidates_.end();
- it_candidate != it_e;
- ++it_candidate) {
+ for (const auto& candidate : candidates_) {
// stop if current candidate has score below threshold
- if (it_candidate->fitness_score > t)
+ if (candidate.fitness_score > t)
return;
// check if current candidate is a unique one compared to previous using the
// min_diff threshold
bool unique = true;
- MatchingCandidates::iterator it = candidates.begin(), it_e2 = candidates.end();
- while (unique && it != it_e2) {
+ for (const auto& c2 : candidates) {
Eigen::Matrix4f diff =
- it_candidate->transformation.colPivHouseholderQr().solve(it->transformation);
+ candidate.transformation.colPivHouseholderQr().solve(c2.transformation);
const float angle3d = Eigen::AngleAxisf(diff.block<3, 3>(0, 0)).angle();
const float translation3d = diff.block<3, 1>(0, 3).norm();
unique = angle3d > min_angle3d && translation3d > min_translation3d;
- ++it;
+ if (!unique) {
+ break;
+ }
}
// add candidate to best candidates
if (unique)
- candidates.push_back(*it_candidate);
+ candidates.push_back(candidate);
}
}
Eigen::Matrix3f rot = tr.block<3, 3>(0, 0);
for (std::size_t i = 0; i < input.size(); ++i) {
- const std::uint8_t* data_in = reinterpret_cast<const std::uint8_t*>(&input[i]);
- std::uint8_t* data_out = reinterpret_cast<std::uint8_t*>(&output[i]);
+ const auto* data_in = reinterpret_cast<const std::uint8_t*>(&input[i]);
+ auto* data_out = reinterpret_cast<std::uint8_t*>(&output[i]);
memcpy(&pt[0], data_in + x_idx_offset_, sizeof(float));
memcpy(&pt[1], data_in + y_idx_offset_, sizeof(float));
memcpy(&pt[2], data_in + z_idx_offset_, sizeof(float));
}
else {
for (std::size_t i = 0; i < input.size(); ++i) {
- const std::uint8_t* data_in = reinterpret_cast<const std::uint8_t*>(&input[i]);
- std::uint8_t* data_out = reinterpret_cast<std::uint8_t*>(&output[i]);
+ const auto* data_in = reinterpret_cast<const std::uint8_t*>(&input[i]);
+ auto* data_out = reinterpret_cast<std::uint8_t*>(&output[i]);
memcpy(&pt[0], data_in + x_idx_offset_, sizeof(float));
memcpy(&pt[1], data_in + y_idx_offset_, sizeof(float));
memcpy(&pt[2], data_in + z_idx_offset_, sizeof(float));
*temp_correspondences = *correspondences_;
}
- std::size_t cnt = correspondences_->size();
// Check whether we have enough correspondences
- if (static_cast<int>(cnt) < min_number_correspondences_) {
+ if (correspondences_->size() < min_number_correspondences_) {
PCL_ERROR("[pcl::%s::computeTransformation] Not enough correspondences found. "
"Relax your threshold parameters.\n",
getClassName().c_str());
++nr_iterations_;
// Update the vizualization of icp convergence
- // if (update_visualizer_ != 0)
- // update_visualizer_(output, source_indices_good, *target_, target_indices_good );
+ if (update_visualizer_ != nullptr) {
+ pcl::Indices source_indices_good, target_indices_good;
+ for (const Correspondence& corr : *correspondences_) {
+ source_indices_good.emplace_back(corr.index_query);
+ target_indices_good.emplace_back(corr.index_match);
+ }
+ update_visualizer_(
+ *input_transformed, source_indices_good, *target_, target_indices_good);
+ }
converged_ = static_cast<bool>((*convergence_criteria_));
} while (convergence_criteria_->getConvergenceState() ==
*temp_correspondences = *correspondences_;
}
- int cnt = correspondences_->size();
// Check whether we have enough correspondences
- if (cnt < min_number_correspondences_) {
+ if (correspondences_->size() < min_number_correspondences_) {
PCL_ERROR("[pcl::%s::computeTransformation] Not enough correspondences found. "
"Relax your threshold parameters.\n",
getClassName().c_str());
namespace pcl {
-template <typename PointSource, typename PointTarget>
-NormalDistributionsTransform<PointSource, PointTarget>::NormalDistributionsTransform()
+template <typename PointSource, typename PointTarget, typename Scalar>
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::
+ NormalDistributionsTransform()
: target_cells_()
, resolution_(1.0f)
, step_size_(0.1)
, outlier_ratio_(0.55)
, gauss_d1_()
, gauss_d2_()
-, trans_probability_()
+, trans_likelihood_()
{
reg_name_ = "NormalDistributionsTransform";
max_iterations_ = 35;
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
void
-NormalDistributionsTransform<PointSource, PointTarget>::computeTransformation(
- PointCloudSource& output, const Eigen::Matrix4f& guess)
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::computeTransformation(
+ PointCloudSource& output, const Matrix4& guess)
{
nr_iterations_ = 0;
converged_ = false;
+ if (target_cells_.getCentroids()->empty()) {
+ PCL_ERROR("[%s::computeTransformation] Voxel grid is not searchable!\n",
+ getClassName().c_str());
+ return;
+ }
// Initializes the gaussian fitting parameters (eq. 6.8) [Magnusson 2009]
const double gauss_c1 = 10 * (1 - outlier_ratio_);
-2 * std::log((-std::log(gauss_c1 * std::exp(-0.5) + gauss_c2) - gauss_d3) /
gauss_d1_);
- if (guess != Eigen::Matrix4f::Identity()) {
+ if (guess != Matrix4::Identity()) {
// Initialise final transformation to the guessed one
final_transformation_ = guess;
// Apply guessed transformation prior to search for neighbours
point_jacobian_.block<3, 3>(0, 0).setIdentity();
point_hessian_.setZero();
- Eigen::Transform<float, 3, Eigen::Affine, Eigen::ColMajor> eig_transformation;
+ Eigen::Transform<Scalar, 3, Eigen::Affine, Eigen::ColMajor> eig_transformation;
eig_transformation.matrix() = final_transformation_;
// Convert initial guess matrix to 6 element transformation vector
Eigen::Matrix<double, 6, 1> transform, score_gradient;
- Eigen::Vector3f init_translation = eig_transformation.translation();
- Eigen::Vector3f init_rotation = eig_transformation.rotation().eulerAngles(0, 1, 2);
- transform << init_translation.cast<double>(), init_rotation.cast<double>();
+ Vector3 init_translation = eig_transformation.translation();
+ Vector3 init_rotation = eig_transformation.rotation().eulerAngles(0, 1, 2);
+ transform << init_translation.template cast<double>(),
+ init_rotation.template cast<double>();
Eigen::Matrix<double, 6, 6> hessian;
// Negative for maximization as opposed to minimization
Eigen::Matrix<double, 6, 1> delta = sv.solve(-score_gradient);
- // Calculate step length with guarnteed sufficient decrease [More, Thuente 1994]
+ // Calculate step length with guaranteed sufficient decrease [More, Thuente 1994]
double delta_norm = delta.norm();
if (delta_norm == 0 || std::isnan(delta_norm)) {
- trans_probability_ = score / static_cast<double>(input_->size());
+ trans_likelihood_ = score / static_cast<double>(input_->size());
converged_ = delta_norm == 0;
return;
}
}
}
- // Store transformation probability. The realtive differences within each scan
+ // Store transformation likelihood. The relative differences within each scan
// registration are accurate but the normalization constants need to be modified for
// it to be globally accurate
- trans_probability_ = score / static_cast<double>(input_->size());
+ trans_likelihood_ = score / static_cast<double>(input_->size());
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
double
-NormalDistributionsTransform<PointSource, PointTarget>::computeDerivatives(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::computeDerivatives(
Eigen::Matrix<double, 6, 1>& score_gradient,
Eigen::Matrix<double, 6, 6>& hessian,
const PointCloudSource& trans_cloud,
return score;
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
void
-NormalDistributionsTransform<PointSource, PointTarget>::computeAngleDerivatives(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::computeAngleDerivatives(
const Eigen::Matrix<double, 6, 1>& transform, bool compute_hessian)
{
// Simplified math for near 0 angles
}
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
void
-NormalDistributionsTransform<PointSource, PointTarget>::computePointDerivatives(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::computePointDerivatives(
const Eigen::Vector3d& x, bool compute_hessian)
{
// Calculate first derivative of Transformation Equation 6.17 w.r.t. transform vector.
}
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
double
-NormalDistributionsTransform<PointSource, PointTarget>::updateDerivatives(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::updateDerivatives(
Eigen::Matrix<double, 6, 1>& score_gradient,
Eigen::Matrix<double, 6, 6>& hessian,
const Eigen::Vector3d& x_trans,
{
// e^(-d_2/2 * (x_k - mu_k)^T Sigma_k^-1 (x_k - mu_k)) Equation 6.9 [Magnusson 2009]
double e_x_cov_x = std::exp(-gauss_d2_ * x_trans.dot(c_inv * x_trans) / 2);
- // Calculate probability of transformed points existence, Equation 6.9 [Magnusson
+ // Calculate likelihood of transformed points existence, Equation 6.9 [Magnusson
// 2009]
const double score_inc = -gauss_d1_ * e_x_cov_x;
return score_inc;
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
void
-NormalDistributionsTransform<PointSource, PointTarget>::computeHessian(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::computeHessian(
Eigen::Matrix<double, 6, 6>& hessian, const PointCloudSource& trans_cloud)
{
hessian.setZero();
- // Precompute Angular Derivatives unessisary because only used after regular
+ // Precompute Angular Derivatives unnecessary because only used after regular
// derivative calculation Update hessian for each point, line 17 in Algorithm 2
// [Magnusson 2009]
for (std::size_t idx = 0; idx < input_->size(); idx++) {
// Transformed Point
const auto& x_trans_pt = trans_cloud[idx];
- // Find nieghbors (Radius search has been experimentally faster than direct neighbor
+ // Find neighbors (Radius search has been experimentally faster than direct neighbor
// checking.
std::vector<TargetGridLeafConstPtr> neighborhood;
std::vector<float> distances;
}
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
void
-NormalDistributionsTransform<PointSource, PointTarget>::updateHessian(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::updateHessian(
Eigen::Matrix<double, 6, 6>& hessian,
const Eigen::Vector3d& x_trans,
const Eigen::Matrix3d& c_inv) const
}
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
bool
-NormalDistributionsTransform<PointSource, PointTarget>::updateIntervalMT(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::updateIntervalMT(
double& a_l,
double& f_l,
double& g_l,
return true;
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
double
-NormalDistributionsTransform<PointSource, PointTarget>::trialValueSelectionMT(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::trialValueSelectionMT(
double a_l,
double f_l,
double g_l,
}
}
-template <typename PointSource, typename PointTarget>
+template <typename PointSource, typename PointTarget, typename Scalar>
double
-NormalDistributionsTransform<PointSource, PointTarget>::computeStepLengthMT(
+NormalDistributionsTransform<PointSource, PointTarget, Scalar>::computeStepLengthMT(
const Eigen::Matrix<double, 6, 1>& x,
Eigen::Matrix<double, 6, 1>& step_dir,
double step_init,
// New transformed point cloud
transformPointCloud(*input_, trans_cloud, final_transformation_);
- // Updates score, gradient and hessian. Hessian calculation is unessisary but testing
- // showed that most step calculations use the initial step suggestion and
+ // Updates score, gradient and hessian. Hessian calculation is unnecessary but
+ // testing showed that most step calculations use the initial step suggestion and
// recalculation the reusable portions of the hessian would intail more computation
// time.
score = computeDerivatives(score_gradient, hessian, trans_cloud, x_t, true);
}
// If inner loop was run then hessian needs to be calculated.
- // Hessian is unnessisary for step length determination but gradients are required
+ // Hessian is unnecessary for step length determination but gradients are required
// so derivative and transform data is stored for the next iteration.
if (step_iterations) {
computeHessian(hessian, trans_cloud);
#ifndef PCL_NDT_2D_IMPL_H_
#define PCL_NDT_2D_IMPL_H_
+#include <boost/core/noncopyable.hpp> // for boost::noncopyable
+
#include <Eigen/Eigenvalues> // for SelfAdjointEigenSolver, EigenSolver
#include <cmath>
else if (alpha > M_PI) {
alpha -= (2 * M_PI);
}
- unsigned int alpha_discretized = static_cast<unsigned int>(std::floor(
+ auto alpha_discretized = static_cast<unsigned int>(std::floor(
(alpha + M_PI) / search_method_->getAngleDiscretizationStep()));
accumulator_array[model_reference_index][alpha_discretized]++;
}
PointFeature>::PyramidFeatureHistogramLevel::initializeHistogramLevel()
{
std::size_t total_vector_size = 1;
- for (std::vector<std::size_t>::iterator dim_it = bins_per_dimension.begin();
- dim_it != bins_per_dimension.end();
- ++dim_it)
- total_vector_size *= *dim_it;
+ for (const auto& bin : bins_per_dimension) {
+ total_vector_size *= bin;
+ }
hist.resize(total_vector_size, 0);
}
nr_dimensions = dimension_range_target_.size();
nr_features = input_->size();
float D = 0.0f;
- for (std::vector<std::pair<float, float>>::iterator range_it =
- dimension_range_target_.begin();
- range_it != dimension_range_target_.end();
- ++range_it) {
- float aux = range_it->first - range_it->second;
+ for (const auto& dim : dimension_range_target_) {
+ float aux = dim.first - dim.second;
D += aux * aux;
}
D = std::sqrt(D);
c2[6] += a.x + b.x;
c2[7] += a.y - b.y;
c2[11] += a.z - b.z;
- source_it++;
- target_it++;
+ ++source_it;
+ ++target_it;
}
c1[4] = c1[1];
// Construct the transformation matrix from x
constructTransformationMatrix(
x(0), x(1), x(2), x(3), x(4), x(5), transformation_matrix);
+
+ if (pcl::console::isVerbosityLevelEnabled(pcl::console::L_DEBUG)) {
+ size_t N = 0;
+ double loss = 0.0;
+ source_it.reset();
+ target_it.reset();
+ while (source_it.isValid() && target_it.isValid()) {
+ if (!std::isfinite(source_it->x) || !std::isfinite(source_it->y) ||
+ !std::isfinite(source_it->z) || !std::isfinite(target_it->x) ||
+ !std::isfinite(target_it->y) || !std::isfinite(target_it->z) ||
+ !std::isfinite(target_it->normal_x) || !std::isfinite(target_it->normal_y) ||
+ !std::isfinite(target_it->normal_z)) {
+ ++target_it;
+ ++source_it;
+ continue;
+ }
+ const float& sx = source_it->x;
+ const float& sy = source_it->y;
+ const float& sz = source_it->z;
+ const float& dx = target_it->x;
+ const float& dy = target_it->y;
+ const float& dz = target_it->z;
+ const float& nx = target_it->normal[0];
+ const float& ny = target_it->normal[1];
+ const float& nz = target_it->normal[2];
+ double a = nz * sy - ny * sz;
+ double b = nx * sz - nz * sx;
+ double c = ny * sx - nx * sy;
+ double d = nx * dx + ny * dy + nz * dz - nx * sx - ny * sy - nz * sz;
+ Vector6d Arow;
+ Arow << a, b, c, nx, ny, nz;
+ loss += pow(Arow.transpose() * x - d, 2);
+ ++target_it;
+ ++source_it;
+ ++N;
+ }
+ loss /= N;
+ PCL_DEBUG("[pcl::registration::TransformationEstimationPointToPlaneLLS::"
+ "estimateRigidTransformation] Loss :%.10e\n",
+ loss);
+ }
}
} // namespace registration
tmp_src_ = NULL;
tmp_tgt_ = NULL;
- tmp_idx_src_ = tmp_idx_tgt_ = NULL;
+ tmp_idx_src_ = tmp_idx_tgt_ = nullptr;
}
//////////////////////////////////////////////////////////////////////////////////////////////
transformation_matrix.topLeftCorner(3, 3) = R;
const Eigen::Matrix<Scalar, 3, 1> Rc(R * centroid_src.head(3));
transformation_matrix.block(0, 3, 3, 1) = centroid_tgt.head(3) - Rc;
+
+ if (pcl::console::isVerbosityLevelEnabled(pcl::console::L_DEBUG)) {
+ size_t N = cloud_src_demean.cols();
+ PCL_DEBUG("[pcl::registration::TransformationEstimationSVD::"
+ "getTransformationFromCorrelation] Loss: %.10e\n",
+ (cloud_tgt_demean - R * cloud_src_demean).squaredNorm() / N);
+ }
}
} // namespace registration
IncrementalRegistration();
/** \brief Empty destructor */
- virtual ~IncrementalRegistration() {}
+ virtual ~IncrementalRegistration() = default;
/** \brief Register new point cloud incrementally
* \note You have to set a valid registration object with @ref setRegistration before
};
/** \brief Empty destructor */
- ~JointIterativeClosestPoint() {}
+ ~JointIterativeClosestPoint() override = default;
/** \brief Provide a pointer to the input source
* (e.g., the point cloud that we want to align to the target)
#include <pcl/memory.h>
#include <pcl/pcl_macros.h>
+#include <limits>
+
namespace pcl {
namespace registration {
/** \brief Container for matching candidate consisting of
struct MatchingCandidate {
/** \brief Constructor. */
MatchingCandidate()
- : fitness_score(FLT_MAX), transformation(Eigen::Matrix4f::Identity()){};
+ : fitness_score(std::numeric_limits<float>::max())
+ , transformation(Eigen::Matrix4f::Identity()){};
/** \brief Value constructor. */
MatchingCandidate(float s, const pcl::Correspondences& c, const Eigen::Matrix4f& m)
: fitness_score(s), correspondences(c), transformation(m){};
/** \brief Destructor. */
- ~MatchingCandidate(){};
+ ~MatchingCandidate() = default;
/** \brief Fitness score of current candidate resulting from matching algorithm. */
float fitness_score;
MetaRegistration();
/** \brief Empty destructor */
- virtual ~MetaRegistration(){};
+ virtual ~MetaRegistration() = default;
/** \brief Register new point cloud
* \note You have to set a valid registration object with \ref setRegistration before
#include <unsupported/Eigen/NonLinearOptimization>
namespace pcl {
-/** \brief A 3D Normal Distribution Transform registration implementation for point
- * cloud data. \note For more information please see <b>Magnusson, M. (2009). The
- * Three-Dimensional Normal-Distributions Transform — an Efficient Representation for
- * Registration, Surface Analysis, and Loop Detection. PhD thesis, Orebro University.
- * Orebro Studies in Technology 36.</b>, <b>More, J., and Thuente, D. (1994). Line
- * Search Algorithm with Guaranteed Sufficient Decrease In ACM Transactions on
- * Mathematical Software.</b> and Sun, W. and Yuan, Y, (2006) Optimization Theory and
- * Methods: Nonlinear Programming. 89-100 \note Math refactored by Todor Stoyanov.
+/** \brief A 3D Normal Distribution Transform registration implementation for
+ * point cloud data.
+ * \note For more information please see <b>Magnusson, M. (2009). The
+ * Three-Dimensional Normal-Distributions Transform — an Efficient Representation
+ * for Registration, Surface Analysis, and Loop Detection. PhD thesis, Orebro
+ * University. Orebro Studies in Technology 36.</b>, <b>More, J., and Thuente,
+ * D. (1994). Line Search Algorithm with Guaranteed Sufficient Decrease In ACM
+ * Transactions on Mathematical Software.</b> and Sun, W. and Yuan, Y, (2006)
+ * Optimization Theory and Methods: Nonlinear Programming. 89-100
+ * \note Math refactored by Todor Stoyanov.
* \author Brian Okorn (Space and Naval Warfare Systems Center Pacific)
*/
-template <typename PointSource, typename PointTarget>
-class NormalDistributionsTransform : public Registration<PointSource, PointTarget> {
+template <typename PointSource, typename PointTarget, typename Scalar = float>
+class NormalDistributionsTransform
+: public Registration<PointSource, PointTarget, Scalar> {
protected:
using PointCloudSource =
- typename Registration<PointSource, PointTarget>::PointCloudSource;
+ typename Registration<PointSource, PointTarget, Scalar>::PointCloudSource;
using PointCloudSourcePtr = typename PointCloudSource::Ptr;
using PointCloudSourceConstPtr = typename PointCloudSource::ConstPtr;
using PointCloudTarget =
- typename Registration<PointSource, PointTarget>::PointCloudTarget;
+ typename Registration<PointSource, PointTarget, Scalar>::PointCloudTarget;
using PointCloudTargetPtr = typename PointCloudTarget::Ptr;
using PointCloudTargetConstPtr = typename PointCloudTarget::ConstPtr;
using PointIndicesPtr = PointIndices::Ptr;
using PointIndicesConstPtr = PointIndices::ConstPtr;
- /** \brief Typename of searchable voxel grid containing mean and covariance. */
+ /** \brief Typename of searchable voxel grid containing mean and
+ * covariance. */
using TargetGrid = VoxelGridCovariance<PointTarget>;
/** \brief Typename of pointer to searchable voxel grid. */
using TargetGridPtr = TargetGrid*;
using TargetGridLeafConstPtr = typename TargetGrid::LeafConstPtr;
public:
- using Ptr = shared_ptr<NormalDistributionsTransform<PointSource, PointTarget>>;
+ using Ptr =
+ shared_ptr<NormalDistributionsTransform<PointSource, PointTarget, Scalar>>;
using ConstPtr =
- shared_ptr<const NormalDistributionsTransform<PointSource, PointTarget>>;
+ shared_ptr<const NormalDistributionsTransform<PointSource, PointTarget, Scalar>>;
+ using Vector3 = typename Eigen::Matrix<Scalar, 3, 1>;
+ using Matrix4 = typename Registration<PointSource, PointTarget, Scalar>::Matrix4;
+ using Affine3 = typename Eigen::Transform<Scalar, 3, Eigen::Affine>;
- /** \brief Constructor.
- * Sets \ref outlier_ratio_ to 0.35, \ref step_size_ to 0.05 and \ref resolution_
- * to 1.0
+ /** \brief Constructor. Sets \ref outlier_ratio_ to 0.55, \ref step_size_ to
+ * 0.1 and \ref resolution_ to 1.0
*/
NormalDistributionsTransform();
/** \brief Empty destructor */
- ~NormalDistributionsTransform() {}
+ ~NormalDistributionsTransform() override = default;
- /** \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
+ /** \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
*/
inline void
setInputTarget(const PointCloudTargetConstPtr& cloud) override
{
- Registration<PointSource, PointTarget>::setInputTarget(cloud);
+ Registration<PointSource, PointTarget, Scalar>::setInputTarget(cloud);
init();
}
inline void
setResolution(float resolution)
{
- // Prevents unnessary voxel initiations
+ // Prevents unnecessary voxel initiations
if (resolution_ != resolution) {
resolution_ = resolution;
if (input_) {
}
}
+ /** \brief Set the minimum number of points required for a cell to be used (must be 3
+ * or greater for covariance calculation). Calls the function of the underlying
+ * VoxelGridCovariance. This function must be called before `setInputTarget` and
+ * `setResolution`. \param[in] min_points_per_voxel the minimum number of points
+ * required for a voxel to be used
+ */
+ inline void
+ setMinPointPerVoxel(unsigned int min_points_per_voxel)
+ {
+ target_cells_.setMinPointPerVoxel(min_points_per_voxel);
+ }
+
/** \brief Get voxel grid resolution.
* \return side length of voxels
*/
outlier_ratio_ = outlier_ratio;
}
+ /** \brief Get the registration alignment likelihood.
+ * \return transformation likelihood
+ */
+ inline double
+ getTransformationLikelihood() const
+ {
+ return trans_likelihood_;
+ }
+
/** \brief Get the registration alignment probability.
* \return transformation probability
*/
+ PCL_DEPRECATED(1,
+ 16,
+ "The method `getTransformationProbability` has been renamed to "
+ "`getTransformationLikelihood`.")
inline double
getTransformationProbability() const
{
- return trans_probability_;
+ return trans_likelihood_;
}
/** \brief Get the number of iterations required to calculate alignment.
/** \brief Convert 6 element transformation vector to affine transformation.
* \param[in] x transformation vector of the form [x, y, z, roll, pitch, yaw]
- * \param[out] trans affine transform corresponding to given transfomation vector
+ * \param[out] trans affine transform corresponding to given transformation
+ * vector
*/
static void
- convertTransform(const Eigen::Matrix<double, 6, 1>& x, Eigen::Affine3f& trans)
+ convertTransform(const Eigen::Matrix<double, 6, 1>& x, Affine3& trans)
{
- trans = Eigen::Translation<float, 3>(x.head<3>().cast<float>()) *
- Eigen::AngleAxis<float>(float(x(3)), Eigen::Vector3f::UnitX()) *
- Eigen::AngleAxis<float>(float(x(4)), Eigen::Vector3f::UnitY()) *
- Eigen::AngleAxis<float>(float(x(5)), Eigen::Vector3f::UnitZ());
+ trans = Eigen::Translation<Scalar, 3>(x.head<3>().cast<Scalar>()) *
+ Eigen::AngleAxis<Scalar>(Scalar(x(3)), Vector3::UnitX()) *
+ Eigen::AngleAxis<Scalar>(Scalar(x(4)), Vector3::UnitY()) *
+ Eigen::AngleAxis<Scalar>(Scalar(x(5)), Vector3::UnitZ());
}
/** \brief Convert 6 element transformation vector to transformation matrix.
* \param[in] x transformation vector of the form [x, y, z, roll, pitch, yaw]
- * \param[out] trans 4x4 transformation matrix corresponding to given transfomation
- * vector
+ * \param[out] trans 4x4 transformation matrix corresponding to given
+ * transformation vector
*/
static void
- convertTransform(const Eigen::Matrix<double, 6, 1>& x, Eigen::Matrix4f& trans)
+ convertTransform(const Eigen::Matrix<double, 6, 1>& x, Matrix4& trans)
{
- Eigen::Affine3f _affine;
+ Affine3 _affine;
convertTransform(x, _affine);
trans = _affine.matrix();
}
protected:
- using Registration<PointSource, PointTarget>::reg_name_;
- using Registration<PointSource, PointTarget>::getClassName;
- using Registration<PointSource, PointTarget>::input_;
- using Registration<PointSource, PointTarget>::indices_;
- using Registration<PointSource, PointTarget>::target_;
- using Registration<PointSource, PointTarget>::nr_iterations_;
- using Registration<PointSource, PointTarget>::max_iterations_;
- using Registration<PointSource, PointTarget>::previous_transformation_;
- using Registration<PointSource, PointTarget>::final_transformation_;
- using Registration<PointSource, PointTarget>::transformation_;
- using Registration<PointSource, PointTarget>::transformation_epsilon_;
- using Registration<PointSource, PointTarget>::transformation_rotation_epsilon_;
- using Registration<PointSource, PointTarget>::converged_;
- using Registration<PointSource, PointTarget>::corr_dist_threshold_;
- using Registration<PointSource, PointTarget>::inlier_threshold_;
-
- using Registration<PointSource, PointTarget>::update_visualizer_;
-
- /** \brief Estimate the transformation and returns the transformed source (input) as
- * output. \param[out] output the resultant input transformed point cloud dataset
+ using Registration<PointSource, PointTarget, Scalar>::reg_name_;
+ using Registration<PointSource, PointTarget, Scalar>::getClassName;
+ using Registration<PointSource, PointTarget, Scalar>::input_;
+ using Registration<PointSource, PointTarget, Scalar>::indices_;
+ using Registration<PointSource, PointTarget, Scalar>::target_;
+ using Registration<PointSource, PointTarget, Scalar>::nr_iterations_;
+ using Registration<PointSource, PointTarget, Scalar>::max_iterations_;
+ using Registration<PointSource, PointTarget, Scalar>::previous_transformation_;
+ using Registration<PointSource, PointTarget, Scalar>::final_transformation_;
+ using Registration<PointSource, PointTarget, Scalar>::transformation_;
+ using Registration<PointSource, PointTarget, Scalar>::transformation_epsilon_;
+ using Registration<PointSource, PointTarget, Scalar>::
+ transformation_rotation_epsilon_;
+ using Registration<PointSource, PointTarget, Scalar>::converged_;
+ using Registration<PointSource, PointTarget, Scalar>::corr_dist_threshold_;
+ using Registration<PointSource, PointTarget, Scalar>::inlier_threshold_;
+
+ using Registration<PointSource, PointTarget, Scalar>::update_visualizer_;
+
+ /** \brief Estimate the transformation and returns the transformed source
+ * (input) as output.
+ * \param[out] output the resultant input transformed point cloud dataset
*/
virtual void
computeTransformation(PointCloudSource& output)
{
- computeTransformation(output, Eigen::Matrix4f::Identity());
+ computeTransformation(output, Matrix4::Identity());
}
- /** \brief Estimate the transformation and returns the transformed source (input) as
- * output. \param[out] output the resultant input transformed point cloud dataset
+ /** \brief Estimate the transformation and returns the transformed source
+ * (input) as output.
+ * \param[out] output the resultant input transformed point cloud dataset
* \param[in] guess the initial gross estimation of the transformation
*/
void
- computeTransformation(PointCloudSource& output,
- const Eigen::Matrix4f& guess) override;
+ computeTransformation(PointCloudSource& output, const Matrix4& guess) override;
/** \brief Initiate covariance voxel structure. */
void inline init()
target_cells_.filter(true);
}
- /** \brief Compute derivatives of probability function w.r.t. the transformation
- * vector. \note Equation 6.10, 6.12 and 6.13 [Magnusson 2009]. \param[out]
- * score_gradient the gradient vector of the probability function w.r.t. the
- * transformation vector \param[out] hessian the hessian matrix of the probability
- * function w.r.t. the transformation vector \param[in] trans_cloud transformed point
- * cloud \param[in] transform the current transform vector \param[in] compute_hessian
- * flag to calculate hessian, unnessissary for step calculation.
+ /** \brief Compute derivatives of likelihood function w.r.t. the
+ * transformation vector.
+ * \note Equation 6.10, 6.12 and 6.13 [Magnusson 2009].
+ * \param[out] score_gradient the gradient vector of the likelihood function
+ * w.r.t. the transformation vector
+ * \param[out] hessian the hessian matrix of the likelihood function
+ * w.r.t. the transformation vector
+ * \param[in] trans_cloud transformed point cloud
+ * \param[in] transform the current transform vector
+ * \param[in] compute_hessian flag to calculate hessian, unnecessary for step
+ * calculation.
*/
double
computeDerivatives(Eigen::Matrix<double, 6, 1>& score_gradient,
const Eigen::Matrix<double, 6, 1>& transform,
bool compute_hessian = true);
- /** \brief Compute individual point contirbutions to derivatives of probability
- * function w.r.t. the transformation vector. \note Equation 6.10, 6.12 and 6.13
- * [Magnusson 2009]. \param[in,out] score_gradient the gradient vector of the
- * probability function w.r.t. the transformation vector \param[in,out] hessian the
- * hessian matrix of the probability function w.r.t. the transformation vector
- * \param[in] x_trans transformed point minus mean of occupied covariance voxel
+ /** \brief Compute individual point contributions to derivatives of
+ * likelihood function w.r.t. the transformation vector.
+ * \note Equation 6.10, 6.12 and 6.13 [Magnusson 2009].
+ * \param[in,out] score_gradient the gradient vector of the likelihood
+ * function w.r.t. the transformation vector
+ * \param[in,out] hessian the hessian matrix of the likelihood function
+ * w.r.t. the transformation vector
+ * \param[in] x_trans transformed point minus mean of occupied covariance
+ * voxel
* \param[in] c_inv covariance of occupied covariance voxel
- * \param[in] compute_hessian flag to calculate hessian, unnessissary for step
+ * \param[in] compute_hessian flag to calculate hessian, unnecessary for step
* calculation.
*/
double
const Eigen::Matrix3d& c_inv,
bool compute_hessian = true) const;
- /** \brief Precompute anglular components of derivatives.
+ /** \brief Precompute angular components of derivatives.
* \note Equation 6.19 and 6.21 [Magnusson 2009].
* \param[in] transform the current transform vector
- * \param[in] compute_hessian flag to calculate hessian, unnessissary for step
+ * \param[in] compute_hessian flag to calculate hessian, unnecessary for step
* calculation.
*/
void
/** \brief Compute point derivatives.
* \note Equation 6.18-21 [Magnusson 2009].
* \param[in] x point from the input cloud
- * \param[in] compute_hessian flag to calculate hessian, unnessissary for step
+ * \param[in] compute_hessian flag to calculate hessian, unnecessary for step
* calculation.
*/
void
computePointDerivatives(const Eigen::Vector3d& x, bool compute_hessian = true);
- /** \brief Compute hessian of probability function w.r.t. the transformation vector.
+ /** \brief Compute hessian of likelihood function w.r.t. the transformation
+ * vector.
* \note Equation 6.13 [Magnusson 2009].
- * \param[out] hessian the hessian matrix of the probability function w.r.t. the
- * transformation vector \param[in] trans_cloud transformed point cloud
+ * \param[out] hessian the hessian matrix of the likelihood function
+ * w.r.t. the transformation vector
+ * \param[in] trans_cloud transformed point cloud
*/
void
computeHessian(Eigen::Matrix<double, 6, 6>& hessian,
const PointCloudSource& trans_cloud);
- /** \brief Compute hessian of probability function w.r.t. the transformation vector.
+ /** \brief Compute hessian of likelihood function w.r.t. the transformation
+ * vector.
* \note Equation 6.13 [Magnusson 2009].
- * \param[out] hessian the hessian matrix of the probability function w.r.t. the
- * transformation vector \param[in] trans_cloud transformed point cloud \param[in]
- * transform the current transform vector
+ * \param[out] hessian the hessian matrix of the likelihood function
+ * w.r.t. the transformation vector
+ * \param[in] trans_cloud transformed point cloud
+ * \param[in] transform the current transform vector
*/
PCL_DEPRECATED(1, 15, "Parameter `transform` is not required")
void
computeHessian(hessian, trans_cloud);
}
- /** \brief Compute individual point contirbutions to hessian of probability function
- * w.r.t. the transformation vector. \note Equation 6.13 [Magnusson 2009].
- * \param[in,out] hessian the hessian matrix of the probability function w.r.t. the
- * transformation vector \param[in] x_trans transformed point minus mean of occupied
- * covariance voxel \param[in] c_inv covariance of occupied covariance voxel
+ /** \brief Compute individual point contributions to hessian of likelihood
+ * function w.r.t. the transformation vector.
+ * \note Equation 6.13 [Magnusson 2009].
+ * \param[in,out] hessian the hessian matrix of the likelihood function
+ * w.r.t. the transformation vector
+ * \param[in] x_trans transformed point minus mean of occupied covariance
+ * voxel
+ * \param[in] c_inv covariance of occupied covariance voxel
*/
void
updateHessian(Eigen::Matrix<double, 6, 6>& hessian,
const Eigen::Vector3d& x_trans,
const Eigen::Matrix3d& c_inv) const;
- /** \brief Compute line search step length and update transform and probability
- * derivatives using More-Thuente method. \note Search Algorithm [More, Thuente 1994]
- * \param[in] transform initial transformation vector, \f$ x \f$ in Equation 1.3
- * (Moore, Thuente 1994) and \f$ \vec{p} \f$ in Algorithm 2 [Magnusson 2009]
- * \param[in] step_dir descent direction, \f$ p \f$ in Equation 1.3 (Moore, Thuente
- * 1994) and \f$ \delta \vec{p} \f$ normalized in Algorithm 2 [Magnusson 2009]
+ /** \brief Compute line search step length and update transform and
+ * likelihood derivatives using More-Thuente method.
+ * \note Search Algorithm [More, Thuente 1994]
+ * \param[in] transform initial transformation vector, \f$ x \f$ in Equation
+ * 1.3 (Moore, Thuente 1994) and \f$ \vec{p} \f$ in Algorithm 2 [Magnusson
+ * 2009]
+ * \param[in] step_dir descent direction, \f$ p \f$ in Equation 1.3 (Moore,
+ * Thuente 1994) and \f$ \delta \vec{p} \f$ normalized in Algorithm 2
+ * [Magnusson 2009]
* \param[in] step_init initial step length estimate, \f$ \alpha_0 \f$ in
- * Moore-Thuente (1994) and the noramal of \f$ \delta \vec{p} \f$ in Algorithm 2
- * [Magnusson 2009] \param[in] step_max maximum step length, \f$ \alpha_max \f$ in
- * Moore-Thuente (1994) \param[in] step_min minimum step length, \f$ \alpha_min \f$ in
- * Moore-Thuente (1994) \param[out] score final score function value, \f$ f(x + \alpha
- * p) \f$ in Equation 1.3 (Moore, Thuente 1994) and \f$ score \f$ in Algorithm 2
- * [Magnusson 2009] \param[in,out] score_gradient gradient of score function w.r.t.
- * transformation vector, \f$ f'(x + \alpha p) \f$ in Moore-Thuente (1994) and \f$
- * \vec{g} \f$ in Algorithm 2 [Magnusson 2009] \param[out] hessian hessian of score
- * function w.r.t. transformation vector, \f$ f''(x + \alpha p) \f$ in Moore-Thuente
- * (1994) and \f$ H \f$ in Algorithm 2 [Magnusson 2009] \param[in,out] trans_cloud
- * transformed point cloud, \f$ X \f$ transformed by \f$ T(\vec{p},\vec{x}) \f$ in
- * Algorithm 2 [Magnusson 2009] \return final step length
+ * Moore-Thuente (1994) and the noramal of \f$ \delta \vec{p} \f$ in Algorithm
+ * 2 [Magnusson 2009]
+ * \param[in] step_max maximum step length, \f$ \alpha_max \f$ in
+ * Moore-Thuente (1994)
+ * \param[in] step_min minimum step length, \f$ \alpha_min \f$ in
+ * Moore-Thuente (1994)
+ * \param[out] score final score function value, \f$ f(x + \alpha p) \f$ in
+ * Equation 1.3 (Moore, Thuente 1994) and \f$ score \f$ in Algorithm 2
+ * [Magnusson 2009]
+ * \param[in,out] score_gradient gradient of score function w.r.t.
+ * transformation vector, \f$ f'(x + \alpha p) \f$ in Moore-Thuente (1994) and
+ * \f$ \vec{g} \f$ in Algorithm 2 [Magnusson 2009]
+ * \param[out] hessian hessian of score function w.r.t. transformation vector,
+ * \f$ f''(x + \alpha p) \f$ in Moore-Thuente (1994) and \f$ H \f$ in
+ * Algorithm 2 [Magnusson 2009]
+ * \param[in,out] trans_cloud transformed point cloud, \f$ X \f$ transformed
+ * by \f$ T(\vec{p},\vec{x}) \f$ in Algorithm 2 [Magnusson 2009]
+ * \return final step length
*/
double
computeStepLengthMT(const Eigen::Matrix<double, 6, 1>& transform,
Eigen::Matrix<double, 6, 6>& hessian,
PointCloudSource& trans_cloud);
- /** \brief Update interval of possible step lengths for More-Thuente method, \f$ I \f$
- * in More-Thuente (1994) \note Updating Algorithm until some value satisfies \f$
- * \psi(\alpha_k) \leq 0 \f$ and \f$ \phi'(\alpha_k) \geq 0 \f$ and Modified Updating
- * Algorithm from then on [More, Thuente 1994]. \param[in,out] a_l first endpoint of
- * interval \f$ I \f$, \f$ \alpha_l \f$ in Moore-Thuente (1994) \param[in,out] f_l
- * value at first endpoint, \f$ f_l \f$ in Moore-Thuente (1994), \f$ \psi(\alpha_l)
- * \f$ for Update Algorithm and \f$ \phi(\alpha_l) \f$ for Modified Update Algorithm
- * \param[in,out] g_l derivative at first endpoint, \f$ g_l \f$ in Moore-Thuente
- * (1994), \f$ \psi'(\alpha_l) \f$ for Update Algorithm and \f$ \phi'(\alpha_l) \f$
- * for Modified Update Algorithm \param[in,out] a_u second endpoint of interval \f$ I
- * \f$, \f$ \alpha_u \f$ in Moore-Thuente (1994) \param[in,out] f_u value at second
- * endpoint, \f$ f_u \f$ in Moore-Thuente (1994), \f$ \psi(\alpha_u) \f$ for Update
- * Algorithm and \f$ \phi(\alpha_u) \f$ for Modified Update Algorithm \param[in,out]
- * g_u derivative at second endpoint, \f$ g_u \f$ in Moore-Thuente (1994), \f$
- * \psi'(\alpha_u) \f$ for Update Algorithm and \f$ \phi'(\alpha_u) \f$ for Modified
- * Update Algorithm \param[in] a_t trial value, \f$ \alpha_t \f$ in Moore-Thuente
- * (1994) \param[in] f_t value at trial value, \f$ f_t \f$ in Moore-Thuente (1994),
- * \f$ \psi(\alpha_t) \f$ for Update Algorithm and \f$ \phi(\alpha_t) \f$ for Modified
- * Update Algorithm \param[in] g_t derivative at trial value, \f$ g_t \f$ in
- * Moore-Thuente (1994), \f$ \psi'(\alpha_t) \f$ for Update Algorithm and \f$
- * \phi'(\alpha_t) \f$ for Modified Update Algorithm \return if interval converges
+ /** \brief Update interval of possible step lengths for More-Thuente method,
+ * \f$ I \f$ in More-Thuente (1994)
+ * \note Updating Algorithm until some value satisfies \f$ \psi(\alpha_k) \leq
+ * 0 \f$ and \f$ \phi'(\alpha_k) \geq 0 \f$ and Modified Updating Algorithm
+ * from then on [More, Thuente 1994].
+ * \param[in,out] a_l first endpoint of interval \f$ I \f$, \f$ \alpha_l \f$
+ * in Moore-Thuente (1994)
+ * \param[in,out] f_l value at first endpoint, \f$ f_l \f$ in Moore-Thuente
+ * (1994), \f$ \psi(\alpha_l) \f$ for Update Algorithm and \f$ \phi(\alpha_l)
+ * \f$ for Modified Update Algorithm
+ * \param[in,out] g_l derivative at first endpoint, \f$ g_l \f$ in
+ * Moore-Thuente (1994), \f$ \psi'(\alpha_l) \f$ for Update Algorithm and \f$
+ * \phi'(\alpha_l) \f$ for Modified Update Algorithm
+ * \param[in,out] a_u second endpoint of interval \f$ I \f$, \f$ \alpha_u \f$
+ * in Moore-Thuente (1994)
+ * \param[in,out] f_u value at second endpoint, \f$ f_u \f$ in Moore-Thuente
+ * (1994), \f$ \psi(\alpha_u) \f$ for Update Algorithm and \f$ \phi(\alpha_u)
+ * \f$ for Modified Update Algorithm
+ * \param[in,out] g_u derivative at second endpoint, \f$ g_u \f$ in
+ * Moore-Thuente (1994), \f$ \psi'(\alpha_u) \f$ for Update Algorithm and \f$
+ * \phi'(\alpha_u) \f$ for Modified Update Algorithm
+ * \param[in] a_t trial value, \f$ \alpha_t \f$ in Moore-Thuente (1994)
+ * \param[in] f_t value at trial value, \f$ f_t \f$ in Moore-Thuente (1994),
+ * \f$ \psi(\alpha_t) \f$ for Update Algorithm and \f$ \phi(\alpha_t) \f$ for
+ * Modified Update Algorithm
+ * \param[in] g_t derivative at trial value, \f$ g_t \f$ in Moore-Thuente
+ * (1994), \f$ \psi'(\alpha_t) \f$ for Update Algorithm and \f$
+ * \phi'(\alpha_t) \f$ for Modified Update Algorithm
+ * \return if interval converges
*/
bool
updateIntervalMT(double& a_l,
double g_t) const;
/** \brief Select new trial value for More-Thuente method.
- * \note Trial Value Selection [More, Thuente 1994], \f$ \psi(\alpha_k) \f$ is used
- * for \f$ f_k \f$ and \f$ g_k \f$ until some value satisfies the test \f$
- * \psi(\alpha_k) \leq 0 \f$ and \f$ \phi'(\alpha_k) \geq 0 \f$ then \f$
- * \phi(\alpha_k) \f$ is used from then on. \note Interpolation Minimizer equations
- * from Optimization Theory and Methods: Nonlinear Programming By Wenyu Sun, Ya-xiang
- * Yuan (89-100). \param[in] a_l first endpoint of interval \f$ I \f$, \f$ \alpha_l
- * \f$ in Moore-Thuente (1994) \param[in] f_l value at first endpoint, \f$ f_l \f$ in
- * Moore-Thuente (1994) \param[in] g_l derivative at first endpoint, \f$ g_l \f$ in
- * Moore-Thuente (1994) \param[in] a_u second endpoint of interval \f$ I \f$, \f$
- * \alpha_u \f$ in Moore-Thuente (1994) \param[in] f_u value at second endpoint, \f$
- * f_u \f$ in Moore-Thuente (1994) \param[in] g_u derivative at second endpoint, \f$
- * g_u \f$ in Moore-Thuente (1994) \param[in] a_t previous trial value, \f$ \alpha_t
- * \f$ in Moore-Thuente (1994) \param[in] f_t value at previous trial value, \f$ f_t
- * \f$ in Moore-Thuente (1994) \param[in] g_t derivative at previous trial value, \f$
- * g_t \f$ in Moore-Thuente (1994) \return new trial value
+ * \note Trial Value Selection [More, Thuente 1994], \f$ \psi(\alpha_k) \f$ is
+ * used for \f$ f_k \f$ and \f$ g_k \f$ until some value satisfies the test
+ * \f$ \psi(\alpha_k) \leq 0 \f$ and \f$ \phi'(\alpha_k) \geq 0 \f$ then \f$
+ * \phi(\alpha_k) \f$ is used from then on.
+ * \note Interpolation Minimizer equations from Optimization Theory and
+ * Methods: Nonlinear Programming By Wenyu Sun, Ya-xiang Yuan (89-100).
+ * \param[in] a_l first endpoint of interval \f$ I \f$, \f$ \alpha_l \f$ in
+ * Moore-Thuente (1994)
+ * \param[in] f_l value at first endpoint, \f$ f_l \f$ in Moore-Thuente (1994)
+ * \param[in] g_l derivative at first endpoint, \f$ g_l \f$ in Moore-Thuente
+ * (1994)
+ * \param[in] a_u second endpoint of interval \f$ I \f$, \f$ \alpha_u \f$ in
+ * Moore-Thuente (1994)
+ * \param[in] f_u value at second endpoint, \f$ f_u \f$ in Moore-Thuente
+ * (1994)
+ * \param[in] g_u derivative at second endpoint, \f$ g_u \f$ in Moore-Thuente
+ * (1994)
+ * \param[in] a_t previous trial value, \f$ \alpha_t \f$ in Moore-Thuente
+ * (1994)
+ * \param[in] f_t value at previous trial value, \f$ f_t \f$ in Moore-Thuente
+ * (1994)
+ * \param[in] g_t derivative at previous trial value, \f$ g_t \f$ in
+ * Moore-Thuente (1994)
+ * \return new trial value
*/
double
trialValueSelectionMT(double a_l,
double f_t,
double g_t) const;
- /** \brief Auxiliary function used to determine endpoints of More-Thuente interval.
+ /** \brief Auxiliary function used to determine endpoints of More-Thuente
+ * interval.
* \note \f$ \psi(\alpha) \f$ in Equation 1.6 (Moore, Thuente 1994)
* \param[in] a the step length, \f$ \alpha \f$ in More-Thuente (1994)
* \param[in] f_a function value at step length a, \f$ \phi(\alpha) \f$ in
- * More-Thuente (1994) \param[in] f_0 initial function value, \f$ \phi(0) \f$ in
- * Moore-Thuente (1994) \param[in] g_0 initial function gradient, \f$ \phi'(0) \f$ in
- * More-Thuente (1994) \param[in] mu the step length, constant \f$ \mu \f$ in
- * Equation 1.1 [More, Thuente 1994] \return sufficient decrease value
+ * More-Thuente (1994)
+ * \param[in] f_0 initial function value, \f$ \phi(0) \f$ in Moore-Thuente
+ * (1994)
+ * \param[in] g_0 initial function gradient, \f$ \phi'(0) \f$ in More-Thuente
+ * (1994)
+ * \param[in] mu the step length, constant \f$ \mu \f$ in Equation 1.1 [More,
+ * Thuente 1994]
+ * \return sufficient decrease value
*/
inline double
auxilaryFunction_PsiMT(
return f_a - f_0 - mu * g_0 * a;
}
- /** \brief Auxiliary function derivative used to determine endpoints of More-Thuente
- * interval. \note \f$ \psi'(\alpha) \f$, derivative of Equation 1.6 (Moore, Thuente
- * 1994) \param[in] g_a function gradient at step length a, \f$ \phi'(\alpha) \f$ in
- * More-Thuente (1994) \param[in] g_0 initial function gradient, \f$ \phi'(0) \f$ in
- * More-Thuente (1994) \param[in] mu the step length, constant \f$ \mu \f$ in
- * Equation 1.1 [More, Thuente 1994] \return sufficient decrease derivative
+ /** \brief Auxiliary function derivative used to determine endpoints of
+ * More-Thuente interval.
+ * \note \f$ \psi'(\alpha) \f$, derivative of Equation 1.6 (Moore, Thuente
+ * 1994)
+ * \param[in] g_a function gradient at step length a, \f$ \phi'(\alpha) \f$ in
+ * More-Thuente (1994)
+ * \param[in] g_0 initial function gradient, \f$ \phi'(0) \f$ in More-Thuente
+ * (1994)
+ * \param[in] mu the step length, constant \f$ \mu \f$ in Equation 1.1 [More,
+ * Thuente 1994]
+ * \return sufficient decrease derivative
*/
inline double
auxilaryFunction_dPsiMT(double g_a, double g_0, double mu = 1.e-4) const
return g_a - mu * g_0;
}
- /** \brief The voxel grid generated from target cloud containing point means and
- * covariances. */
+ /** \brief The voxel grid generated from target cloud containing point means
+ * and covariances. */
TargetGrid target_cells_;
/** \brief The side length of voxels. */
/** \brief The maximum step length. */
double step_size_;
- /** \brief The ratio of outliers of points w.r.t. a normal distribution, Equation 6.7
- * [Magnusson 2009]. */
+ /** \brief The ratio of outliers of points w.r.t. a normal distribution,
+ * Equation 6.7 [Magnusson 2009]. */
double outlier_ratio_;
- /** \brief The normalization constants used fit the point distribution to a normal
- * distribution, Equation 6.8 [Magnusson 2009]. */
+ /** \brief The normalization constants used fit the point distribution to a
+ * normal distribution, Equation 6.8 [Magnusson 2009]. */
double gauss_d1_, gauss_d2_;
- /** \brief The probability score of the transform applied to the input cloud,
+ /** \brief The likelihood score of the transform applied to the input cloud,
* Equation 6.9 and 6.10 [Magnusson 2009]. */
- double trans_probability_;
+ union {
+ PCL_DEPRECATED(1,
+ 16,
+ "`trans_probability_` has been renamed to `trans_likelihood_`.")
+ double trans_probability_;
+ double trans_likelihood_;
+ };
/** \brief Precomputed Angular Gradient
*
- * The precomputed angular derivatives for the jacobian of a transformation vector,
- * Equation 6.19 [Magnusson 2009].
+ * The precomputed angular derivatives for the jacobian of a transformation
+ * vector, Equation 6.19 [Magnusson 2009].
*/
Eigen::Matrix<double, 8, 4> angular_jacobian_;
/** \brief Precomputed Angular Hessian
*
- * The precomputed angular derivatives for the hessian of a transformation vector,
- * Equation 6.19 [Magnusson 2009].
+ * The precomputed angular derivatives for the hessian of a transformation
+ * vector, Equation 6.19 [Magnusson 2009].
*/
Eigen::Matrix<double, 15, 4> angular_hessian_;
- /** \brief The first order derivative of the transformation of a point w.r.t. the
- * transform vector, \f$ J_E \f$ in Equation 6.18 [Magnusson 2009]. */
+ /** \brief The first order derivative of the transformation of a point
+ * w.r.t. the transform vector, \f$ J_E \f$ in Equation 6.18 [Magnusson
+ * 2009]. */
Eigen::Matrix<double, 3, 6> point_jacobian_;
- /** \brief The second order derivative of the transformation of a point w.r.t. the
- * transform vector, \f$ H_E \f$ in Equation 6.20 [Magnusson 2009]. */
+ /** \brief The second order derivative of the transformation of a point
+ * w.r.t. the transform vector, \f$ H_E \f$ in Equation 6.20 [Magnusson
+ * 2009]. */
Eigen::Matrix<double, 18, 6> point_hessian_;
public:
}
/** \brief Empty destructor */
- ~NormalDistributionsTransform2D() {}
+ ~NormalDistributionsTransform2D() override = default;
/** \brief centre of the ndt grid (target coordinate system)
* \param centre value to set
using RegistrationPtr = typename Registration<PointT, PointT>::Ptr;
using GraphHandlerVertex = typename pcl::registration::GraphHandler<GraphT>::Vertex;
- /** \brief Empty destructor */
- virtual ~PairwiseGraphRegistration() {}
-
/** \brief Empty constructor */
PairwiseGraphRegistration() : registration_method_(), incremental_(true) {}
/** \brief Constructor */
/** \brief Structure for representing a single pyramid histogram level */
struct PyramidFeatureHistogramLevel {
- PyramidFeatureHistogramLevel() {}
+ PyramidFeatureHistogramLevel() = default;
PyramidFeatureHistogramLevel(std::vector<std::size_t>& a_bins_per_dimension,
std::vector<float>& a_bin_step)
{}
/** \brief destructor. */
- ~Registration() {}
+ ~Registration() override = default;
/** \brief Provide a pointer to the transformation estimation object.
* (e.g., SVD, point to plane etc.)
{
if (visualizerCallback) {
update_visualizer_ = visualizerCallback;
+ pcl::Indices indices;
+ update_visualizer_(*input_, indices, *target_, indices);
return (true);
}
return (false);
/** \brief The minimum number of correspondences that the algorithm needs before
* attempting to estimate the transformation. The default value is 3.
*/
- int min_number_correspondences_;
+ unsigned int min_number_correspondences_;
/** \brief The set of correspondences determined at this ICP step. */
CorrespondencesPtr correspondences_;
};
/** \brief Destructor */
- ~SampleConsensusPrerejective() {}
+ ~SampleConsensusPrerejective() override = default;
/** \brief Provide a boost shared pointer to the source point cloud's feature
* descriptors \param features the source point cloud's features
public:
using Matrix4 = Eigen::Matrix<Scalar, 4, 4>;
- TransformationEstimation(){};
- virtual ~TransformationEstimation(){};
+ TransformationEstimation() = default;
+ virtual ~TransformationEstimation() = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud. \param[in] cloud_src the source point cloud dataset \param[in]
using Matrix4 =
typename TransformationEstimation<PointSource, PointTarget, Scalar>::Matrix4;
- TransformationEstimation2D(){};
- virtual ~TransformationEstimation2D(){};
+ TransformationEstimation2D() = default;
+ virtual ~TransformationEstimation2D() = default;
/** \brief Estimate a rigid transformation between a source and a target point cloud
* in 2D. \param[in] cloud_src the source point cloud dataset \param[in] cloud_tgt the
/** \endcond */
/** \brief Constructor */
- TransformationEstimation3Point(){};
+ TransformationEstimation3Point() = default;
/** \brief Destructor */
- ~TransformationEstimation3Point(){};
+ ~TransformationEstimation3Point() override = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud. \param[in] cloud_src the source point cloud dataset \param[in]
typename TransformationEstimation<PointSource, PointTarget, Scalar>::Matrix4;
TransformationEstimationDQ(){};
- virtual ~TransformationEstimationDQ(){};
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud using dual quaternion optimization \param[in] cloud_src the source
using Matrix4 =
typename TransformationEstimation<PointSource, PointTarget, Scalar>::Matrix4;
- TransformationEstimationDualQuaternion(){};
- ~TransformationEstimationDualQuaternion(){};
+ TransformationEstimationDualQuaternion() = default;
+ ~TransformationEstimationDualQuaternion() override = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud using dual quaternion optimization \param[in] cloud_src the source
tmp_idx_src_ = src.tmp_idx_src_;
tmp_idx_tgt_ = src.tmp_idx_tgt_;
warp_point_ = src.warp_point_;
+ return (*this);
}
/** \brief Destructor. */
- ~TransformationEstimationLM(){};
+ ~TransformationEstimationLM() override = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud using LM. \param[in] cloud_src the source point cloud dataset
Functor(int m_data_points) : m_data_points_(m_data_points) {}
/** \brief Destructor. */
- virtual ~Functor() {}
+ virtual ~Functor() = default;
/** \brief Get the number of values. */
int
}
/** \brief Destructor. */
- ~OptimizationFunctor() {}
+ ~OptimizationFunctor() override = default;
/** Fill fvec from x. For the current state vector x fill the f values
* \param[in] x state vector
}
/** \brief Destructor. */
- ~OptimizationFunctorWithIndices() {}
+ ~OptimizationFunctorWithIndices() override = default;
/** Fill fvec from x. For the current state vector x fill the f values
* \param[in] x state vector
using Vector4 = Eigen::Matrix<Scalar, 4, 1>;
- TransformationEstimationPointToPlane(){};
- ~TransformationEstimationPointToPlane(){};
+ TransformationEstimationPointToPlane() = default;
+ ~TransformationEstimationPointToPlane() override = default;
protected:
Scalar
using Matrix4 =
typename TransformationEstimation<PointSource, PointTarget, Scalar>::Matrix4;
- TransformationEstimationPointToPlaneLLS(){};
- ~TransformationEstimationPointToPlaneLLS(){};
+ TransformationEstimationPointToPlaneLLS() = default;
+ ~TransformationEstimationPointToPlaneLLS() override = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud using SVD. \param[in] cloud_src the source point cloud dataset
using Matrix4 =
typename TransformationEstimation<PointSource, PointTarget, Scalar>::Matrix4;
- TransformationEstimationPointToPlaneLLSWeighted(){};
- virtual ~TransformationEstimationPointToPlaneLLSWeighted(){};
+ TransformationEstimationPointToPlaneLLSWeighted() = default;
+ virtual ~TransformationEstimationPointToPlaneLLSWeighted() = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud using SVD. \param[in] cloud_src the source point cloud dataset
warp_point_ = src.warp_point_;
correspondence_weights_ = src.correspondence_weights_;
use_correspondence_weights_ = src.use_correspondence_weights_;
+ return (*this);
}
/** \brief Destructor. */
- virtual ~TransformationEstimationPointToPlaneWeighted(){};
+ virtual ~TransformationEstimationPointToPlaneWeighted() = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud using LM. \param[in] cloud_src the source point cloud dataset
Functor(int m_data_points) : m_data_points_(m_data_points) {}
/** \brief Destructor. */
- virtual ~Functor() {}
+ virtual ~Functor() = default;
/** \brief Get the number of values. */
int
}
/** \brief Destructor. */
- virtual ~OptimizationFunctor() {}
+ virtual ~OptimizationFunctor() = default;
/** Fill fvec from x. For the current state vector x fill the f values
* \param[in] x state vector
}
/** \brief Destructor. */
- virtual ~OptimizationFunctorWithIndices() {}
+ virtual ~OptimizationFunctorWithIndices() = default;
/** Fill fvec from x. For the current state vector x fill the f values
* \param[in] x state vector
* \param[in] use_umeyama Toggles whether or not to use 3rd party software*/
TransformationEstimationSVD(bool use_umeyama = true) : use_umeyama_(use_umeyama) {}
- ~TransformationEstimationSVD(){};
+ ~TransformationEstimationSVD() override = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud using SVD. \param[in] cloud_src the source point cloud dataset
TransformationEstimationSymmetricPointToPlaneLLS()
: enforce_same_direction_normals_(true){};
- ~TransformationEstimationSymmetricPointToPlaneLLS(){};
+ ~TransformationEstimationSymmetricPointToPlaneLLS() override = default;
/** \brief Estimate a rigid rotation transformation between a source and a target
* point cloud using SVD. \param[in] cloud_src the source point cloud dataset
using PointCloudTargetPtr = typename PointCloudTarget::Ptr;
using PointCloudTargetConstPtr = typename PointCloudTarget::ConstPtr;
- TransformationValidation(){};
- virtual ~TransformationValidation(){};
+ TransformationValidation() = default;
+ virtual ~TransformationValidation() = default;
/** \brief Validate the given transformation with respect to the input cloud data, and
* return a score. Pure virtual.
, force_no_recompute_(false)
{}
- virtual ~TransformationValidationEuclidean(){};
+ virtual ~TransformationValidationEuclidean() = default;
/** \brief Set the maximum allowable distance between a point and its correspondence
* in the target in order for a correspondence to be considered \a valid. Default:
}
/** \brief Empty destructor */
- virtual ~MyPointRepresentation() {}
+ virtual ~MyPointRepresentation() = default;
virtual void
copyToFloatArray(const PointTarget& p, float* out) const
typename pcl::PointCloud<PointT>::ConstPtr())
: pose(p), cloud(c)
{}
+
+ PCL_MAKE_ALIGNED_OPERATOR_NEW;
};
} // namespace registration
} // namespace pcl
};
/** \brief Destructor. */
- virtual ~WarpPointRigid(){};
+ virtual ~WarpPointRigid() = default;
/** \brief Set warp parameters. Pure virtual.
* \param[in] p warp parameters
WarpPointRigid3D() : WarpPointRigid<PointSourceT, PointTargetT, Scalar>(3) {}
/** \brief Empty destructor */
- ~WarpPointRigid3D() {}
+ ~WarpPointRigid3D() override = default;
/** \brief Set warp parameters.
* \param[in] p warp parameters (tx ty rz)
WarpPointRigid6D() : WarpPointRigid<PointSourceT, PointTargetT, Scalar>(6) {}
/** \brief Empty destructor */
- ~WarpPointRigid6D() {}
+ ~WarpPointRigid6D() override = default;
/** \brief Set warp parameters.
* \note Assumes the quaternion parameters are normalized.
// For each set of features, go over each correspondence from input_correspondences_
for (std::size_t i = 0; i < input_correspondences_->size(); ++i) {
// Go over the map of features
- for (FeaturesMap::const_iterator it = features_map_.begin();
- it != features_map_.end();
- ++it) {
+ for (const auto& feature : features_map_) {
// Check if the score in feature space is above the given threshold
// (assume that the number of feature correspondenecs is the same as the number of
// point correspondences)
- if (!it->second->isCorrespondenceValid(static_cast<int>(i)))
+ if (!feature.second->isCorrespondenceValid(static_cast<int>(i)))
break;
remaining_correspondences[number_valid_correspondences] =
pcl::registration::CorrespondenceRejectorVarTrimmed::optimizeInlierRatio(
std::vector<double>& dists) const
{
- unsigned int points_nbr = static_cast<unsigned int>(dists.size());
+ auto points_nbr = static_cast<unsigned int>(dists.size());
std::sort(dists.begin(), dists.end());
const int min_el = int(std::floor(min_ratio_ * points_nbr));
{
// Discretize the feature cloud and insert it in the hash map
feature_hash_map_->clear();
- unsigned int n =
+ auto n =
static_cast<unsigned int>(std::sqrt(static_cast<float>(feature_cloud->size())));
int d1, d2, d3, d4;
max_dist_ = -1.0;
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
src/sac_model_plane.cpp
src/sac_model_registration.cpp
src/sac_model_sphere.cpp
+ src/sac_model_ellipse3d.cpp
)
set(incs
"include/pcl/${SUBSYS_NAME}/sac_model_registration.h"
"include/pcl/${SUBSYS_NAME}/sac_model_registration_2d.h"
"include/pcl/${SUBSYS_NAME}/sac_model_sphere.h"
+ "include/pcl/${SUBSYS_NAME}/sac_model_ellipse3d.h"
)
set(impl_incs
"include/pcl/${SUBSYS_NAME}/impl/sac_model_registration.hpp"
"include/pcl/${SUBSYS_NAME}/impl/sac_model_registration_2d.hpp"
"include/pcl/${SUBSYS_NAME}/impl/sac_model_sphere.hpp"
+ "include/pcl/${SUBSYS_NAME}/impl/sac_model_ellipse3d.hpp"
)
set(LIB_NAME "pcl_${SUBSYS_NAME}")
#ifndef PCL_SAMPLE_CONSENSUS_IMPL_MLESAC_H_
#define PCL_SAMPLE_CONSENSUS_IMPL_MLESAC_H_
+#include <limits>
#include <pcl/sample_consensus/mlesac.h>
-#include <cfloat> // for FLT_MAX
#include <pcl/common/common.h> // for computeMedian
//////////////////////////////////////////////////////////////////////////
double d_best_penalty = std::numeric_limits<double>::max();
double k = 1.0;
+ const double log_probability = std::log (1.0 - probability_);
+ const double one_over_indices = 1.0 / static_cast<double> (sac_model_->getIndices ()->size ());
+
Indices selection;
Eigen::VectorXf model_coefficients (sac_model_->getModelSize ());
std::vector<double> distances;
n_inliers_count++;
// Compute the k parameter (k=std::log(z)/std::log(1-w^n))
- double w = static_cast<double> (n_inliers_count) / static_cast<double> (sac_model_->getIndices ()->size ());
- double p_no_outliers = 1 - std::pow (w, static_cast<double> (selection.size ()));
- p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by -Inf
- p_no_outliers = (std::min) (1 - std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by 0.
- k = std::log (1 - probability_) / std::log (p_no_outliers);
+ const double w = static_cast<double> (n_inliers_count) * one_over_indices;
+ double p_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ())); // Probability that selection is contaminated by at least one outlier
+ p_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by -Inf
+ p_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by 0.
+ k = log_probability / std::log (p_outliers);
}
++iterations_;
Eigen::Vector4f &min_p,
Eigen::Vector4f &max_p) const
{
- min_p.setConstant (FLT_MAX);
- max_p.setConstant (-FLT_MAX);
+ min_p.setConstant (std::numeric_limits<float>::max());
+ max_p.setConstant (std::numeric_limits<float>::lowest());
min_p[3] = max_p[3] = 0;
for (std::size_t i = 0; i < indices->size (); ++i)
double d_best_penalty = std::numeric_limits<double>::max();
double k = 1.0;
+ const double log_probability = std::log (1.0 - probability_);
+ const double one_over_indices = 1.0 / static_cast<double> (sac_model_->getIndices ()->size ());
+
Indices selection;
Eigen::VectorXf model_coefficients (sac_model_->getModelSize ());
std::vector<double> distances;
++n_inliers_count;
// Compute the k parameter (k=std::log(z)/std::log(1-w^n))
- double w = static_cast<double> (n_inliers_count) / static_cast<double> (sac_model_->getIndices ()->size ());
- double p_no_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ()));
- p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by -Inf
- p_no_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by 0.
- k = std::log (1.0 - probability_) / std::log (p_no_outliers);
+ const double w = static_cast<double> (n_inliers_count) * one_over_indices;
+ double p_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ())); // Probability that selection is contaminated by at least one outlier
+ p_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by -Inf
+ p_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by 0.
+ k = log_probability / std::log (p_outliers);
}
++iterations_;
# pragma GCC system_header
#endif
+#include <limits>
+
#include <boost/math/distributions/binomial.hpp>
#include <pcl/sample_consensus/prosac.h>
pcl::ProgressiveSampleConsensus<PointT>::computeModel (int debug_verbosity_level)
{
// Warn and exit if no threshold was set
- if (threshold_ == DBL_MAX)
+ if (threshold_ == std::numeric_limits<double>::max())
{
PCL_ERROR ("[pcl::ProgressiveSampleConsensus::computeModel] No threshold set!\n");
return (false);
// Compute the k parameter (k=std::log(z)/std::log(1-w^n))
const double w = static_cast<double> (n_best_inliers_count) * one_over_indices;
- double p_no_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ()));
- p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by -Inf
- p_no_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by 0.
- k = log_probability / std::log (p_no_outliers);
+ double p_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ())); // Probability that selection is contaminated by at least one outlier
+ p_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by -Inf
+ p_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by 0.
+ k = log_probability / std::log (p_outliers);
}
} // omp critical
}
double d_best_penalty = std::numeric_limits<double>::max();
double k = 1.0;
+ const double log_probability = std::log (1.0 - probability_);
+ const double one_over_indices = 1.0 / static_cast<double> (sac_model_->getIndices ()->size ());
+
Indices selection;
Eigen::VectorXf model_coefficients (sac_model_->getModelSize ());
std::vector<double> distances;
n_inliers_count++;
// Compute the k parameter (k=std::log(z)/std::log(1-w^n))
- double w = static_cast<double> (n_inliers_count) / static_cast<double>(sac_model_->getIndices ()->size ());
- double p_no_outliers = 1 - std::pow (w, static_cast<double> (selection.size ()));
- p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by -Inf
- p_no_outliers = (std::min) (1 - std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by 0.
- k = std::log (1 - probability_) / std::log (p_no_outliers);
+ const double w = static_cast<double> (n_inliers_count) * one_over_indices;
+ double p_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ())); // Probability that selection is contaminated by at least one outlier
+ p_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by -Inf
+ p_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by 0.
+ k = log_probability / std::log (p_outliers);
}
++iterations_;
model_coefficients_ = model_coefficients;
// Compute the k parameter (k=std::log(z)/std::log(1-w^n))
- const double w = static_cast<double> (n_inliers_count) * one_over_indices;
- double p_no_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ()));
- p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by -Inf
- p_no_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_no_outliers); // Avoid division by 0.
- k = log_probability / std::log (p_no_outliers);
+ const double w = static_cast<double> (n_best_inliers_count) * one_over_indices;
+ double p_outliers = 1.0 - std::pow (w, static_cast<double> (selection.size ())); // Probability that selection is contaminated by at least one outlier
+ p_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by -Inf
+ p_outliers = (std::min) (1.0 - std::numeric_limits<double>::epsilon (), p_outliers); // Avoid division by 0.
+ k = log_probability / std::log (p_outliers);
}
++iterations_;
PCL_ERROR ("[pcl::SampleConsensusModelCircle2D::isSampleGood] Wrong number of samples (is %lu, should be %lu)!\n", samples.size (), sample_size_);
return (false);
}
- // Get the values at the two points
+
+ // Double precision here follows computeModelCoefficients, which means we
+ // can't use getVector3fMap-accessor to make our lives easier.
Eigen::Array2d p0 ((*input_)[samples[0]].x, (*input_)[samples[0]].y);
Eigen::Array2d p1 ((*input_)[samples[1]].x, (*input_)[samples[1]].y);
Eigen::Array2d p2 ((*input_)[samples[2]].x, (*input_)[samples[2]].y);
// Compute the segment values (in 2d) between p2 and p0
p2 -= p0;
- Eigen::Array2d dy1dy2 = p1 / p2;
+ // Check if the triangle area spanned by the three sample points is greater than 0
+ // https://en.wikipedia.org/wiki/Triangle#Using_vectors
+ if (std::abs (p1.x()*p2.y() - p2.x()*p1.y()) < Eigen::NumTraits<double>::dummy_precision ()) {
+ PCL_ERROR ("[pcl::SampleConsensusModelCircle2D::isSampleGood] Sample points too similar or collinear!\n");
+ return (false);
+ }
- return (dy1dy2[0] != dy1dy2[1]);
+ return (true);
}
//////////////////////////////////////////////////////////////////////////
template <typename PointT> bool
pcl::SampleConsensusModelCircle2D<PointT>::computeModelCoefficients (const Indices &samples, Eigen::VectorXf &model_coefficients) const
{
- // Need 3 samples
- if (samples.size () != sample_size_)
+ if (!isSampleGood (samples))
{
- PCL_ERROR ("[pcl::SampleConsensusModelCircle2D::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
+ PCL_ERROR ("[pcl::SampleConsensusModelCircle2D::computeModelCoefficients] Invalid set of samples given!\n");
return (false);
}
#ifndef PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_CIRCLE_3D_HPP_
#define PCL_SAMPLE_CONSENSUS_IMPL_SAC_MODEL_CIRCLE_3D_HPP_
-#include <cfloat> // for DBL_MAX
+#include <limits>
#include <unsupported/Eigen/NonLinearOptimization> // for LevenbergMarquardt
#include <pcl/sample_consensus/sac_model_circle3d.h>
PCL_ERROR ("[pcl::SampleConsensusModelCircle3D::isSampleGood] Wrong number of samples (is %lu, should be %lu)!\n", samples.size (), sample_size_);
return (false);
}
- // Get the values at the three points
+
+ // Double precision here follows computeModelCoefficients, which means we
+ // can't use getVector3fMap-accessor to make our lives easier.
Eigen::Vector3d p0 ((*input_)[samples[0]].x, (*input_)[samples[0]].y, (*input_)[samples[0]].z);
Eigen::Vector3d p1 ((*input_)[samples[1]].x, (*input_)[samples[1]].y, (*input_)[samples[1]].z);
Eigen::Vector3d p2 ((*input_)[samples[2]].x, (*input_)[samples[2]].y, (*input_)[samples[2]].z);
- // calculate vectors between points
- p1 -= p0;
- p2 -= p0;
+ // Check if the squared norm of the cross-product is non-zero, otherwise
+ // common_helper_vec, which plays an important role in computeModelCoefficients,
+ // would likely be ill-formed.
+ if ((p1 - p0).cross(p1 - p2).squaredNorm() < Eigen::NumTraits<float>::dummy_precision ())
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelCircle3D::isSampleGood] Sample points too similar or collinear!\n");
+ return (false);
+ }
- return (p1.dot (p2) < 0.000001);
+ return (true);
}
//////////////////////////////////////////////////////////////////////////
template <typename PointT> bool
pcl::SampleConsensusModelCircle3D<PointT>::computeModelCoefficients (const Indices &samples, Eigen::VectorXf &model_coefficients) const
{
- // Need 3 samples
if (samples.size () != sample_size_)
{
PCL_ERROR ("[pcl::SampleConsensusModelCircle3D::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
Eigen::Vector3d common_helper_vec = helper_vec01.cross (helper_vec12);
+ // The same check is implemented in isSampleGood, so be sure to look there too
+ // if you find the need to change something here.
+ if (common_helper_vec.squaredNorm() < Eigen::NumTraits<float>::dummy_precision ())
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelCircle3D::computeModelCoefficients] Sample points too similar or collinear!\n");
+ return (false);
+ }
+
double commonDividend = 2.0 * common_helper_vec.squaredNorm ();
double alpha = (helper_vec12.squaredNorm () * helper_vec01.dot (helper_vec02)) / commonDividend;
if (!SampleConsensusModel<PointT>::isModelValid (model_coefficients))
return (false);
- if (radius_min_ != -DBL_MAX && model_coefficients[3] < radius_min_)
+ if (radius_min_ != std::numeric_limits<double>::lowest() && model_coefficients[3] < radius_min_)
{
PCL_DEBUG ("[pcl::SampleConsensusModelCircle3D::isModelValid] Radius of circle is too small: should be larger than %g, but is %g.\n",
radius_min_, model_coefficients[3]);
return (false);
}
- if (radius_max_ != DBL_MAX && model_coefficients[3] > radius_max_)
+ if (radius_max_ != std::numeric_limits<double>::max() && model_coefficients[3] > radius_max_)
{
PCL_DEBUG ("[pcl::SampleConsensusModelCircle3D::isModelValid] Radius of circle is too big: should be smaller than %g, but is %g.\n",
radius_max_, model_coefficients[3]);
pcl::SampleConsensusModelCone<PointT, PointNT>::computeModelCoefficients (
const Indices &samples, Eigen::VectorXf &model_coefficients) const
{
- // Need 3 samples
- if (samples.size () != sample_size_)
+ // Make sure that the samples are valid
+ if (!isSampleGood (samples))
{
- PCL_ERROR ("[pcl::SampleConsensusModelCone::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
+ PCL_ERROR ("[pcl::SampleConsensusModelCone::computeModelCoefficients] Invalid set of samples given\n");
return (false);
}
Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0.0f);
Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0.0f);
- float opening_angle = model_coefficients[6];
+ const float sin_opening_angle = std::sin (model_coefficients[6]),
+ cos_opening_angle = std::cos (model_coefficients[6]),
+ tan_opening_angle = std::tan (model_coefficients[6]);
float apexdotdir = apex.dot (axis_dir);
float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
// Calculate the actual radius of the cone at the level of the projected point
Eigen::Vector4f height = apex - pt_proj;
- float actual_cone_radius = tanf (opening_angle) * height.norm ();
+ float actual_cone_radius = tan_opening_angle * height.norm ();
// Approximate the distance from the point to the cone as the difference between
// dist(point,cone_axis) and actual cone radius
// Calculate the cones perfect normals
height.normalize ();
- Eigen::Vector4f cone_normal = sinf (opening_angle) * height + std::cos (opening_angle) * dir;
+ Eigen::Vector4f cone_normal = sin_opening_angle * height + cos_opening_angle * dir;
// Calculate the angular distance between the point normal and the (dir=pt_proj->pt) vector
Eigen::Vector4f n ((*normals_)[(*indices_)[i]].normal[0], (*normals_)[(*indices_)[i]].normal[1], (*normals_)[(*indices_)[i]].normal[2], 0.0f);
Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0.0f);
Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0.0f);
- float opening_angle = model_coefficients[6];
+ const float sin_opening_angle = std::sin (model_coefficients[6]),
+ cos_opening_angle = std::cos (model_coefficients[6]),
+ tan_opening_angle = std::tan (model_coefficients[6]);
float apexdotdir = apex.dot (axis_dir);
float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
// Calculate the actual radius of the cone at the level of the projected point
Eigen::Vector4f height = apex - pt_proj;
- double actual_cone_radius = tan(opening_angle) * height.norm ();
+ double actual_cone_radius = tan_opening_angle * height.norm ();
// Approximate the distance from the point to the cone as the difference between
// dist(point,cone_axis) and actual cone radius
// Calculate the cones perfect normals
height.normalize ();
- Eigen::Vector4f cone_normal = sinf (opening_angle) * height + std::cos (opening_angle) * pp_pt_dir;
+ Eigen::Vector4f cone_normal = sin_opening_angle * height + cos_opening_angle * pp_pt_dir;
// Calculate the angular distance between the point normal and the (dir=pt_proj->pt) vector
Eigen::Vector4f n ((*normals_)[(*indices_)[i]].normal[0], (*normals_)[(*indices_)[i]].normal[1], (*normals_)[(*indices_)[i]].normal[2], 0.0f);
Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0.0f);
Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0.0f);
- float opening_angle = model_coefficients[6];
+ const float sin_opening_angle = std::sin (model_coefficients[6]),
+ cos_opening_angle = std::cos (model_coefficients[6]),
+ tan_opening_angle = std::tan (model_coefficients[6]);
float apexdotdir = apex.dot (axis_dir);
float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
// Calculate the actual radius of the cone at the level of the projected point
Eigen::Vector4f height = apex - pt_proj;
- double actual_cone_radius = tan(opening_angle) * height.norm ();
+ double actual_cone_radius = tan_opening_angle * height.norm ();
// Approximate the distance from the point to the cone as the difference between
// dist(point,cone_axis) and actual cone radius
// Calculate the cones perfect normals
height.normalize ();
- Eigen::Vector4f cone_normal = sinf (opening_angle) * height + std::cos (opening_angle) * pp_pt_dir;
+ Eigen::Vector4f cone_normal = sin_opening_angle * height + cos_opening_angle * pp_pt_dir;
// Calculate the angular distance between the point normal and the (dir=pt_proj->pt) vector
Eigen::Vector4f n ((*normals_)[(*indices_)[i]].normal[0], (*normals_)[(*indices_)[i]].normal[1], (*normals_)[(*indices_)[i]].normal[2], 0.0f);
Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0.0f);
Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0.0f);
- float opening_angle = model_coefficients[6];
+ const float tan_opening_angle = std::tan (model_coefficients[6]);
float apexdotdir = apex.dot (axis_dir);
float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
// Calculate the actual radius of the cone at the level of the projected point
Eigen::Vector4f height = apex - pp;
- float actual_cone_radius = tanf (opening_angle) * height.norm ();
+ float actual_cone_radius = tan_opening_angle * height.norm ();
// Calculate the projection of the point onto the cone
pp += dir * actual_cone_radius;
// Calculate the actual radius of the cone at the level of the projected point
Eigen::Vector4f height = apex - pp;
- float actual_cone_radius = tanf (opening_angle) * height.norm ();
+ float actual_cone_radius = tan_opening_angle * height.norm ();
// Calculate the projection of the point onto the cone
pp += dir * actual_cone_radius;
Eigen::Vector4f apex (model_coefficients[0], model_coefficients[1], model_coefficients[2], 0.0f);
Eigen::Vector4f axis_dir (model_coefficients[3], model_coefficients[4], model_coefficients[5], 0.0f);
- float openning_angle = model_coefficients[6];
+ const float tan_opening_angle = std::tan (model_coefficients[6]);
float apexdotdir = apex.dot (axis_dir);
float dirdotdir = 1.0f / axis_dir.dot (axis_dir);
// Calculate the actual radius of the cone at the level of the projected point
Eigen::Vector4f height = apex - pt_proj;
- double actual_cone_radius = tan (openning_angle) * height.norm ();
+ double actual_cone_radius = tan_opening_angle * height.norm ();
// Approximate the distance from the point to the cone as the difference between
// dist(point,cone_axis) and actual cone radius
PCL_ERROR ("[pcl::SampleConsensusModelCylinder::isSampleGood] Wrong number of samples (is %lu, should be %lu)!\n", samples.size (), sample_size_);
return (false);
}
+
+ // Make sure that the two sample points are not identical
+ if (
+ std::abs ((*input_)[samples[0]].x - (*input_)[samples[1]].x) <= std::numeric_limits<float>::epsilon ()
+ &&
+ std::abs ((*input_)[samples[0]].y - (*input_)[samples[1]].y) <= std::numeric_limits<float>::epsilon ()
+ &&
+ std::abs ((*input_)[samples[0]].z - (*input_)[samples[1]].z) <= std::numeric_limits<float>::epsilon ())
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelCylinder::isSampleGood] The two sample points are (almost) identical!\n");
+ return (false);
+ }
+
return (true);
}
pcl::SampleConsensusModelCylinder<PointT, PointNT>::computeModelCoefficients (
const Indices &samples, Eigen::VectorXf &model_coefficients) const
{
- // Need 2 samples
- if (samples.size () != sample_size_)
+ // Make sure that the samples are valid
+ if (!isSampleGood (samples))
{
- PCL_ERROR ("[pcl::SampleConsensusModelCylinder::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
+ PCL_ERROR ("[pcl::SampleConsensusModelCylinder::computeModelCoefficients] Invalid set of samples given!\n");
return (false);
}
return (false);
}
- if (std::abs ((*input_)[samples[0]].x - (*input_)[samples[1]].x) <= std::numeric_limits<float>::epsilon () &&
- std::abs ((*input_)[samples[0]].y - (*input_)[samples[1]].y) <= std::numeric_limits<float>::epsilon () &&
- std::abs ((*input_)[samples[0]].z - (*input_)[samples[1]].z) <= std::numeric_limits<float>::epsilon ())
- {
- return (false);
- }
-
Eigen::Vector4f p1 ((*input_)[samples[0]].x, (*input_)[samples[0]].y, (*input_)[samples[0]].z, 0.0f);
Eigen::Vector4f p2 ((*input_)[samples[1]].x, (*input_)[samples[1]].y, (*input_)[samples[1]].z, 0.0f);
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2014-, Open Perception Inc.
+ *
+ * All rights reserved
+ */
+
+#pragma once
+
+#include <limits>
+
+#include <unsupported/Eigen/NonLinearOptimization> // for LevenbergMarquardt
+#include <pcl/sample_consensus/sac_model_ellipse3d.h>
+#include <pcl/common/concatenate.h>
+
+#include <Eigen/Eigenvalues>
+#include <complex>
+
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> bool
+pcl::SampleConsensusModelEllipse3D<PointT>::isSampleGood (
+ const Indices &samples) const
+{
+ if (samples.size () != sample_size_)
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelEllipse3D::isSampleGood] Wrong number of samples (is %lu, should be %lu)!\n", samples.size (), sample_size_);
+ return (false);
+ }
+
+ // Use three points out of the 6 samples
+ const Eigen::Vector3d p0 ((*input_)[samples[0]].x, (*input_)[samples[0]].y, (*input_)[samples[0]].z);
+ const Eigen::Vector3d p1 ((*input_)[samples[1]].x, (*input_)[samples[1]].y, (*input_)[samples[1]].z);
+ const Eigen::Vector3d p2 ((*input_)[samples[2]].x, (*input_)[samples[2]].y, (*input_)[samples[2]].z);
+
+ // Check if the squared norm of the cross-product is non-zero, otherwise
+ // common_helper_vec, which plays an important role in computeModelCoefficients,
+ // would likely be ill-formed.
+ if ((p1 - p0).cross(p1 - p2).squaredNorm() < Eigen::NumTraits<float>::dummy_precision ())
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelEllipse3D::isSampleGood] Sample points too similar or collinear!\n");
+ return (false);
+ }
+
+ return (true);
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> bool
+pcl::SampleConsensusModelEllipse3D<PointT>::computeModelCoefficients (const Indices &samples, Eigen::VectorXf &model_coefficients) const
+{
+ // Uses 6 samples
+ if (samples.size () != sample_size_)
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelEllipse3D::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
+ return (false);
+ }
+
+ model_coefficients.resize (model_size_); // 11 coefs
+
+ const Eigen::Vector3f p0((*input_)[samples[0]].x, (*input_)[samples[0]].y, (*input_)[samples[0]].z);
+ const Eigen::Vector3f p1((*input_)[samples[1]].x, (*input_)[samples[1]].y, (*input_)[samples[1]].z);
+ const Eigen::Vector3f p2((*input_)[samples[2]].x, (*input_)[samples[2]].y, (*input_)[samples[2]].z);
+ const Eigen::Vector3f p3((*input_)[samples[3]].x, (*input_)[samples[3]].y, (*input_)[samples[3]].z);
+ const Eigen::Vector3f p4((*input_)[samples[4]].x, (*input_)[samples[4]].y, (*input_)[samples[4]].z);
+ const Eigen::Vector3f p5((*input_)[samples[5]].x, (*input_)[samples[5]].y, (*input_)[samples[5]].z);
+
+ const Eigen::Vector3f common_helper_vec = (p1 - p0).cross(p1 - p2);
+ const Eigen::Vector3f ellipse_normal = common_helper_vec.normalized();
+
+ // The same check is implemented in isSampleGood, so be sure to look there too
+ // if you find the need to change something here.
+ if (common_helper_vec.squaredNorm() < Eigen::NumTraits<float>::dummy_precision ())
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelEllipse3D::computeModelCoefficients] Sample points too similar or collinear!\n");
+ return (false);
+ }
+
+ // Definition of the local reference frame of the ellipse
+ Eigen::Vector3f x_axis = (p1 - p0).normalized();
+ const Eigen::Vector3f z_axis = ellipse_normal.normalized();
+ const Eigen::Vector3f y_axis = z_axis.cross(x_axis).normalized();
+
+ // Compute the rotation matrix and its transpose
+ const Eigen::Matrix3f Rot = (Eigen::Matrix3f(3,3)
+ << x_axis(0), y_axis(0), z_axis(0),
+ x_axis(1), y_axis(1), z_axis(1),
+ x_axis(2), y_axis(2), z_axis(2))
+ .finished();
+ const Eigen::Matrix3f Rot_T = Rot.transpose();
+
+ // Convert the points to local coordinates
+ const Eigen::Vector3f p0_ = Rot_T * (p0 - p0);
+ const Eigen::Vector3f p1_ = Rot_T * (p1 - p0);
+ const Eigen::Vector3f p2_ = Rot_T * (p2 - p0);
+ const Eigen::Vector3f p3_ = Rot_T * (p3 - p0);
+ const Eigen::Vector3f p4_ = Rot_T * (p4 - p0);
+ const Eigen::Vector3f p5_ = Rot_T * (p5 - p0);
+
+
+ // Fit an ellipse to the samples to obtain its conic equation parameters
+ // (this implementation follows the manuscript "Direct Least Square Fitting of Ellipses"
+ // A. Fitzgibbon, M. Pilu and R. Fisher, IEEE TPAMI, 21(5) : 476–480, May 1999).
+
+ // xOy projections only
+ const Eigen::VectorXf X = (Eigen::VectorXf(6) << p0_(0), p1_(0), p2_(0), p3_(0), p4_(0), p5_(0)).finished();
+ const Eigen::VectorXf Y = (Eigen::VectorXf(6) << p0_(1), p1_(1), p2_(1), p3_(1), p4_(1), p5_(1)).finished();
+
+ // Design matrix D
+ const Eigen::MatrixXf D = (Eigen::MatrixXf(6,6)
+ << X(0) * X(0), X(0) * Y(0), Y(0) * Y(0), X(0), Y(0), 1.0,
+ X(1) * X(1), X(1) * Y(1), Y(1) * Y(1), X(1), Y(1), 1.0,
+ X(2) * X(2), X(2) * Y(2), Y(2) * Y(2), X(2), Y(2), 1.0,
+ X(3) * X(3), X(3) * Y(3), Y(3) * Y(3), X(3), Y(3), 1.0,
+ X(4) * X(4), X(4) * Y(4), Y(4) * Y(4), X(4), Y(4), 1.0,
+ X(5) * X(5), X(5) * Y(5), Y(5) * Y(5), X(5), Y(5), 1.0)
+ .finished();
+
+ // Scatter matrix S
+ const Eigen::MatrixXf S = D.transpose() * D;
+
+ // Constraint matrix C
+ const Eigen::MatrixXf C = (Eigen::MatrixXf(6,6)
+ << 0.0, 0.0, -2.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
+ -2.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
+ .finished();
+
+ // Solve the Generalized Eigensystem: S*a = lambda*C*a
+ Eigen::GeneralizedEigenSolver<Eigen::MatrixXf> solver;
+ solver.compute(S, C);
+ const Eigen::VectorXf eigvals = solver.eigenvalues().real();
+
+ // Find the negative eigenvalue 'neigvec' (the largest, if many exist)
+ int idx(-1);
+ float absmin(0.0);
+ for (size_t i(0); i < static_cast<size_t>(eigvals.size()); ++i) {
+ if (eigvals(i) < absmin && !std::isinf(eigvals(i))) {
+ idx = i;
+ }
+ }
+ // Return "false" in case the negative eigenvalue was not found
+ if (idx == -1) {
+ PCL_DEBUG("[pcl::SampleConsensusModelEllipse3D::computeModelCoefficients] Failed to find the negative eigenvalue in the GES.\n");
+ return (false);
+ }
+ const Eigen::VectorXf neigvec = solver.eigenvectors().real().col(idx).normalized();
+
+
+ // Convert the conic model parameters to parametric ones
+
+ // Conic parameters
+ const float con_A(neigvec(0));
+ const float con_B(neigvec(1));
+ const float con_C(neigvec(2));
+ const float con_D(neigvec(3));
+ const float con_E(neigvec(4));
+ const float con_F(neigvec(5));
+
+ // Build matrix M0
+ const Eigen::MatrixXf M0 = (Eigen::MatrixXf(3, 3)
+ << con_F, con_D/2.0, con_E/2.0,
+ con_D/2.0, con_A, con_B/2.0,
+ con_E/2.0, con_B/2.0, con_C)
+ .finished();
+
+ // Build matrix M
+ const Eigen::MatrixXf M = (Eigen::MatrixXf(2, 2)
+ << con_A, con_B/2.0,
+ con_B/2.0, con_C)
+ .finished();
+
+ // Calculate the eigenvalues and eigenvectors of matrix M
+ Eigen::EigenSolver<Eigen::MatrixXf> solver_M(M);
+
+ Eigen::VectorXf eigvals_M = solver_M.eigenvalues().real();
+
+ // Order the eigenvalues so that |lambda_0 - con_A| <= |lambda_0 - con_C|
+ float aux_eigval(0.0);
+ if (std::abs(eigvals_M(0) - con_A) > std::abs(eigvals_M(0) - con_C)) {
+ aux_eigval = eigvals_M(0);
+ eigvals_M(0) = eigvals_M(1);
+ eigvals_M(1) = aux_eigval;
+ }
+
+ // Parametric parameters of the ellipse
+ float par_a = std::sqrt(-M0.determinant() / (M.determinant() * eigvals_M(0)));
+ float par_b = std::sqrt(-M0.determinant() / (M.determinant() * eigvals_M(1)));
+ const float par_h = (con_B * con_E - 2.0 * con_C * con_D) / (4.0 * con_A * con_C - std::pow(con_B, 2));
+ const float par_k = (con_B * con_D - 2.0 * con_A * con_E) / (4.0 * con_A * con_C - std::pow(con_B, 2));
+ const float par_t = (M_PI / 2.0 - std::atan((con_A - con_C) / con_B)) / 2.0; // equivalent to: acot((con_A - con_C) / con_B) / 2.0;
+
+ // Convert the center point of the ellipse to global coordinates
+ // (the if statement ensures that 'par_a' always refers to the semi-major axis length)
+ Eigen::Vector3f p_ctr;
+ float aux_par(0.0);
+ if (par_a > par_b) {
+ p_ctr = p0 + Rot * Eigen::Vector3f(par_h, par_k, 0.0);
+ } else {
+ aux_par = par_a;
+ par_a = par_b;
+ par_b = aux_par;
+ p_ctr = p0 + Rot * Eigen::Vector3f(par_k, par_h, 0.0);
+ }
+
+ // Center (x, y, z)
+ model_coefficients[0] = static_cast<float>(p_ctr(0));
+ model_coefficients[1] = static_cast<float>(p_ctr(1));
+ model_coefficients[2] = static_cast<float>(p_ctr(2));
+
+ // Semi-major axis length 'a' (along the local x-axis)
+ model_coefficients[3] = static_cast<float>(par_a);
+ // Semi-minor axis length 'b' (along the local y-axis)
+ model_coefficients[4] = static_cast<float>(par_b);
+
+ // Ellipse normal
+ model_coefficients[5] = static_cast<float>(ellipse_normal[0]);
+ model_coefficients[6] = static_cast<float>(ellipse_normal[1]);
+ model_coefficients[7] = static_cast<float>(ellipse_normal[2]);
+
+ // Retrive the ellipse point at the tilt angle t (par_t), along the local x-axis
+ const Eigen::VectorXf params = (Eigen::VectorXf(5) << par_a, par_b, par_h, par_k, par_t).finished();
+ Eigen::Vector3f p_th_(0.0, 0.0, 0.0);
+ get_ellipse_point(params, par_t, p_th_(0), p_th_(1));
+
+ // Redefinition of the x-axis of the ellipse's local reference frame
+ x_axis = (Rot * p_th_).normalized();
+ model_coefficients[8] = static_cast<float>(x_axis[0]);
+ model_coefficients[9] = static_cast<float>(x_axis[1]);
+ model_coefficients[10] = static_cast<float>(x_axis[2]);
+
+
+ PCL_DEBUG ("[pcl::SampleConsensusModelEllipse3D::computeModelCoefficients] Model is (%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g).\n",
+ model_coefficients[0], model_coefficients[1], model_coefficients[2], model_coefficients[3],
+ model_coefficients[4], model_coefficients[5], model_coefficients[6], model_coefficients[7],
+ model_coefficients[8], model_coefficients[9], model_coefficients[10]);
+ return (true);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> void
+pcl::SampleConsensusModelEllipse3D<PointT>::getDistancesToModel (const Eigen::VectorXf &model_coefficients, std::vector<double> &distances) const
+{
+ // Check if the model is valid given the user constraints
+ if (!isModelValid (model_coefficients))
+ {
+ distances.clear ();
+ return;
+ }
+ distances.resize (indices_->size ());
+
+ // c : Ellipse Center
+ const Eigen::Vector3f c(model_coefficients[0], model_coefficients[1], model_coefficients[2]);
+ // n : Ellipse (Plane) Normal
+ const Eigen::Vector3f n_axis(model_coefficients[5], model_coefficients[6], model_coefficients[7]);
+ // x : Ellipse (Plane) X-Axis
+ const Eigen::Vector3f x_axis(model_coefficients[8], model_coefficients[9], model_coefficients[10]);
+ // y : Ellipse (Plane) Y-Axis
+ const Eigen::Vector3f y_axis = n_axis.cross(x_axis).normalized();
+ // a : Ellipse semi-major axis (X) length
+ const float par_a(model_coefficients[3]);
+ // b : Ellipse semi-minor axis (Y) length
+ const float par_b(model_coefficients[4]);
+
+ // Compute the rotation matrix and its transpose
+ const Eigen::Matrix3f Rot = (Eigen::Matrix3f(3,3)
+ << x_axis(0), y_axis(0), n_axis(0),
+ x_axis(1), y_axis(1), n_axis(1),
+ x_axis(2), y_axis(2), n_axis(2))
+ .finished();
+ const Eigen::Matrix3f Rot_T = Rot.transpose();
+
+ // Ellipse parameters
+ const Eigen::VectorXf params = (Eigen::VectorXf(5) << par_a, par_b, 0.0, 0.0, 0.0).finished();
+ float th_opt;
+
+ // Iterate through the 3D points and calculate the distances from them to the ellipse
+ for (std::size_t i = 0; i < indices_->size (); ++i)
+ // Calculate the distance from the point to the ellipse:
+ // 1. calculate intersection point of the plane in which the ellipse lies and the
+ // line from the sample point with the direction of the plane normal (projected point)
+ // 2. calculate the intersection point of the line from the ellipse center to the projected point
+ // with the ellipse
+ // 3. calculate distance from corresponding point on the ellipse to the sample point
+ {
+ // p : Sample Point
+ const Eigen::Vector3f p((*input_)[(*indices_)[i]].x, (*input_)[(*indices_)[i]].y, (*input_)[(*indices_)[i]].z);
+
+ // Local coordinates of sample point p
+ const Eigen::Vector3f p_ = Rot_T * (p - c);
+
+ // k : Point on Ellipse
+ // Calculate the shortest distance from the point to the ellipse which is given by
+ // the norm of a vector that is normal to the ellipse tangent calculated at the
+ // point it intersects the tangent.
+ const Eigen::Vector2f distanceVector = dvec2ellipse(params, p_(0), p_(1), th_opt);
+
+ distances[i] = distanceVector.norm();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> void
+pcl::SampleConsensusModelEllipse3D<PointT>::selectWithinDistance (
+ const Eigen::VectorXf &model_coefficients, const double threshold,
+ Indices &inliers)
+{
+ inliers.clear();
+ // Check if the model is valid given the user constraints
+ if (!isModelValid (model_coefficients))
+ {
+ return;
+ }
+ inliers.reserve (indices_->size ());
+
+ // c : Ellipse Center
+ const Eigen::Vector3f c(model_coefficients[0], model_coefficients[1], model_coefficients[2]);
+ // n : Ellipse (Plane) Normal
+ const Eigen::Vector3f n_axis(model_coefficients[5], model_coefficients[6], model_coefficients[7]);
+ // x : Ellipse (Plane) X-Axis
+ const Eigen::Vector3f x_axis(model_coefficients[8], model_coefficients[9], model_coefficients[10]);
+ // y : Ellipse (Plane) Y-Axis
+ const Eigen::Vector3f y_axis = n_axis.cross(x_axis).normalized();
+ // a : Ellipse semi-major axis (X) length
+ const float par_a(model_coefficients[3]);
+ // b : Ellipse semi-minor axis (Y) length
+ const float par_b(model_coefficients[4]);
+
+ // Compute the rotation matrix and its transpose
+ const Eigen::Matrix3f Rot = (Eigen::Matrix3f(3,3)
+ << x_axis(0), y_axis(0), n_axis(0),
+ x_axis(1), y_axis(1), n_axis(1),
+ x_axis(2), y_axis(2), n_axis(2))
+ .finished();
+ const Eigen::Matrix3f Rot_T = Rot.transpose();
+
+ const auto squared_threshold = threshold * threshold;
+ // Iterate through the 3d points and calculate the distances from them to the ellipse
+ for (std::size_t i = 0; i < indices_->size (); ++i)
+ {
+ // p : Sample Point
+ const Eigen::Vector3f p((*input_)[(*indices_)[i]].x, (*input_)[(*indices_)[i]].y, (*input_)[(*indices_)[i]].z);
+
+ // Local coordinates of sample point p
+ const Eigen::Vector3f p_ = Rot_T * (p - c);
+
+ // k : Point on Ellipse
+ // Calculate the shortest distance from the point to the ellipse which is given by
+ // the norm of a vector that is normal to the ellipse tangent calculated at the
+ // point it intersects the tangent.
+ const Eigen::VectorXf params = (Eigen::VectorXf(5) << par_a, par_b, 0.0, 0.0, 0.0).finished();
+ float th_opt;
+ const Eigen::Vector2f distanceVector = dvec2ellipse(params, p_(0), p_(1), th_opt);
+
+ if (distanceVector.squaredNorm() < squared_threshold)
+ {
+ // Returns the indices of the points whose distances are smaller than the threshold
+ inliers.push_back ((*indices_)[i]);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> std::size_t
+pcl::SampleConsensusModelEllipse3D<PointT>::countWithinDistance (
+ const Eigen::VectorXf &model_coefficients, const double threshold) const
+{
+ // Check if the model is valid given the user constraints
+ if (!isModelValid (model_coefficients))
+ return (0);
+ std::size_t nr_p = 0;
+
+ // c : Ellipse Center
+ const Eigen::Vector3f c(model_coefficients[0], model_coefficients[1], model_coefficients[2]);
+ // n : Ellipse (Plane) Normal
+ const Eigen::Vector3f n_axis(model_coefficients[5], model_coefficients[6], model_coefficients[7]);
+ // x : Ellipse (Plane) X-Axis
+ const Eigen::Vector3f x_axis(model_coefficients[8], model_coefficients[9], model_coefficients[10]);
+ // y : Ellipse (Plane) Y-Axis
+ const Eigen::Vector3f y_axis = n_axis.cross(x_axis).normalized();
+ // a : Ellipse semi-major axis (X) length
+ const float par_a(model_coefficients[3]);
+ // b : Ellipse semi-minor axis (Y) length
+ const float par_b(model_coefficients[4]);
+
+ // Compute the rotation matrix and its transpose
+ const Eigen::Matrix3f Rot = (Eigen::Matrix3f(3,3)
+ << x_axis(0), y_axis(0), n_axis(0),
+ x_axis(1), y_axis(1), n_axis(1),
+ x_axis(2), y_axis(2), n_axis(2))
+ .finished();
+ const Eigen::Matrix3f Rot_T = Rot.transpose();
+
+ const auto squared_threshold = threshold * threshold;
+ // Iterate through the 3d points and calculate the distances from them to the ellipse
+ for (std::size_t i = 0; i < indices_->size (); ++i)
+ {
+ // p : Sample Point
+ const Eigen::Vector3f p((*input_)[(*indices_)[i]].x, (*input_)[(*indices_)[i]].y, (*input_)[(*indices_)[i]].z);
+
+ // Local coordinates of sample point p
+ const Eigen::Vector3f p_ = Rot_T * (p - c);
+
+ // k : Point on Ellipse
+ // Calculate the shortest distance from the point to the ellipse which is given by
+ // the norm of a vector that is normal to the ellipse tangent calculated at the
+ // point it intersects the tangent.
+ const Eigen::VectorXf params = (Eigen::VectorXf(5) << par_a, par_b, 0.0, 0.0, 0.0).finished();
+ float th_opt;
+ const Eigen::Vector2f distanceVector = dvec2ellipse(params, p_(0), p_(1), th_opt);
+
+ if (distanceVector.squaredNorm() < squared_threshold)
+ nr_p++;
+ }
+ return (nr_p);
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> void
+pcl::SampleConsensusModelEllipse3D<PointT>::optimizeModelCoefficients (
+ const Indices &inliers,
+ const Eigen::VectorXf &model_coefficients,
+ Eigen::VectorXf &optimized_coefficients) const
+{
+ optimized_coefficients = model_coefficients;
+
+ // Needs a set of valid model coefficients
+ if (!isModelValid (model_coefficients))
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelEllipse3D::optimizeModelCoefficients] Given model is invalid!\n");
+ return;
+ }
+
+ // Need more than the minimum sample size to make a difference
+ if (inliers.size () <= sample_size_)
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelEllipse3D::optimizeModelCoefficients] Not enough inliers to refine/optimize the model's coefficients (%lu)! Returning the same coefficients.\n", inliers.size ());
+ return;
+ }
+
+ OptimizationFunctor functor(this, inliers);
+ Eigen::NumericalDiff<OptimizationFunctor> num_diff(functor);
+ Eigen::LevenbergMarquardt<Eigen::NumericalDiff<OptimizationFunctor>, double> lm(num_diff);
+ Eigen::VectorXd coeff;
+ int info = lm.minimize(coeff);
+ for (Eigen::Index i = 0; i < coeff.size (); ++i)
+ optimized_coefficients[i] = static_cast<float> (coeff[i]);
+
+ // Compute the L2 norm of the residuals
+ PCL_DEBUG ("[pcl::SampleConsensusModelEllipse3D::optimizeModelCoefficients] LM solver finished with exit code %i, having a residual norm of %g. \nInitial solution: %g %g %g %g %g %g %g %g %g %g %g %g %g \nFinal solution: %g %g %g %g %g %g %g %g %g %g %g %g %g\n",
+ info, lm.fvec.norm (),
+
+ model_coefficients[0],
+ model_coefficients[1],
+ model_coefficients[2],
+ model_coefficients[3],
+ model_coefficients[4],
+ model_coefficients[5],
+ model_coefficients[6],
+ model_coefficients[7],
+ model_coefficients[8],
+ model_coefficients[9],
+ model_coefficients[10],
+
+ optimized_coefficients[0],
+ optimized_coefficients[1],
+ optimized_coefficients[2],
+ optimized_coefficients[3],
+ optimized_coefficients[4],
+ optimized_coefficients[5],
+ optimized_coefficients[6],
+ optimized_coefficients[7],
+ optimized_coefficients[8],
+ optimized_coefficients[9],
+ optimized_coefficients[10]);
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> void
+pcl::SampleConsensusModelEllipse3D<PointT>::projectPoints (
+ const Indices &inliers, const Eigen::VectorXf &model_coefficients,
+ PointCloud &projected_points, bool copy_data_fields) const
+{
+ // Needs a valid set of model coefficients
+ if (!isModelValid (model_coefficients))
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelEllipse3D::projectPoints] Given model is invalid!\n");
+ return;
+ }
+
+ projected_points.header = input_->header;
+ projected_points.is_dense = input_->is_dense;
+
+ // Copy all the data fields from the input cloud to the projected one?
+ if (copy_data_fields)
+ {
+ // Allocate enough space and copy the basics
+ projected_points.resize (input_->size ());
+ projected_points.width = input_->width;
+ projected_points.height = input_->height;
+
+ using FieldList = typename pcl::traits::fieldList<PointT>::type;
+ // Iterate over each point
+ for (std::size_t i = 0; i < projected_points.size(); ++i)
+ {
+ // Iterate over each dimension
+ pcl::for_each_type<FieldList>(NdConcatenateFunctor<PointT, PointT>((*input_)[i], projected_points[i]));
+ }
+
+ // c : Ellipse Center
+ const Eigen::Vector3f c(model_coefficients[0], model_coefficients[1], model_coefficients[2]);
+ // n : Ellipse (Plane) Normal
+ const Eigen::Vector3f n_axis(model_coefficients[5], model_coefficients[6], model_coefficients[7]);
+ // x : Ellipse (Plane) X-Axis
+ const Eigen::Vector3f x_axis(model_coefficients[8], model_coefficients[9], model_coefficients[10]);
+ // y : Ellipse (Plane) Y-Axis
+ const Eigen::Vector3f y_axis = n_axis.cross(x_axis).normalized();
+ // a : Ellipse semi-major axis (X) length
+ const float par_a(model_coefficients[3]);
+ // b : Ellipse semi-minor axis (Y) length
+ const float par_b(model_coefficients[4]);
+
+ // Compute the rotation matrix and its transpose
+ const Eigen::Matrix3f Rot = (Eigen::Matrix3f(3,3)
+ << x_axis(0), y_axis(0), n_axis(0),
+ x_axis(1), y_axis(1), n_axis(1),
+ x_axis(2), y_axis(2), n_axis(2))
+ .finished();
+ const Eigen::Matrix3f Rot_T = Rot.transpose();
+
+ // Iterate through the 3d points and calculate the distances from them to the plane
+ for (std::size_t i = 0; i < inliers.size (); ++i)
+ {
+ // p : Sample Point
+ const Eigen::Vector3f p((*input_)[(*indices_)[i]].x, (*input_)[(*indices_)[i]].y, (*input_)[(*indices_)[i]].z);
+
+ // Local coordinates of sample point p
+ const Eigen::Vector3f p_ = Rot_T * (p - c);
+
+ // k : Point on Ellipse
+ // Calculate the shortest distance from the point to the ellipse which is given by
+ // the norm of a vector that is normal to the ellipse tangent calculated at the
+ // point it intersects the tangent.
+ const Eigen::VectorXf params = (Eigen::VectorXf(5) << par_a, par_b, 0.0, 0.0, 0.0).finished();
+ float th_opt;
+ dvec2ellipse(params, p_(0), p_(1), th_opt);
+
+ // Retrive the ellipse point at the tilt angle t, along the local x-axis
+ Eigen::Vector3f k_(0.0, 0.0, 0.0);
+ get_ellipse_point(params, th_opt, k_[0], k_[1]);
+
+ const Eigen::Vector3f k = c + Rot * k_;
+
+ projected_points[i].x = static_cast<float> (k[0]);
+ projected_points[i].y = static_cast<float> (k[1]);
+ projected_points[i].z = static_cast<float> (k[2]);
+ }
+ }
+ else
+ {
+ // Allocate enough space and copy the basics
+ projected_points.resize (inliers.size ());
+ projected_points.width = inliers.size ();
+ projected_points.height = 1;
+
+ using FieldList = typename pcl::traits::fieldList<PointT>::type;
+ // Iterate over each point
+ for (std::size_t i = 0; i < inliers.size (); ++i)
+ // Iterate over each dimension
+ pcl::for_each_type <FieldList> (NdConcatenateFunctor <PointT, PointT> ((*input_)[inliers[i]], projected_points[i]));
+
+ // c : Ellipse Center
+ const Eigen::Vector3f c(model_coefficients[0], model_coefficients[1], model_coefficients[2]);
+ // n : Ellipse (Plane) Normal
+ const Eigen::Vector3f n_axis(model_coefficients[5], model_coefficients[6], model_coefficients[7]);
+ // x : Ellipse (Plane) X-Axis
+ const Eigen::Vector3f x_axis(model_coefficients[8], model_coefficients[9], model_coefficients[10]);
+ // y : Ellipse (Plane) Y-Axis
+ const Eigen::Vector3f y_axis = n_axis.cross(x_axis).normalized();
+ // a : Ellipse semi-major axis (X) length
+ const float par_a(model_coefficients[3]);
+ // b : Ellipse semi-minor axis (Y) length
+ const float par_b(model_coefficients[4]);
+
+ // Compute the rotation matrix and its transpose
+ const Eigen::Matrix3f Rot = (Eigen::Matrix3f(3,3)
+ << x_axis(0), y_axis(0), n_axis(0),
+ x_axis(1), y_axis(1), n_axis(1),
+ x_axis(2), y_axis(2), n_axis(2))
+ .finished();
+ const Eigen::Matrix3f Rot_T = Rot.transpose();
+
+ // Iterate through the 3d points and calculate the distances from them to the plane
+ for (std::size_t i = 0; i < inliers.size (); ++i)
+ {
+ // p : Sample Point
+ const Eigen::Vector3f p((*input_)[(*indices_)[i]].x, (*input_)[(*indices_)[i]].y, (*input_)[(*indices_)[i]].z);
+
+ // Local coordinates of sample point p
+ const Eigen::Vector3f p_ = Rot_T * (p - c);
+
+ // k : Point on Ellipse
+ // Calculate the shortest distance from the point to the ellipse which is given by
+ // the norm of a vector that is normal to the ellipse tangent calculated at the
+ // point it intersects the tangent.
+ const Eigen::VectorXf params = (Eigen::VectorXf(5) << par_a, par_b, 0.0, 0.0, 0.0).finished();
+ float th_opt;
+ dvec2ellipse(params, p_(0), p_(1), th_opt);
+
+ // Retrive the ellipse point at the tilt angle t, along the local x-axis
+ //// model_coefficients[5] = static_cast<float>(par_t);
+ Eigen::Vector3f k_(0.0, 0.0, 0.0);
+ get_ellipse_point(params, th_opt, k_[0], k_[1]);
+
+ const Eigen::Vector3f k = c + Rot * k_;
+
+ projected_points[i].x = static_cast<float> (k[0]);
+ projected_points[i].y = static_cast<float> (k[1]);
+ projected_points[i].z = static_cast<float> (k[2]);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> bool
+pcl::SampleConsensusModelEllipse3D<PointT>::doSamplesVerifyModel (
+ const std::set<index_t> &indices,
+ const Eigen::VectorXf &model_coefficients,
+ const double threshold) const
+{
+ // Needs a valid model coefficients
+ if (!isModelValid (model_coefficients))
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelEllipse3D::doSamplesVerifyModel] Given model is invalid!\n");
+ return (false);
+ }
+
+ // c : Ellipse Center
+ const Eigen::Vector3f c(model_coefficients[0], model_coefficients[1], model_coefficients[2]);
+ // n : Ellipse (Plane) Normal
+ const Eigen::Vector3f n_axis(model_coefficients[5], model_coefficients[6], model_coefficients[7]);
+ // x : Ellipse (Plane) X-Axis
+ const Eigen::Vector3f x_axis(model_coefficients[8], model_coefficients[9], model_coefficients[10]);
+ // y : Ellipse (Plane) Y-Axis
+ const Eigen::Vector3f y_axis = n_axis.cross(x_axis).normalized();
+ // a : Ellipse semi-major axis (X) length
+ const float par_a(model_coefficients[3]);
+ // b : Ellipse semi-minor axis (Y) length
+ const float par_b(model_coefficients[4]);
+
+ // Compute the rotation matrix and its transpose
+ const Eigen::Matrix3f Rot = (Eigen::Matrix3f(3,3)
+ << x_axis(0), y_axis(0), n_axis(0),
+ x_axis(1), y_axis(1), n_axis(1),
+ x_axis(2), y_axis(2), n_axis(2))
+ .finished();
+ const Eigen::Matrix3f Rot_T = Rot.transpose();
+
+ const auto squared_threshold = threshold * threshold;
+ for (const auto &index : indices)
+ {
+ // p : Sample Point
+ const Eigen::Vector3f p((*input_)[index].x, (*input_)[index].y, (*input_)[index].z);
+
+ // Local coordinates of sample point p
+ const Eigen::Vector3f p_ = Rot_T * (p - c);
+
+ // k : Point on Ellipse
+ // Calculate the shortest distance from the point to the ellipse which is given by
+ // the norm of a vector that is normal to the ellipse tangent calculated at the
+ // point it intersects the tangent.
+ const Eigen::VectorXf params = (Eigen::VectorXf(5) << par_a, par_b, 0.0, 0.0, 0.0).finished();
+ float th_opt;
+ const Eigen::Vector2f distanceVector = dvec2ellipse(params, p_(0), p_(1), th_opt);
+
+ if (distanceVector.squaredNorm() > squared_threshold)
+ return (false);
+ }
+ return (true);
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT> bool
+pcl::SampleConsensusModelEllipse3D<PointT>::isModelValid (const Eigen::VectorXf &model_coefficients) const
+{
+ if (!SampleConsensusModel<PointT>::isModelValid (model_coefficients))
+ return (false);
+
+ if (radius_min_ != std::numeric_limits<double>::lowest() && (model_coefficients[3] < radius_min_ || model_coefficients[4] < radius_min_))
+ {
+ PCL_DEBUG ("[pcl::SampleConsensusModelEllipse3D::isModelValid] Semi-minor axis OR semi-major axis (radii) of ellipse is/are too small: should be larger than %g, but are {%g, %g}.\n",
+ radius_min_, model_coefficients[3], model_coefficients[4]);
+ return (false);
+ }
+ if (radius_max_ != std::numeric_limits<double>::max() && (model_coefficients[3] > radius_max_ || model_coefficients[4] > radius_max_))
+ {
+ PCL_DEBUG ("[pcl::SampleConsensusModelEllipse3D::isModelValid] Semi-minor axis OR semi-major axis (radii) of ellipse is/are too big: should be smaller than %g, but are {%g, %g}.\n",
+ radius_max_, model_coefficients[3], model_coefficients[4]);
+ return (false);
+ }
+
+ return (true);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT>
+void inline pcl::SampleConsensusModelEllipse3D<PointT>::get_ellipse_point(
+ const Eigen::VectorXf& par, float th, float& x, float& y)
+{
+ /*
+ * Calculates a point on the ellipse model 'par' using the angle 'th'.
+ */
+
+ // Parametric eq.params
+ const float par_a(par[0]);
+ const float par_b(par[1]);
+ const float par_h(par[2]);
+ const float par_k(par[3]);
+ const float par_t(par[4]);
+
+ x = par_h + std::cos(par_t) * par_a * std::cos(th) -
+ std::sin(par_t) * par_b * std::sin(th);
+ y = par_k + std::sin(par_t) * par_a * std::cos(th) +
+ std::cos(par_t) * par_b * std::sin(th);
+
+ return;
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT>
+Eigen::Vector2f inline pcl::SampleConsensusModelEllipse3D<PointT>::dvec2ellipse(
+ const Eigen::VectorXf& par, float u, float v, float& th_opt)
+{
+ /*
+ * Minimum distance vector from point p=(u,v) to the ellipse model 'par'.
+ */
+
+ // Parametric eq.params
+ // (par_a, par_b, and par_t do not need to be declared)
+ const float par_h = par[2];
+ const float par_k = par[3];
+
+ const Eigen::Vector2f center(par_h, par_k);
+ Eigen::Vector2f p(u, v);
+ p -= center;
+
+ // Local x-axis of the ellipse
+ Eigen::Vector2f x_axis(0.0, 0.0);
+ get_ellipse_point(par, 0.0, x_axis(0), x_axis(1));
+ x_axis -= center;
+
+ // Local y-axis of the ellipse
+ Eigen::Vector2f y_axis(0.0, 0.0);
+ get_ellipse_point(par, M_PI / 2.0, y_axis(0), y_axis(1));
+ y_axis -= center;
+
+ // Convert the point p=(u,v) to local ellipse coordinates
+ const float x_proj = p.dot(x_axis) / x_axis.norm();
+ const float y_proj = p.dot(y_axis) / y_axis.norm();
+
+ // Find the ellipse quandrant to where the point p=(u,v) belongs,
+ // and limit the search interval to 'th_min' and 'th_max'.
+ float th_min(0.0), th_max(0.0);
+ const float th = std::atan2(y_proj, x_proj);
+
+ if (-M_PI <= th && th < -M_PI / 2.0) {
+ // Q3
+ th_min = -M_PI;
+ th_max = -M_PI / 2.0;
+ }
+ if (-M_PI / 2.0 <= th && th < 0.0) {
+ // Q4
+ th_min = -M_PI / 2.0;
+ th_max = 0.0;
+ }
+ if (0.0 <= th && th < M_PI / 2.0) {
+ // Q1
+ th_min = 0.0;
+ th_max = M_PI / 2.0;
+ }
+ if (M_PI / 2.0 <= th && th <= M_PI) {
+ // Q2
+ th_min = M_PI / 2.0;
+ th_max = M_PI;
+ }
+
+ // Use an unconstrained line search optimizer to find the optimal th_opt
+ th_opt = golden_section_search(par, u, v, th_min, th_max, 1.e-3);
+
+ // Distance vector from a point (u,v) to a given point in the ellipse model 'par' at an angle 'th_opt'.
+ float x(0.0), y(0.0);
+ get_ellipse_point(par, th_opt, x, y);
+ Eigen::Vector2f distanceVector(u - x, v - y);
+ return distanceVector;
+}
+
+//////////////////////////////////////////////////////////////////////////
+template <typename PointT>
+float inline pcl::SampleConsensusModelEllipse3D<PointT>::golden_section_search(
+ const Eigen::VectorXf& par,
+ float u,
+ float v,
+ float th_min,
+ float th_max,
+ float epsilon)
+{
+ /*
+ * Golden section search
+ */
+
+ constexpr float phi(1.61803398874989484820f); // Golden ratio
+
+ // tl (theta lower bound), tu (theta upper bound)
+ float tl(th_min), tu(th_max);
+ float ta = tl + (tu - tl) * (1 - 1 / phi);
+ float tb = tl + (tu - tl) * 1 / phi;
+
+ while ((tu - tl) > epsilon) {
+
+ // theta a
+ float x_a(0.0), y_a(0.0);
+ get_ellipse_point(par, ta, x_a, y_a);
+ float squared_dist_ta = (u - x_a) * (u - x_a) + (v - y_a) * (v - y_a);
+
+ // theta b
+ float x_b(0.0), y_b(0.0);
+ get_ellipse_point(par, tb, x_b, y_b);
+ float squared_dist_tb = (u - x_b) * (u - x_b) + (v - y_b) * (v - y_b);
+
+ if (squared_dist_ta < squared_dist_tb) {
+ tu = tb;
+ tb = ta;
+ ta = tl + (tu - tl) * (1 - 1 / phi);
+ }
+ else if (squared_dist_ta > squared_dist_tb) {
+ tl = ta;
+ ta = tb;
+ tb = tl + (tu - tl) * 1 / phi;
+ }
+ else {
+ tl = ta;
+ tu = tb;
+ ta = tl + (tu - tl) * (1 - 1 / phi);
+ tb = tl + (tu - tl) * 1 / phi;
+ }
+ }
+ return (tl + tu) / 2.0;
+}
+
+
+#define PCL_INSTANTIATE_SampleConsensusModelEllipse3D(T) template class PCL_EXPORTS pcl::SampleConsensusModelEllipse3D<T>;
PCL_ERROR ("[pcl::SampleConsensusModelLine::isSampleGood] Wrong number of samples (is %lu, should be %lu)!\n", samples.size (), sample_size_);
return (false);
}
+
// Make sure that the two sample points are not identical
if (
- ((*input_)[samples[0]].x != (*input_)[samples[1]].x)
- ||
- ((*input_)[samples[0]].y != (*input_)[samples[1]].y)
- ||
- ((*input_)[samples[0]].z != (*input_)[samples[1]].z))
+ std::abs ((*input_)[samples[0]].x - (*input_)[samples[1]].x) <= std::numeric_limits<float>::epsilon ()
+ &&
+ std::abs ((*input_)[samples[0]].y - (*input_)[samples[1]].y) <= std::numeric_limits<float>::epsilon ()
+ &&
+ std::abs ((*input_)[samples[0]].z - (*input_)[samples[1]].z) <= std::numeric_limits<float>::epsilon ())
{
- return (true);
+ PCL_ERROR ("[pcl::SampleConsensusModelLine::isSampleGood] The two sample points are (almost) identical!\n");
+ return (false);
}
- return (false);
+ return (true);
}
//////////////////////////////////////////////////////////////////////////
pcl::SampleConsensusModelLine<PointT>::computeModelCoefficients (
const Indices &samples, Eigen::VectorXf &model_coefficients) const
{
- // Need 2 samples
- if (samples.size () != sample_size_)
- {
- PCL_ERROR ("[pcl::SampleConsensusModelLine::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
- return (false);
- }
-
- if (std::abs ((*input_)[samples[0]].x - (*input_)[samples[1]].x) <= std::numeric_limits<float>::epsilon () &&
- std::abs ((*input_)[samples[0]].y - (*input_)[samples[1]].y) <= std::numeric_limits<float>::epsilon () &&
- std::abs ((*input_)[samples[0]].z - (*input_)[samples[1]].z) <= std::numeric_limits<float>::epsilon ())
+ // Make sure that the samples are valid
+ if (!isSampleGood (samples))
{
+ PCL_ERROR ("[pcl::SampleConsensusModelLine::computeModelCoefficients] Invalid set of samples given!\n");
return (false);
}
model_coefficients[4] = (*input_)[samples[1]].y - model_coefficients[1];
model_coefficients[5] = (*input_)[samples[1]].z - model_coefficients[2];
+ // This precondition should hold if the samples have been found to be good
+ assert (model_coefficients.template tail<3> ().squaredNorm () > 0.0f);
+
model_coefficients.template tail<3> ().normalize ();
PCL_DEBUG ("[pcl::SampleConsensusModelLine::computeModelCoefficients] Model is (%g,%g,%g,%g,%g,%g).\n",
model_coefficients[0], model_coefficients[1], model_coefficients[2],
PCL_ERROR ("[pcl::SampleConsensusModelPlane::isSampleGood] Wrong number of samples (is %lu, should be %lu)!\n", samples.size (), sample_size_);
return (false);
}
- // Get the values at the two points
- pcl::Array4fMapConst p0 = (*input_)[samples[0]].getArray4fMap ();
- pcl::Array4fMapConst p1 = (*input_)[samples[1]].getArray4fMap ();
- pcl::Array4fMapConst p2 = (*input_)[samples[2]].getArray4fMap ();
- Eigen::Array4f dy1dy2 = (p1-p0) / (p2-p0);
+ // Check if the sample points are collinear
+ // Similar checks are implemented as precaution in computeModelCoefficients,
+ // so if you find the need to fix something in here, look there, too.
+ pcl::Vector3fMapConst p0 = (*input_)[samples[0]].getVector3fMap ();
+ pcl::Vector3fMapConst p1 = (*input_)[samples[1]].getVector3fMap ();
+ pcl::Vector3fMapConst p2 = (*input_)[samples[2]].getVector3fMap ();
+
+ // Check if the norm of the cross-product would be non-zero, otherwise
+ // normalization will fail. One could also interpret this as kind of check
+ // if the triangle spanned by those three points would have an area greater
+ // than zero.
+ if ((p1 - p0).cross(p2 - p0).stableNorm() < Eigen::NumTraits<float>::dummy_precision ())
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelPlane::isSampleGood] Sample points too similar or collinear!\n");
+ return (false);
+ }
- return ( (dy1dy2[0] != dy1dy2[1]) || (dy1dy2[2] != dy1dy2[1]) );
+ return (true);
}
//////////////////////////////////////////////////////////////////////////
pcl::SampleConsensusModelPlane<PointT>::computeModelCoefficients (
const Indices &samples, Eigen::VectorXf &model_coefficients) const
{
- // Need 3 samples
+ // The checks are redundant with isSampleGood above, but since most of the
+ // computed values are also used to compute the model coefficients, this might
+ // be a situation where this duplication is acceptable.
if (samples.size () != sample_size_)
{
PCL_ERROR ("[pcl::SampleConsensusModelPlane::computeModelCoefficients] Invalid set of samples given (%lu)!\n", samples.size ());
return (false);
}
- pcl::Array4fMapConst p0 = (*input_)[samples[0]].getArray4fMap ();
- pcl::Array4fMapConst p1 = (*input_)[samples[1]].getArray4fMap ();
- pcl::Array4fMapConst p2 = (*input_)[samples[2]].getArray4fMap ();
+ pcl::Vector3fMapConst p0 = (*input_)[samples[0]].getVector3fMap ();
+ pcl::Vector3fMapConst p1 = (*input_)[samples[1]].getVector3fMap ();
+ pcl::Vector3fMapConst p2 = (*input_)[samples[2]].getVector3fMap ();
- // Compute the segment values (in 3d) between p1 and p0
- Eigen::Array4f p1p0 = p1 - p0;
- // Compute the segment values (in 3d) between p2 and p0
- Eigen::Array4f p2p0 = p2 - p0;
+ const Eigen::Vector3f cross = (p1 - p0).cross(p2 - p0);
+ const float crossNorm = cross.stableNorm();
- // Avoid some crashes by checking for collinearity here
- Eigen::Array4f dy1dy2 = p1p0 / p2p0;
- if ( (dy1dy2[0] == dy1dy2[1]) && (dy1dy2[2] == dy1dy2[1]) ) // Check for collinearity
+ // Checking for collinearity here
+ if (crossNorm < Eigen::NumTraits<float>::dummy_precision ())
{
+ PCL_ERROR ("[pcl::SampleConsensusModelPlane::computeModelCoefficients] Chosen samples are collinear!\n");
return (false);
}
// Compute the plane coefficients from the 3 given points in a straightforward manner
// calculate the plane normal n = (p2-p1) x (p3-p1) = cross (p2-p1, p3-p1)
model_coefficients.resize (model_size_);
- model_coefficients[0] = p1p0[1] * p2p0[2] - p1p0[2] * p2p0[1];
- model_coefficients[1] = p1p0[2] * p2p0[0] - p1p0[0] * p2p0[2];
- model_coefficients[2] = p1p0[0] * p2p0[1] - p1p0[1] * p2p0[0];
- model_coefficients[3] = 0.0f;
-
- // Normalize
- model_coefficients.normalize ();
+ model_coefficients.template head<3>() = cross / crossNorm;
// ... + d = 0
- model_coefficients[3] = -1.0f * (model_coefficients.template head<4>().dot (p0.matrix ()));
+ model_coefficients[3] = -1.0f * (model_coefficients.template head<3>().dot (p0));
PCL_DEBUG ("[pcl::SampleConsensusModelPlane::computeModelCoefficients] Model is (%g,%g,%g,%g).\n",
model_coefficients[0], model_coefficients[1], model_coefficients[2], model_coefficients[3]);
EIGEN_ALIGN16 Eigen::Matrix3f covariance_matrix;
Eigen::Vector4f xyz_centroid;
- computeMeanAndCovarianceMatrix (*input_, inliers, covariance_matrix, xyz_centroid);
+ if (0 == computeMeanAndCovarianceMatrix (*input_, inliers, covariance_matrix, xyz_centroid))
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelPlane::optimizeModelCoefficients] computeMeanAndCovarianceMatrix failed (returned 0) because there are no valid inliers.\n");
+ optimized_coefficients = model_coefficients;
+ return;
+ }
// Compute the model coefficients
EIGEN_ALIGN16 Eigen::Vector3f::Scalar eigen_value;
if ((p_tr - pt_tgt).squaredNorm () < thresh)
nr_p++;
}
+ PCL_DEBUG ("[pcl::SampleConsensusModelRegistration::countWithinDistance] %zu inliers of %zu total points, threshold=%g\n", nr_p, indices_->size(), threshold);
return (nr_p);
}
}
// Call Umeyama directly from Eigen
+ PCL_DEBUG_STREAM("[pcl::SampleConsensusModelRegistration::estimateRigidTransformationSVD] src and tgt:" << std::endl << src << std::endl << std::endl << tgt << std::endl);
Eigen::Matrix4d transformation_matrix = pcl::umeyama (src, tgt, false);
// Return the correct transformation
return (false);
}
- Eigen::Matrix4f temp;
+ // TODO maybe find a more stable algorithm for this?
+ Eigen::Matrix4d temp;
for (int i = 0; i < 4; i++)
{
temp (i, 0) = (*input_)[samples[i]].x;
temp (i, 2) = (*input_)[samples[i]].z;
temp (i, 3) = 1;
}
- float m11 = temp.determinant ();
+ const double m11 = temp.determinant ();
if (m11 == 0)
{
return (false); // the points don't define a sphere!
((*input_)[samples[i]].y) * ((*input_)[samples[i]].y) +
((*input_)[samples[i]].z) * ((*input_)[samples[i]].z);
}
- float m12 = temp.determinant ();
+ const double m12 = temp.determinant ();
for (int i = 0; i < 4; ++i)
{
temp (i, 1) = temp (i, 0);
temp (i, 0) = (*input_)[samples[i]].x;
}
- float m13 = temp.determinant ();
+ const double m13 = temp.determinant ();
for (int i = 0; i < 4; ++i)
{
temp (i, 2) = temp (i, 1);
temp (i, 1) = (*input_)[samples[i]].y;
}
- float m14 = temp.determinant ();
+ const double m14 = temp.determinant ();
for (int i = 0; i < 4; ++i)
{
temp (i, 2) = (*input_)[samples[i]].y;
temp (i, 3) = (*input_)[samples[i]].z;
}
- float m15 = temp.determinant ();
+ const double m15 = temp.determinant ();
// Center (x , y, z)
model_coefficients.resize (model_size_);
//////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::SampleConsensusModelSphere<PointT>::projectPoints (
- const Indices &, const Eigen::VectorXf &model_coefficients, PointCloud &projected_points, bool) const
+ const Indices &inliers, const Eigen::VectorXf &model_coefficients, PointCloud &projected_points, bool copy_data_fields) const
{
- // Needs a valid model coefficients
+ // Needs a valid set of model coefficients
if (!isModelValid (model_coefficients))
{
PCL_ERROR ("[pcl::SampleConsensusModelSphere::projectPoints] Given model is invalid!\n");
return;
}
- // Allocate enough space and copy the basics
- projected_points.resize (input_->size ());
projected_points.header = input_->header;
- projected_points.width = input_->width;
- projected_points.height = input_->height;
projected_points.is_dense = input_->is_dense;
- PCL_WARN ("[pcl::SampleConsensusModelSphere::projectPoints] Not implemented yet.\n");
- projected_points.points = input_->points;
+ // C : sphere center
+ const Eigen::Vector3d C (model_coefficients[0], model_coefficients[1], model_coefficients[2]);
+ // r : radius
+ const double r = model_coefficients[3];
+
+ // Copy all the data fields from the input cloud to the projected one?
+ if (copy_data_fields)
+ {
+ // Allocate enough space and copy the basics
+ projected_points.resize (input_->size ());
+ projected_points.width = input_->width;
+ projected_points.height = input_->height;
+
+ using FieldList = typename pcl::traits::fieldList<PointT>::type;
+ // Iterate over each point
+ for (std::size_t i = 0; i < projected_points.points.size (); ++i)
+ // Iterate over each dimension
+ pcl::for_each_type <FieldList> (NdConcatenateFunctor <PointT, PointT> (input_->points[i], projected_points.points[i]));
+
+ // Iterate through the 3d points and calculate the distances from them to the sphere
+ for (std::size_t i = 0; i < inliers.size (); ++i)
+ {
+ // what i have:
+ // P : Sample Point
+ const Eigen::Vector3d P (input_->points[inliers[i]].x, input_->points[inliers[i]].y, input_->points[inliers[i]].z);
+
+ const Eigen::Vector3d direction = (P - C).normalized();
+
+ // K : Point on Sphere
+ const Eigen::Vector3d K = C + r * direction;
+
+ projected_points.points[inliers[i]].x = static_cast<float> (K[0]);
+ projected_points.points[inliers[i]].y = static_cast<float> (K[1]);
+ projected_points.points[inliers[i]].z = static_cast<float> (K[2]);
+ }
+ }
+ else
+ {
+ // Allocate enough space and copy the basics
+ projected_points.resize (inliers.size ());
+ projected_points.width = static_cast<uint32_t> (inliers.size ());
+ projected_points.height = 1;
+
+ using FieldList = typename pcl::traits::fieldList<PointT>::type;
+ // Iterate over each point
+ for (std::size_t i = 0; i < inliers.size (); ++i)
+ // Iterate over each dimension
+ pcl::for_each_type <FieldList> (NdConcatenateFunctor <PointT, PointT> (input_->points[inliers[i]], projected_points.points[i]));
+
+ // Iterate through the 3d points and calculate the distances from them to the plane
+ for (std::size_t i = 0; i < inliers.size (); ++i)
+ {
+ // what i have:
+ // P : Sample Point
+ const Eigen::Vector3d P (input_->points[inliers[i]].x, input_->points[inliers[i]].y, input_->points[inliers[i]].z);
+
+ const Eigen::Vector3d direction = (P - C).normalized();
+
+ // K : Point on Sphere
+ const Eigen::Vector3d K = C + r * direction;
+
+ projected_points.points[i].x = static_cast<float> (K[0]);
+ projected_points.points[i].y = static_cast<float> (K[1]);
+ projected_points.points[i].z = static_cast<float> (K[2]);
+ }
+ }
}
//////////////////////////////////////////////////////////////////////////
if (sqr_distance < sqr_threshold)
{
// Need to estimate sqrt here to keep MSAC and friends general
- distances[i] = sqrt (sqr_distance);
+ distances[i] = std::sqrt (sqr_distance);
}
else
{
// Penalize outliers by doubling the distance
- distances[i] = 2 * sqrt (sqr_distance);
+ distances[i] = 2 * std::sqrt (sqr_distance);
}
}
}
Eigen::Vector4f centroid;
Eigen::Matrix3f covariance_matrix;
- computeMeanAndCovarianceMatrix (*input_, inliers, covariance_matrix, centroid);
+ if (0 == computeMeanAndCovarianceMatrix (*input_, inliers, covariance_matrix, centroid))
+ {
+ PCL_ERROR ("[pcl::SampleConsensusModelStick::optimizeModelCoefficients] computeMeanAndCovarianceMatrix failed (returned 0) because there are no valid inliers.\n");
+ optimized_coefficients = model_coefficients;
+ return;
+ }
optimized_coefficients[0] = centroid[0];
optimized_coefficients[1] = centroid[1];
SACMODEL_REGISTRATION_2D,
SACMODEL_PARALLEL_PLANE,
SACMODEL_NORMAL_PARALLEL_PLANE,
- SACMODEL_STICK
+ SACMODEL_STICK,
+ SACMODEL_ELLIPSE3D
};
}
private:
/** \brief Constructor for base SAC. */
- SampleConsensus () {};
+ SampleConsensus () = default;
public:
using Ptr = shared_ptr<SampleConsensus<T> >;
}
/** \brief Destructor for base SAC. */
- virtual ~SampleConsensus () {};
+ virtual ~SampleConsensus () = default;
/** \brief Set the distance to model threshold.
* \param[in] threshold distance to model threshold
#pragma once
#include <ctime>
-#include <climits>
+#include <limits>
#include <memory>
#include <set>
#include <boost/random/mersenne_twister.hpp> // for mt19937
};
/** \brief Destructor for base SampleConsensusModel. */
- virtual ~SampleConsensusModel () {};
+ virtual ~SampleConsensusModel () = default;
/** \brief Get a set of random data samples and return them as point
* indices.
samples.size (), indices_->size ());
// one of these will make it stop :)
samples.clear ();
- iterations = INT_MAX - 1;
+ iterations = std::numeric_limits<int>::max() - 1;
return;
}
// elements, that does not matter (and nowadays, random number generators are good)
//std::swap (shuffled_indices_[i], shuffled_indices_[i + (rand () % (index_size - i))]);
std::swap (shuffled_indices_[i], shuffled_indices_[i + (rnd () % (index_size - i))]);
- std::copy (shuffled_indices_.begin (), shuffled_indices_.begin () + sample_size, sample.begin ());
+ std::copy (shuffled_indices_.cbegin (), shuffled_indices_.cbegin () + sample_size, sample.begin ());
}
/** \brief Fills a sample array with one random sample from the indices_ vector
shuffled_indices_[i] = indices[i-1];
}
- std::copy (shuffled_indices_.begin (), shuffled_indices_.begin () + sample_size, sample.begin ());
+ std::copy (shuffled_indices_.cbegin (), shuffled_indices_.cbegin () + sample_size, sample.begin ());
}
/** \brief Check whether a model is valid given the user constraints.
SampleConsensusModelFromNormals () : normal_distance_weight_ (0.0), normals_ () {};
/** \brief Destructor. */
- virtual ~SampleConsensusModelFromNormals () {}
+ virtual ~SampleConsensusModelFromNormals () = default;
/** \brief Set the normal angular distance weight.
* \param[in] w the relative weight (between 0 and 1) to give to the angular
*/
Functor (int m_data_points) : m_data_points_ (m_data_points) {}
- virtual ~Functor () {}
+ virtual ~Functor () = default;
/** \brief Get the number of values. */
int
}
/** \brief Empty destructor */
- ~SampleConsensusModelCircle2D () {}
+ ~SampleConsensusModelCircle2D () override = default;
/** \brief Copy constructor.
* \param[in] source the model to copy into this
}
/** \brief Empty destructor */
- ~SampleConsensusModelCircle3D () {}
+ ~SampleConsensusModelCircle3D () override = default;
/** \brief Copy constructor.
* \param[in] source the model to copy into this
}
/** \brief Empty destructor */
- ~SampleConsensusModelCone () {}
+ ~SampleConsensusModelCone () override = default;
/** \brief Copy constructor.
* \param[in] source the model to copy into this
}
/** \brief Empty destructor */
- ~SampleConsensusModelCylinder () {}
+ ~SampleConsensusModelCylinder () override = default;
/** \brief Copy constructor.
* \param[in] source the model to copy into this
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2014-, Open Perception Inc.
+ *
+ * All rights reserved
+ */
+
+#pragma once
+
+#include <pcl/sample_consensus/sac_model.h>
+#include <pcl/sample_consensus/model_types.h>
+
+namespace pcl
+{
+ /** \brief SampleConsensusModelEllipse3D defines a model for 3D ellipse segmentation.
+ *
+ * The model coefficients are defined as:
+ * - \b center.x : the X coordinate of the ellipse's center
+ * - \b center.y : the Y coordinate of the ellipse's center
+ * - \b center.z : the Z coordinate of the ellipse's center
+ * - \b semi_axis.u : semi-major axis length along the local u-axis of the ellipse
+ * - \b semi_axis.v : semi-minor axis length along the local v-axis of the ellipse
+ * - \b normal.x : the X coordinate of the normal's direction
+ * - \b normal.y : the Y coordinate of the normal's direction
+ * - \b normal.z : the Z coordinate of the normal's direction
+ * - \b u.x : the X coordinate of the local u-axis of the ellipse
+ * - \b u.y : the Y coordinate of the local u-axis of the ellipse
+ * - \b u.z : the Z coordinate of the local u-axis of the ellipse
+ *
+ * For more details please refer to the following manuscript:
+ * "Semi-autonomous Prosthesis Control Using Minimal Depth Information and Vibrotactile Feedback",
+ * Miguel N. Castro & Strahinja Dosen. IEEE Transactions on Human-Machine Systems [under review]. arXiv:2210.00541.
+ * (@ github.com/mnobrecastro/pcl-ellipse-fitting)
+ *
+ * \author Miguel Nobre Castro (mnobrecastro@gmail.com)
+ * \ingroup sample_consensus
+ */
+ template <typename PointT>
+ class SampleConsensusModelEllipse3D : public SampleConsensusModel<PointT>
+ {
+ public:
+ using SampleConsensusModel<PointT>::model_name_;
+ using SampleConsensusModel<PointT>::input_;
+ using SampleConsensusModel<PointT>::indices_;
+ using SampleConsensusModel<PointT>::radius_min_;
+ using SampleConsensusModel<PointT>::radius_max_;
+
+ using PointCloud = typename SampleConsensusModel<PointT>::PointCloud;
+ using PointCloudPtr = typename SampleConsensusModel<PointT>::PointCloudPtr;
+ using PointCloudConstPtr = typename SampleConsensusModel<PointT>::PointCloudConstPtr;
+
+ using Ptr = shared_ptr<SampleConsensusModelEllipse3D<PointT> >;
+ using ConstPtr = shared_ptr<const SampleConsensusModelEllipse3D<PointT> >;
+
+ /** \brief Constructor for base SampleConsensusModelEllipse3D.
+ * \param[in] cloud the input point cloud dataset
+ * \param[in] random if true set the random seed to the current time, else set to 12345 (default: false)
+ */
+ SampleConsensusModelEllipse3D (const PointCloudConstPtr &cloud, bool random = false)
+ : SampleConsensusModel<PointT> (cloud, random)
+ {
+ model_name_ = "SampleConsensusModelEllipse3D";
+ sample_size_ = 6;
+ model_size_ = 11;
+ }
+
+ /** \brief Constructor for base SampleConsensusModelEllipse3D.
+ * \param[in] cloud the input point cloud dataset
+ * \param[in] indices a vector of point indices to be used from \a cloud
+ * \param[in] random if true set the random seed to the current time, else set to 12345 (default: false)
+ */
+ SampleConsensusModelEllipse3D (const PointCloudConstPtr &cloud,
+ const Indices &indices,
+ bool random = false)
+ : SampleConsensusModel<PointT> (cloud, indices, random)
+ {
+ model_name_ = "SampleConsensusModelEllipse3D";
+ sample_size_ = 6;
+ model_size_ = 11;
+ }
+
+ /** \brief Empty destructor */
+ ~SampleConsensusModelEllipse3D () override = default;
+
+ /** \brief Copy constructor.
+ * \param[in] source the model to copy into this
+ */
+ SampleConsensusModelEllipse3D (const SampleConsensusModelEllipse3D &source) :
+ SampleConsensusModel<PointT> ()
+ {
+ *this = source;
+ model_name_ = "SampleConsensusModelEllipse3D";
+ }
+
+ /** \brief Copy constructor.
+ * \param[in] source the model to copy into this
+ */
+ inline SampleConsensusModelEllipse3D&
+ operator = (const SampleConsensusModelEllipse3D &source)
+ {
+ SampleConsensusModel<PointT>::operator=(source);
+ return (*this);
+ }
+
+ /** \brief Check whether the given index samples can form a valid 3D ellipse model, compute the model coefficients
+ * from these samples and store them in model_coefficients. The ellipse coefficients are: x, y, R.
+ * \param[in] samples the point indices found as possible good candidates for creating a valid model
+ * \param[out] model_coefficients the resultant model coefficients
+ */
+ bool
+ computeModelCoefficients (const Indices &samples,
+ Eigen::VectorXf &model_coefficients) const override;
+
+ /** \brief Compute all distances from the cloud data to a given 3D ellipse model.
+ * \param[in] model_coefficients the coefficients of a 3D ellipse model that we need to compute distances to
+ * \param[out] distances the resultant estimated distances
+ */
+ void
+ getDistancesToModel (const Eigen::VectorXf &model_coefficients,
+ std::vector<double> &distances) const override;
+
+ /** \brief Compute all distances from the cloud data to a given 3D ellipse model.
+ * \param[in] model_coefficients the coefficients of a 3D ellipse model that we need to compute distances to
+ * \param[in] threshold a maximum admissible distance threshold for determining the inliers from the outliers
+ * \param[out] inliers the resultant model inliers
+ */
+ void
+ selectWithinDistance (const Eigen::VectorXf &model_coefficients,
+ const double threshold,
+ Indices &inliers) override;
+
+ /** \brief Count all the points which respect the given model coefficients as inliers.
+ *
+ * \param[in] model_coefficients the coefficients of a model that we need to compute distances to
+ * \param[in] threshold maximum admissible distance threshold for determining the inliers from the outliers
+ * \return the resultant number of inliers
+ */
+ std::size_t
+ countWithinDistance (const Eigen::VectorXf &model_coefficients,
+ const double threshold) const override;
+
+ /** \brief Recompute the 3d ellipse coefficients using the given inlier set and return them to the user.
+ * @note: these are the coefficients of the 3d ellipse model after refinement (e.g. after SVD)
+ * \param[in] inliers the data inliers found as supporting the model
+ * \param[in] model_coefficients the initial guess for the optimization
+ * \param[out] optimized_coefficients the resultant recomputed coefficients after non-linear optimization
+ */
+ void
+ optimizeModelCoefficients (const Indices &inliers,
+ const Eigen::VectorXf &model_coefficients,
+ Eigen::VectorXf &optimized_coefficients) const override;
+
+ /** \brief Create a new point cloud with inliers projected onto the 3d ellipse model.
+ * \param[in] inliers the data inliers that we want to project on the 3d ellipse model
+ * \param[in] model_coefficients the coefficients of a 3d ellipse model
+ * \param[out] projected_points the resultant projected points
+ * \param[in] copy_data_fields set to true if we need to copy the other data fields
+ */
+ void
+ projectPoints (const Indices &inliers,
+ const Eigen::VectorXf &model_coefficients,
+ PointCloud &projected_points,
+ bool copy_data_fields = true) const override;
+
+ /** \brief Verify whether a subset of indices verifies the given 3d ellipse model coefficients.
+ * \param[in] indices the data indices that need to be tested against the 3d ellipse model
+ * \param[in] model_coefficients the 3d ellipse model coefficients
+ * \param[in] threshold a maximum admissible distance threshold for determining the inliers from the outliers
+ */
+ bool
+ doSamplesVerifyModel (const std::set<index_t> &indices,
+ const Eigen::VectorXf &model_coefficients,
+ const double threshold) const override;
+
+ /** \brief Return a unique id for this model (SACMODEL_ELLIPSE3D). */
+ inline pcl::SacModel
+ getModelType () const override { return (SACMODEL_ELLIPSE3D); }
+
+ protected:
+ using SampleConsensusModel<PointT>::sample_size_;
+ using SampleConsensusModel<PointT>::model_size_;
+
+ /** \brief Check whether a model is valid given the user constraints.
+ * \param[in] model_coefficients the set of model coefficients
+ */
+ bool
+ isModelValid (const Eigen::VectorXf &model_coefficients) const override;
+
+ /** \brief Check if a sample of indices results in a good sample of points indices.
+ * \param[in] samples the resultant index samples
+ */
+ bool
+ isSampleGood(const Indices &samples) const override;
+
+ private:
+ /** \brief Functor for the optimization function */
+ struct OptimizationFunctor : pcl::Functor<double>
+ {
+ /** Functor constructor
+ * \param[in] indices the indices of data points to evaluate
+ * \param[in] estimator pointer to the estimator object
+ */
+ OptimizationFunctor (const pcl::SampleConsensusModelEllipse3D<PointT> *model, const Indices& indices) :
+ pcl::Functor<double> (indices.size ()), model_ (model), indices_ (indices) {}
+
+ /** Cost function to be minimized
+ * \param[in] x the variables array
+ * \param[out] fvec the resultant functions evaluations
+ * \return 0
+ */
+ int operator() (const Eigen::VectorXd &x, Eigen::VectorXd &fvec) const
+ {
+ // c : Ellipse Center
+ const Eigen::Vector3f c(x[0], x[1], x[2]);
+ // n : Ellipse (Plane) Normal
+ const Eigen::Vector3f n_axis(x[5], x[6], x[7]);
+ // x : Ellipse (Plane) X-Axis
+ const Eigen::Vector3f x_axis(x[8], x[9], x[10]);
+ // y : Ellipse (Plane) Y-Axis
+ const Eigen::Vector3f y_axis = n_axis.cross(x_axis).normalized();
+ // a : Ellipse semi-major axis (X) length
+ const float par_a(x[3]);
+ // b : Ellipse semi-minor axis (Y) length
+ const float par_b(x[4]);
+
+ // Compute the rotation matrix and its transpose
+ const Eigen::Matrix3f Rot = (Eigen::Matrix3f(3,3)
+ << x_axis(0), y_axis(0), n_axis(0),
+ x_axis(1), y_axis(1), n_axis(1),
+ x_axis(2), y_axis(2), n_axis(2))
+ .finished();
+ const Eigen::Matrix3f Rot_T = Rot.transpose();
+
+ for (int i = 0; i < values (); ++i)
+ {
+ // what i have:
+ // p : Sample Point
+ const Eigen::Vector3f p = (*model_->input_)[indices_[i]].getVector3fMap().template cast<float>();
+
+ // Local coordinates of sample point p
+ const Eigen::Vector3f p_ = Rot_T * (p - c);
+
+ // k : Point on Ellipse
+ // Calculate the shortest distance from the point to the ellipse which is
+ // given by the norm of a vector that is normal to the ellipse tangent
+ // calculated at the point it intersects the tangent.
+ const Eigen::VectorXf params = (Eigen::VectorXf(5) << par_a, par_b, 0.0, 0.0, 0.0).finished();
+ float th_opt;
+ const Eigen::Vector2f distanceVector = dvec2ellipse(params, p_(0), p_(1), th_opt);
+ fvec[i] = distanceVector.norm();
+ }
+ return (0);
+ }
+
+ const pcl::SampleConsensusModelEllipse3D<PointT> *model_;
+ const Indices &indices_;
+ };
+
+ static void
+ get_ellipse_point(const Eigen::VectorXf& par, float th, float& x, float& y);
+
+ static Eigen::Vector2f
+ dvec2ellipse(const Eigen::VectorXf& par, float u, float v, float& th_opt);
+
+ static float
+ golden_section_search(
+ const Eigen::VectorXf& par,
+ float u,
+ float v,
+ float th_min,
+ float th_max,
+ float epsilon);
+ };
+}
+
+#ifdef PCL_NO_PRECOMPILE
+#include <pcl/sample_consensus/impl/sac_model_ellipse3d.hpp>
+#endif
}
/** \brief Empty destructor */
- ~SampleConsensusModelLine () {}
+ ~SampleConsensusModelLine () override = default;
/** \brief Check whether the given index samples can form a valid line model, compute the model coefficients from
* these samples and store them internally in model_coefficients_. The line coefficients are represented by a
}
/** \brief Empty destructor */
- ~SampleConsensusModelNormalParallelPlane () {}
+ ~SampleConsensusModelNormalParallelPlane () override = default;
/** \brief Set the axis along which we need to search for a plane perpendicular to.
* \param[in] ax the axis along which we need to search for a plane perpendicular to
}
/** \brief Empty destructor */
- ~SampleConsensusModelNormalPlane () {}
+ ~SampleConsensusModelNormalPlane () override = default;
/** \brief Select all the points which respect the given model coefficients as inliers.
* \param[in] model_coefficients the coefficients of a plane model that we need to compute distances to
}
/** \brief Empty destructor */
- ~SampleConsensusModelNormalSphere () {}
+ ~SampleConsensusModelNormalSphere () override = default;
/** \brief Select all the points which respect the given model coefficients as inliers.
* \param[in] model_coefficients the coefficients of a sphere model that we need to compute distances to
}
/** \brief Empty destructor */
- ~SampleConsensusModelParallelLine () {}
+ ~SampleConsensusModelParallelLine () override = default;
/** \brief Set the axis along which we need to search for a line.
* \param[in] ax the axis along which we need to search for a line
}
/** \brief Empty destructor */
- ~SampleConsensusModelParallelPlane () {}
+ ~SampleConsensusModelParallelPlane () override = default;
/** \brief Set the axis along which we need to search for a plane perpendicular to.
* \param[in] ax the axis along which we need to search for a plane perpendicular to
}
/** \brief Empty destructor */
- ~SampleConsensusModelPerpendicularPlane () {}
+ ~SampleConsensusModelPerpendicularPlane () override = default;
/** \brief Set the axis along which we need to search for a plane perpendicular to.
* \param[in] ax the axis along which we need to search for a plane perpendicular to
}
/** \brief Empty destructor */
- ~SampleConsensusModelPlane () {}
+ ~SampleConsensusModelPlane () override = default;
/** \brief Check whether the given index samples can form a valid plane model, compute the model coefficients from
* these samples and store them internally in model_coefficients_. The plane coefficients are:
}
/** \brief Empty destructor */
- ~SampleConsensusModelRegistration () {}
+ ~SampleConsensusModelRegistration () override = default;
/** \brief Provide a pointer to the input dataset
* \param[in] cloud the const boost shared pointer to a PointCloud message
{
target_ = target;
// Cache the size and fill the target indices
- const index_t target_size = static_cast<index_t> (target->size ());
+ const auto target_size = static_cast<index_t> (target->size ());
indices_tgt_.reset (new Indices (target_size));
std::iota (indices_tgt_->begin (), indices_tgt_->end (), 0);
computeOriginalIndexMapping ();
}
/** \brief Empty destructor */
- virtual ~SampleConsensusModelRegistration2D () {}
+ virtual ~SampleConsensusModelRegistration2D () = default;
/** \brief Compute all distances from the transformed points to their correspondences
* \param[in] model_coefficients the 4x4 transformation matrix
}
/** \brief Empty destructor */
- ~SampleConsensusModelSphere () {}
+ ~SampleConsensusModelSphere () override = default;
/** \brief Copy constructor.
* \param[in] source the model to copy into this
}
/** \brief Empty destructor */
- ~SampleConsensusModelStick () {}
+ ~SampleConsensusModelStick () override = default;
/** \brief Check whether the given index samples can form a valid stick model, compute the model coefficients from
* these samples and store them internally in model_coefficients_. The stick coefficients are represented by a
<li>\link pcl::SampleConsensusModelParallelPlane SACMODEL_PARALLEL_PLANE \endlink - a model for determining a plane <b>parallel</b> to a user-specified axis, within a maximum specified angular deviation. The plane coefficients are similar to \link pcl::SampleConsensusModelPlane SACMODEL_PLANE \endlink.</li>
<li>\link pcl::SampleConsensusModelNormalParallelPlane SACMODEL_NORMAL_PARALLEL_PLANE \endlink defines a model for 3D plane segmentation using additional surface normal constraints. The plane normal must lie <b>parallel</b> to a user-specified axis. SACMODEL_NORMAL_PARALLEL_PLANE therefore is equivalent to SACMODEL_NORMAL_PLANE + SACMODEL_PERPENDICULAR_PLANE. The plane coefficients are similar to \link pcl::SampleConsensusModelPlane SACMODEL_PLANE \endlink.</li>
<li>\link pcl::SampleConsensusModelStick SACMODEL_STICK \endlink - a model for 3D stick segmentation. A stick is a line with a user given minimum/maximum width.</li>
+ <li>\link pcl::SampleConsensusModelEllipse3D SACMODEL_ELLIPSE3D \endlink - used to determine 3D ellipses in a plane. The ellipses's <b>eleven</b> coefficients are given by its center and radius as: [<b>center.x, center.y, center.z, semi_axis.u, semi_axis.v, normal.x, normal.y, normal.z, u.x, u.y, u.z</b>]</li>
</ul>
The following list describes the robust sample consensus estimators implemented:
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2014-, Open Perception Inc.
+ *
+ * All rights reserved
+ */
+
+#include <pcl/sample_consensus/impl/sac_model_ellipse3d.hpp>
+
+#ifndef PCL_NO_PRECOMPILE
+#include <pcl/impl/instantiate.hpp>
+#include <pcl/point_types.h>
+// Instantiations of specific point types
+#ifdef PCL_ONLY_CORE_POINT_TYPES
+ PCL_INSTANTIATE(SampleConsensusModelEllipse3D, (pcl::PointXYZ)(pcl::PointXYZI)(pcl::PointXYZRGBA)(pcl::PointXYZRGB)(pcl::PointXYZRGBNormal))
+#else
+ PCL_INSTANTIATE(SampleConsensusModelEllipse3D, PCL_XYZ_POINT_TYPES)
+#endif
+#endif // PCL_NO_PRECOMPILE
+
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS flann)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS flann)
PCL_ADD_DOC("${SUBSYS_NAME}")
/** \brief Destructor for KdTree. */
- ~BruteForce ()
- {
- }
+ ~BruteForce () override = default;
/** \brief Search for the k-nearest neighbors for the given query point.
* \param[in] point the given query point
/** \brief destructor
*/
- virtual ~FlannIndexCreator () {}
+ virtual ~FlannIndexCreator () = default;
};
using FlannIndexCreatorPtr = shared_ptr<FlannIndexCreator>;
KdTreeIndexCreator (unsigned int max_leaf_size=15) : max_leaf_size_ (max_leaf_size){}
/** \brief Empty destructor */
- ~KdTreeIndexCreator () {}
+ ~KdTreeIndexCreator () override = default;
/** \brief Create a FLANN Index from the input data.
* \param[in] data The FLANN matrix containing the input.
* a maximum of max_leaf_size points per leaf node. Higher values make index creation
* cheaper, but search more costly (and the other way around).
*/
- KMeansIndexCreator (){}
+ KMeansIndexCreator () = default;
/** \brief Empty destructor */
- virtual ~KMeansIndexCreator () {}
+ virtual ~KMeansIndexCreator () = default;
/** \brief Create a FLANN Index from the input data.
* \param[in] data The FLANN matrix containing the input.
KdTreeMultiIndexCreator (int trees = 4) : trees_ (trees) {}
/** \brief Empty destructor */
- virtual ~KdTreeMultiIndexCreator () {}
+ virtual ~KdTreeMultiIndexCreator () = default;
/** \brief Create a FLANN Index from the input data.
* \param[in] data The FLANN matrix containing the input.
/** \brief Destructor for FlannSearch. */
- ~FlannSearch ();
+ ~FlannSearch () override;
//void
/** \brief Destructor for KdTree. */
- ~KdTree ()
- {
- }
+ ~KdTree () override = default;
/** \brief Provide a pointer to the point representation to use to convert points into k-D vectors.
* \param[in] point_representation the const boost shared pointer to a PointRepresentation
/** \brief Empty Destructor. */
- ~Octree ()
- {
- }
+ ~Octree () override = default;
/** \brief Provide a pointer to the input dataset.
* \param[in] cloud the const boost shared pointer to a PointCloud message
}
/** \brief Empty deconstructor. */
- ~OrganizedNeighbor () {}
+ ~OrganizedNeighbor () override = default;
/** \brief Test whether this search-object is valid (input is organized AND from projective device)
* User should use this method after setting the input cloud, since setInput just prints an error
/** Destructor. */
virtual
- ~Search ()
- {
- }
+ ~Search () = default;
/** \brief Returns the search method name
*/
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
ApproximateProgressiveMorphologicalFilter ();
- ~ApproximateProgressiveMorphologicalFilter ();
+ ~ApproximateProgressiveMorphologicalFilter () override;
/** \brief Get the maximum window size to be used in filtering ground returns. */
inline int
/** \brief Empty destructor for comparator. */
virtual
- ~Comparator ()
- {
- }
+ ~Comparator () = default;
/** \brief Set the input cloud for the comparator.
* \param[in] cloud the point cloud this comparator will operate on
public:
CPCSegmentation ();
- ~CPCSegmentation ();
+ ~CPCSegmentation () override;
/** \brief Merge supervoxels using cuts through local convexities. The input parameters are generated by using the \ref SupervoxelClustering class. To retrieve the output use the \ref relabelCloud method.
* \note There are three ways to retrieve the segmentation afterwards (inherited from \ref LCCPSegmentation): \ref relabelCloud, \ref getSupervoxelToSegmentMap and \ref getSupervoxelToSegmentMap */
/** \brief Destructor for PlaneCoefficientComparator. */
- ~EdgeAwarePlaneComparator ()
- {
- }
+ ~EdgeAwarePlaneComparator () override
+ = default;
/** \brief Set a distance map to use. For an example of a valid distance map see
* IntegralImageNormalEstimation::getDistanceMap
using pcl::PlaneCoefficientComparator<PointT, PointNT>::distance_threshold_;
/** \brief Empty constructor for PlaneCoefficientComparator. */
- EuclideanPlaneCoefficientComparator ()
- {
- }
+ EuclideanPlaneCoefficientComparator () = default;
/** \brief Destructor for PlaneCoefficientComparator. */
- ~EuclideanPlaneCoefficientComparator ()
- {
- }
+ ~EuclideanPlaneCoefficientComparator () = default;
/** \brief Compare two neighboring points, by using normal information, and euclidean distance information.
* \param[in] idx1 The index of the first point.
#pragma once
-#include <cfloat> // for FLT_MAX
+#include <limits>
#include <pcl/pcl_base.h>
/** \brief Empty constructor. */
ExtractPolygonalPrismData () : planar_hull_ (), min_pts_hull_ (3),
- height_limit_min_ (0), height_limit_max_ (FLT_MAX),
+ height_limit_min_ (0),
+ height_limit_max_(std::numeric_limits<float>::max()),
vpx_ (0), vpy_ (0), vpz_ (0)
{};
}
/** \brief Get the height limits (min/max) as set by the user. The
- * default values are -FLT_MAX, FLT_MAX.
+ * default values are 0, std::numeric_limits<float>::max().
* \param[out] height_min the resultant min height limit
* \param[out] height_max the resultant max height limit
*/
/// construct a maxflow/mincut problem with estimated max_nodes
BoykovKolmogorov (std::size_t max_nodes = 0);
/// destructor
- virtual ~BoykovKolmogorov () {}
+ virtual ~BoykovKolmogorov () = default;
/// get number of nodes in the graph
std::size_t
numNodes () const { return nodes_.size (); }
/// Gaussian structure
struct Gaussian
{
- Gaussian () {}
+ Gaussian () = default;
/// mean of the gaussian
Color mu;
/// covariance matrix of the gaussian
/// Initialize GMM with ddesired number of gaussians.
GMM (std::size_t K) : gaussians_ (K) {}
/// Destructor
- ~GMM () {}
+ ~GMM () = default;
/// \return K
std::size_t
getK () const { return gaussians_.size (); }
, initialized_ (false)
{}
/// Destructor
- ~GrabCut () {};
+ ~GrabCut () override = default;
// /// Set input cloud
void
setInputCloud (const PointCloudConstPtr& cloud) override;
/** \brief Destructor for GroundPlaneComparator. */
- ~GroundPlaneComparator ()
- {
- }
+ ~GroundPlaneComparator () override
+ = default;
/** \brief Provide the input cloud.
* \param[in] cloud the input point cloud.
*/
{
// Normal must be similar to neighbor
// Normal must be similar to expected normal
- float threshold = distance_threshold_;
- if (depth_dependent_)
- {
- Eigen::Vector3f vec = (*input_)[idx1].getVector3fMap ();
+ // TODO check logic in this class: which member variables are needed?
+ // float threshold = distance_threshold_;
+ // if (depth_dependent_)
+ // {
+ // Eigen::Vector3f vec = (*input_)[idx1].getVector3fMap ();
- float z = vec.dot (z_axis_);
- threshold *= z * z;
- }
+ // float z = vec.dot (z_axis_);
+ // threshold *= z * z;
+ // }
return ( ((*normals_)[idx1].getNormalVector3fMap ().dot (desired_road_axis_) > road_angular_threshold_) &&
((*normals_)[idx1].getNormalVector3fMap ().dot ((*normals_)[idx2].getNormalVector3fMap () ) > angular_threshold_ ));
#include <pcl/common/common.h>
#include <pcl/common/io.h>
#include <pcl/filters/morphological_filter.h>
-#include <pcl/filters/extract_indices.h>
#include <pcl/segmentation/approximate_progressive_morphological_filter.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
-pcl::ApproximateProgressiveMorphologicalFilter<PointT>::~ApproximateProgressiveMorphologicalFilter ()
-{
-}
+pcl::ApproximateProgressiveMorphologicalFilter<PointT>::~ApproximateProgressiveMorphologicalFilter () = default;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
}
template <typename PointT>
-pcl::CPCSegmentation<PointT>::~CPCSegmentation ()
-{
-}
+pcl::CPCSegmentation<PointT>::~CPCSegmentation () = default;
template <typename PointT> void
pcl::CPCSegmentation<PointT>::segment ()
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
-pcl::CrfNormalSegmentation<PointT>::CrfNormalSegmentation ()
-{
-}
+pcl::CrfNormalSegmentation<PointT>::CrfNormalSegmentation () = default;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
-pcl::CrfNormalSegmentation<PointT>::~CrfNormalSegmentation ()
-{
-}
+pcl::CrfNormalSegmentation<PointT>::~CrfNormalSegmentation () = default;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
-pcl::CrfSegmentation<PointT>::~CrfSegmentation ()
-{
-}
+pcl::CrfSegmentation<PointT>::~CrfSegmentation () = default;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
if (n_link.nb_links > 0)
{
const auto point_index = (*indices_) [i_point];
- std::vector<float>::const_iterator weights_it = n_link.weights.begin ();
+ auto weights_it = n_link.weights.begin ();
for (auto indices_it = n_link.indices.cbegin (); indices_it != n_link.indices.cend (); ++indices_it, ++weights_it)
{
if ((*indices_it != point_index) && (*indices_it != UNAVAILABLE))
}
template <typename PointT>
-pcl::LCCPSegmentation<PointT>::~LCCPSegmentation ()
-{
-}
+pcl::LCCPSegmentation<PointT>::~LCCPSegmentation () = default;
template <typename PointT> void
pcl::LCCPSegmentation<PointT>::reset ()
std::map<std::uint32_t, VertexID> label_ID_map;
// Add all supervoxel labels as vertices
- for (typename std::map<std::uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
+ for (auto svlabel_itr = sv_label_to_supervoxel_map_.begin ();
svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
{
const std::uint32_t& sv_label = svlabel_itr->first;
// Initialization
// clear the processed_ map
seg_label_to_sv_list_map_.clear ();
- for (typename std::map<std::uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
+ for (auto svlabel_itr = sv_label_to_supervoxel_map_.begin ();
svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
{
const std::uint32_t& sv_label = svlabel_itr->first;
{
// clear the processed_ map
seg_label_to_sv_list_map_.clear ();
- for (typename std::map<std::uint32_t, typename pcl::Supervoxel<PointT>::Ptr>::iterator svlabel_itr = sv_label_to_supervoxel_map_.begin ();
+ for (auto svlabel_itr = sv_label_to_supervoxel_map_.begin ();
svlabel_itr != sv_label_to_supervoxel_map_.end (); ++svlabel_itr)
{
const std::uint32_t& sv_label = svlabel_itr->first;
if ( graph_is_valid_ && unary_potentials_are_valid_ && binary_potentials_are_valid_ )
{
clusters.reserve (clusters_.size ());
- std::copy (clusters_.begin (), clusters_.end (), std::back_inserter (clusters));
+ std::copy (clusters_.cbegin (), clusters_.cend (), std::back_inserter (clusters));
deinitCompute ();
return;
}
assembleLabels (residual_capacity);
clusters.reserve (clusters_.size ());
- std::copy (clusters_.begin (), clusters_.end (), std::back_inserter (clusters));
+ std::copy (clusters_.cbegin (), clusters_.cend (), std::back_inserter (clusters));
deinitCompute ();
}
template <typename PointT> bool
pcl::MinCutSegmentation<PointT>::addEdge (int source, int target, double weight)
{
- std::set<int>::iterator iter_out = edge_marker_[source].find (target);
+ auto iter_out = edge_marker_[source].find (target);
if ( iter_out != edge_marker_[source].end () )
return (false);
OutEdgeIterator src_edge_end;
std::pair<EdgeDescriptor, bool> sink_edge;
- for (boost::tie (src_edge_iter, src_edge_end) = boost::out_edges (source_, *graph_); src_edge_iter != src_edge_end; src_edge_iter++)
+ for (boost::tie (src_edge_iter, src_edge_end) = boost::out_edges (source_, *graph_); src_edge_iter != src_edge_end; ++src_edge_iter)
{
double source_weight = 0.0;
double sink_weight = 0.0;
edge_marker.clear ();
edge_marker.resize (indices_->size () + 2, out_edges_marker);
- for (boost::tie (vertex_iter, vertex_end) = boost::vertices (*graph_); vertex_iter != vertex_end; vertex_iter++)
+ for (boost::tie (vertex_iter, vertex_end) = boost::vertices (*graph_); vertex_iter != vertex_end; ++vertex_iter)
{
VertexDescriptor source_vertex = *vertex_iter;
if (source_vertex == source_ || source_vertex == sink_)
continue;
- for (boost::tie (edge_iter, edge_end) = boost::out_edges (source_vertex, *graph_); edge_iter != edge_end; edge_iter++)
+ for (boost::tie (edge_iter, edge_end) = boost::out_edges (source_vertex, *graph_); edge_iter != edge_end; ++edge_iter)
{
//If this is not the edge of the graph, but the reverse fictitious edge that is needed for the algorithm then continue
EdgeDescriptor reverse_edge = (*reverse_edges_)[*edge_iter];
//If we already changed weight for this edge then continue
VertexDescriptor target_vertex = boost::target (*edge_iter, *graph_);
- std::set<VertexDescriptor>::iterator iter_out = edge_marker[static_cast<int> (source_vertex)].find (target_vertex);
+ auto iter_out = edge_marker[static_cast<int> (source_vertex)].find (target_vertex);
if ( iter_out != edge_marker[static_cast<int> (source_vertex)].end () )
continue;
clusters_.resize (2, segment);
OutEdgeIterator edge_iter, edge_end;
- for ( boost::tie (edge_iter, edge_end) = boost::out_edges (source_, *graph_); edge_iter != edge_end; edge_iter++ )
+ for ( boost::tie (edge_iter, edge_end) = boost::out_edges (source_, *graph_); edge_iter != edge_end; ++edge_iter )
{
if (labels[edge_iter->m_target] == 1)
{
if (!clusters_.empty ())
{
- colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
+ colored_cloud.reset(new pcl::PointCloud<pcl::PointXYZRGB>);
unsigned char foreground_color[3] = {255, 255, 255};
unsigned char background_color[3] = {255, 0, 0};
colored_cloud->width = (clusters_[0].indices.size () + clusters_[1].indices.size ());
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
-pcl::ProgressiveMorphologicalFilter<PointT>::~ProgressiveMorphologicalFilter ()
-{
-}
+pcl::ProgressiveMorphologicalFilter<PointT>::~ProgressiveMorphologicalFilter () = default;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
assembleRegions ();
clusters.resize (clusters_.size ());
- std::vector<pcl::PointIndices>::iterator cluster_iter_input = clusters.begin ();
+ auto cluster_iter_input = clusters.begin ();
for (const auto& cluster : clusters_)
{
if ((cluster.indices.size () >= min_pts_per_cluster_) &&
if (!clusters_.empty ())
{
- colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGB>)->makeShared ();
+ colored_cloud.reset(new pcl::PointCloud<pcl::PointXYZRGB>);
srand (static_cast<unsigned int> (time (nullptr)));
std::vector<unsigned char> colors;
if (!clusters_.empty ())
{
- colored_cloud = (new pcl::PointCloud<pcl::PointXYZRGBA>)->makeShared ();
+ colored_cloud.reset(new pcl::PointCloud<pcl::PointXYZRGBA>);
srand (static_cast<unsigned int> (time (nullptr)));
std::vector<unsigned char> colors;
findSegmentNeighbours ();
applyRegionMergingAlgorithm ();
- std::vector<pcl::PointIndices>::iterator cluster_iter = clusters_.begin ();
+ auto cluster_iter = clusters_.begin ();
while (cluster_iter != clusters_.end ())
{
if (cluster_iter->indices.size () < min_pts_per_cluster_ ||
}
clusters.reserve (clusters_.size ());
- std::copy (clusters_.begin (), clusters_.end (), std::back_inserter (clusters));
+ std::copy (clusters_.cbegin (), clusters_.cend (), std::back_inserter (clusters));
deinitCompute ();
}
#include <pcl/sample_consensus/sac_model_sphere.h>
#include <pcl/sample_consensus/sac_model_normal_sphere.h>
#include <pcl/sample_consensus/sac_model_stick.h>
+#include <pcl/sample_consensus/sac_model_ellipse3d.h>
#include <pcl/memory.h> // for static_pointer_cast
}
break;
}
+ case SACMODEL_ELLIPSE3D:
+ {
+ PCL_DEBUG("[pcl::%s::initSACModel] Using a model of type: SACMODEL_ELLIPSE3D\n", getClassName().c_str());
+ model_.reset(new SampleConsensusModelEllipse3D<PointT>(input_, *indices_));
+ typename SampleConsensusModelEllipse3D<PointT>::Ptr model_ellipse3d = static_pointer_cast<SampleConsensusModelEllipse3D<PointT>>(model_);
+ double min_radius, max_radius;
+ model_ellipse3d->getRadiusLimits(min_radius, max_radius);
+ if (radius_min_ != min_radius && radius_max_ != max_radius) {
+ PCL_DEBUG("[pcl::%s::initSACModel] Setting radius limits to %f/%f\n", getClassName().c_str(), radius_min_, radius_max_);
+ model_ellipse3d->setRadiusLimits(radius_min_, radius_max_);
+ }
+ break;
+ }
+ case SACMODEL_CYLINDER:
+ case SACMODEL_NORMAL_PLANE:
+ case SACMODEL_NORMAL_PARALLEL_PLANE:
+ case SACMODEL_CONE:
+ case SACMODEL_NORMAL_SPHERE:
+ {
+ PCL_ERROR ("[pcl::%s::initSACModel] Use SACSegmentationFromNormals for this model instead!\n", getClassName ().c_str ());
+ return (false);
+ }
default:
{
PCL_ERROR ("[pcl::%s::initSACModel] No valid model given!\n", getClassName ().c_str ());
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
-pcl::SupervoxelClustering<PointT>::~SupervoxelClustering ()
-{
-
-}
+pcl::SupervoxelClustering<PointT>::~SupervoxelClustering () = default;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
{
voxel_centroid_cloud_.reset (new PointCloudT);
voxel_centroid_cloud_->resize (adjacency_octree_->getLeafCount ());
- typename LeafVectorT::iterator leaf_itr = adjacency_octree_->begin ();
- typename PointCloudT::iterator cent_cloud_itr = voxel_centroid_cloud_->begin ();
+ auto leaf_itr = adjacency_octree_->begin ();
+ auto cent_cloud_itr = voxel_centroid_cloud_->begin ();
for (int idx = 0 ; leaf_itr != adjacency_octree_->end (); ++leaf_itr, ++cent_cloud_itr, ++idx)
{
VoxelData& new_voxel_data = (*leaf_itr)->getData ();
//Verify that input normal cloud size is same as input cloud size
assert (input_normals_->size () == input_->size ());
//For every point in the input cloud, find its corresponding leaf
- typename NormalCloudT::const_iterator normal_itr = input_normals_->begin ();
- for (typename PointCloudT::const_iterator input_itr = input_->begin (); input_itr != input_->end (); ++input_itr, ++normal_itr)
+ auto normal_itr = input_normals_->begin ();
+ for (auto input_itr = input_->begin (); input_itr != input_->end (); ++input_itr, ++normal_itr)
{
//If the point is not finite we ignore it
if ( !pcl::isFinite<PointT> (*input_itr))
indices.reserve (81);
//Push this point
indices.push_back (new_voxel_data.idx_);
- for (typename LeafContainerT::const_iterator neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
+ for (auto neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
{
VoxelData& neighb_voxel_data = (*neighb_itr)->getData ();
//Push neighbor index
indices.push_back (neighb_voxel_data.idx_);
//Get neighbors neighbors, push onto cloud
- for (typename LeafContainerT::const_iterator neighb_neighb_itr=(*neighb_itr)->cbegin (); neighb_neighb_itr!=(*neighb_itr)->cend (); ++neighb_neighb_itr)
+ for (auto neighb_neighb_itr=(*neighb_itr)->cbegin (); neighb_neighb_itr!=(*neighb_itr)->cend (); ++neighb_neighb_itr)
{
VoxelData& neighb2_voxel_data = (*neighb_neighb_itr)->getData ();
indices.push_back (neighb2_voxel_data.idx_);
pcl::PointCloud<pcl::PointXYZL> xyzl_copy;
copyPointCloud (*voxels, xyzl_copy);
- pcl::PointCloud<pcl::PointXYZL>::iterator xyzl_copy_itr = xyzl_copy.begin ();
+ auto xyzl_copy_itr = xyzl_copy.begin ();
for ( ; xyzl_copy_itr != xyzl_copy.end (); ++xyzl_copy_itr)
xyzl_copy_itr->label = sv_itr->getLabel ();
pcl::PointCloud<pcl::PointXYZL>::Ptr labeled_cloud (new pcl::PointCloud<pcl::PointXYZL>);
pcl::copyPointCloud (*input_,*labeled_cloud);
- typename pcl::PointCloud <PointT>::const_iterator i_input = input_->begin ();
+ auto i_input = input_->begin ();
for (auto i_labeled = labeled_cloud->begin (); i_labeled != labeled_cloud->end (); ++i_labeled,++i_input)
{
if ( !pcl::isFinite<PointT> (*i_input))
{
pcl::PointCloud<pcl::PointNormal>::Ptr normal_cloud (new pcl::PointCloud<pcl::PointNormal>);
normal_cloud->resize (supervoxel_clusters.size ());
- pcl::PointCloud<pcl::PointNormal>::iterator normal_cloud_itr = normal_cloud->begin ();
+ auto normal_cloud_itr = normal_cloud->begin ();
for (auto sv_itr = supervoxel_clusters.cbegin (), sv_itr_end = supervoxel_clusters.cend ();
sv_itr != sv_itr_end; ++sv_itr, ++normal_cloud_itr)
{
for (auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr)
{
//for each neighbor of the leaf
- for (typename LeafContainerT::const_iterator neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
+ for (auto neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
{
//Get a reference to the data contained in the leaf
VoxelData& neighbor_voxel = ((*neighb_itr)->getData ());
indices.reserve (81);
//Push this point
indices.push_back (voxel_data.idx_);
- for (typename LeafContainerT::const_iterator neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
+ for (auto neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
{
//Get a reference to the data contained in the leaf
VoxelData& neighbor_voxel_data = ((*neighb_itr)->getData ());
{
indices.push_back (neighbor_voxel_data.idx_);
//Also check its neighbors
- for (typename LeafContainerT::const_iterator neighb_neighb_itr=(*neighb_itr)->cbegin (); neighb_neighb_itr!=(*neighb_itr)->cend (); ++neighb_neighb_itr)
+ for (auto neighb_neighb_itr=(*neighb_itr)->cbegin (); neighb_neighb_itr!=(*neighb_itr)->cend (); ++neighb_neighb_itr)
{
VoxelData& neighb_neighb_voxel_data = (*neighb_neighb_itr)->getData ();
if (neighb_neighb_voxel_data.owner_ == this)
voxels.reset (new pcl::PointCloud<PointT>);
voxels->clear ();
voxels->resize (leaves_.size ());
- typename pcl::PointCloud<PointT>::iterator voxel_itr = voxels->begin ();
+ auto voxel_itr = voxels->begin ();
for (auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr, ++voxel_itr)
{
const VoxelData& leaf_data = (*leaf_itr)->getData ();
normals.reset (new pcl::PointCloud<Normal>);
normals->clear ();
normals->resize (leaves_.size ());
- typename pcl::PointCloud<Normal>::iterator normal_itr = normals->begin ();
+ auto normal_itr = normals->begin ();
for (auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr, ++normal_itr)
{
const VoxelData& leaf_data = (*leaf_itr)->getData ();
for (auto leaf_itr = leaves_.cbegin (); leaf_itr != leaves_.cend (); ++leaf_itr)
{
//for each neighbor of the leaf
- for (typename LeafContainerT::const_iterator neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
+ for (auto neighb_itr=(*leaf_itr)->cbegin (); neighb_itr!=(*leaf_itr)->cend (); ++neighb_itr)
{
//Get a reference to the data contained in the leaf
VoxelData& neighbor_voxel = ((*neighb_itr)->getData ());
#include <flann/algorithms/linear_index.h> // for flann::LinearIndexParams
#include <flann/util/matrix.h> // for flann::Matrix
+#include <pcl/features/normal_3d.h> // for NormalEstimation
#include <pcl/segmentation/unary_classifier.h>
#include <pcl/common/io.h>
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
-pcl::UnaryClassifier<PointT>::~UnaryClassifier ()
-{
-}
+pcl::UnaryClassifier<PointT>::~UnaryClassifier () = default;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
{
// find the 'label' field index
std::vector <pcl::PCLPointField> fields;
- int label_idx = -1;
- pcl::PointCloud <PointT> point;
- label_idx = pcl::getFieldIndex<PointT> ("label", fields);
+ const int label_idx = pcl::getFieldIndex<PointT> ("label", fields);
if (label_idx != -1)
{
for (const auto& point: *in)
{
// get the 'label' field
- std::uint32_t label;
+ std::uint32_t label;
memcpy (&label, reinterpret_cast<const char*> (&point) + fields[label_idx].offset, sizeof(std::uint32_t));
// check if label exist
{
// Query point
flann::Matrix<float> p = flann::Matrix<float>(new float[n_col], 1, n_col);
- memcpy (&p.ptr ()[0], (*query_features)[i].histogram, p.cols * p.rows * sizeof (float));
+ std::copy((*query_features)[i].histogram, (*query_features)[i].histogram + n_col, p.ptr());
flann::Matrix<int> indices (new int[k], 1, k);
flann::Matrix<float> distances (new float[k], 1, k);
/** \brief Destructor that frees memory. */
- ~MinCutSegmentation ();
+ ~MinCutSegmentation () override;
/** \brief This method simply sets the input point cloud.
* \param[in] cloud the const boost shared pointer to a PointCloud
/** \brief Destructor for OrganizedConnectedComponentSegmentation. */
- ~OrganizedConnectedComponentSegmentation ()
- {
- }
+ ~OrganizedConnectedComponentSegmentation () override = default;
/** \brief Provide a pointer to the comparator to be used for segmentation.
* \param[in] compare the comparator
/** \brief Destructor for OrganizedMultiPlaneSegmentation. */
- ~OrganizedMultiPlaneSegmentation ()
- {
- }
+ ~OrganizedMultiPlaneSegmentation () override = default;
/** \brief Provide a pointer to the input normals.
* \param[in] normals the input normal cloud
PlanarPolygonFusion () : regions_ () {}
/** \brief Destructor */
- virtual ~PlanarPolygonFusion () {}
+ virtual ~PlanarPolygonFusion () = default;
/** \brief Reset the state (clean the list of planar models). */
void
public:
/** \brief Empty constructor for PlanarRegion. */
- PlanarRegion ()
- {}
+ PlanarRegion () = default;
/** \brief Constructor for Planar region from a Region3D and a PlanarPolygon.
* \param[in] region a Region3D for the input data
}
/** \brief Destructor. */
- ~PlanarRegion () {}
+ ~PlanarRegion () override = default;
/** \brief Constructor for PlanarRegion.
* \param[in] centroid the centroid of the region.
/** \brief Destructor for PlaneCoefficientComparator. */
- ~PlaneCoefficientComparator ()
- {
- }
+ ~PlaneCoefficientComparator () override = default;
void
setInputCloud (const PointCloudConstPtr& cloud) override
}
/** \brief Destructor for PlaneCoefficientComparator. */
- ~PlaneRefinementComparator ()
- {
- }
+ ~PlaneRefinementComparator () override = default;
/** \brief Set the vector of model coefficients to which we will compare.
* \param[in] models a vector of model coefficients produced by the initial segmentation step.
ProgressiveMorphologicalFilter ();
- ~ProgressiveMorphologicalFilter ();
+ ~ProgressiveMorphologicalFilter () override;
/** \brief Get the maximum window size to be used in filtering ground returns. */
inline int
}
/** \brief Destructor. */
- virtual ~Region3D () {}
+ virtual ~Region3D () = default;
/** \brief Get the centroid of the region. */
inline Eigen::Vector3f
* Implements the well known Region Growing algorithm used for segmentation.
* Description can be found in the article
* "Segmentation of point clouds using smoothness constraint"
- * by T. Rabbania, F. A. van den Heuvelb, G. Vosselmanc.
+ * by T. Rabbani, F. A. van den Heuvel, G. Vosselman.
* In addition to residual test, the possibility to test curvature is added.
* \ingroup segmentation
*/
* finding KNN. In other words it frees memory.
*/
- ~RegionGrowing ();
+ ~RegionGrowing () override;
/** \brief Get the minimum number of points that a cluster needs to contain in order to be considered valid. */
pcl::uindex_t
/** \brief This function implements the algorithm described in the article
* "Segmentation of point clouds using smoothness constraint"
- * by T. Rabbania, F. A. van den Heuvelb, G. Vosselmanc.
+ * by T. Rabbani, F. A. van den Heuvel, G. Vosselman.
*/
void
applySmoothRegionGrowingAlgorithm ();
/** \brief If set to true then residual test will be done during segmentation. */
bool residual_flag_;
- /** \brief Thershold used for testing the smoothness between points. */
+ /** \brief Threshold used for testing the smoothness between points. */
float theta_threshold_;
- /** \brief Thershold used in residual test. */
+ /** \brief Threshold used in residual test. */
float residual_threshold_;
- /** \brief Thershold used in curvature test. */
+ /** \brief Threshold used in curvature test. */
float curvature_threshold_;
/** \brief Number of neighbours to find. */
unsigned int neighbour_number_;
- /** \brief Serch method that will be used for KNN. */
+ /** \brief Search method that will be used for KNN. */
KdTreePtr search_;
/** \brief Contains normals of the points that will be segmented. */
/** \brief Destructor that frees memory. */
- ~RegionGrowingRGB ();
+ ~RegionGrowingRGB () override;
/** \brief Returns the color threshold value used for testing if points belong to the same region. */
float
/** \brief Destructor for RGBPlaneCoefficientComparator. */
- ~RGBPlaneCoefficientComparator ()
- {
- }
+ ~RGBPlaneCoefficientComparator () = default;
/** \brief Set the tolerance in color space between neighboring points, to be considered part of the same plane.
* \param[in] color_threshold The distance in color space
}
/** \brief Empty destructor. */
- ~SACSegmentation () { /*srv_.reset ();*/ };
+ ~SACSegmentation () override = default;
/** \brief The type of model to use (user given parameter).
* \param[in] model the model type (check \a model_types.h)
* finding neighbors. In other words it frees memory.
*/
- ~SupervoxelClustering ();
+ ~SupervoxelClustering () override;
/** \brief Set the resolution of the octree voxels */
void
#include <pcl/point_types.h>
#include <pcl/features/fpfh.h>
-#include <pcl/features/normal_3d.h>
#include <pcl/ml/kmeans.h>
- \ref sample_consensus "sample_consensus"
- \ref kdtree "kdtree"
- \ref octree "octree"
+ - \ref features "features"
*/
if ((u < 0) && (v < 0)) return flow_value_;
if (u < 0) { return source_edges_[v]; }
if (v < 0) { return target_edges_[u]; }
- capacitated_edge::const_iterator it = nodes_[u].find (v);
+ auto it = nodes_[u].find (v);
if (it == nodes_[u].end ()) return 0.0;
return it->second;
}
if (source_edges_[u] == 0.0) continue;
// augment s-u-v-t paths
- for (std::map<int, double>::iterator it = nodes_[u].begin (); it != nodes_[u].end (); ++it)
+ for (auto it = nodes_[u].begin (); it != nodes_[u].end (); ++it)
{
const int v = it->first;
if ((it->second == 0.0) || (target_edges_[v] == 0.0)) continue;
assert ((v >= 0) && (v < (int)nodes_.size ()));
assert (u != v);
- capacitated_edge::iterator it = nodes_[u].find (v);
+ auto it = nodes_[u].find (v);
if (it == nodes_[u].end ())
{
assert (cap_uv + cap_vu >= 0.0);
}
else
{
- capacitated_edge::iterator jt = nodes_[v].find (u);
+ auto jt = nodes_[v].find (u);
it->second += cap_uv;
jt->second += cap_vu;
assert (it->second + jt->second >= 0.0);
const int u = active_head_;
if (cut_[u] == SOURCE) {
- for (capacitated_edge::iterator it = nodes_[u].begin (); it != nodes_[u].end (); ++it)
+ for (auto it = nodes_[u].begin (); it != nodes_[u].end (); ++it)
{
if (it->second > 0.0)
{
}
else
{
- for (capacitated_edge::iterator it = nodes_[u].begin (); it != nodes_[u].end (); ++it)
+ for (auto it = nodes_[u].begin (); it != nodes_[u].end (); ++it)
{
if (cut_[it->first] == TARGET) continue;
if (nodes_[it->first][u] > 0.0)
// look for new parent
bool b_free_orphan = true;
- for (capacitated_edge::iterator jt = nodes_[u].begin (); jt != nodes_[u].end (); ++jt) {
+ for (auto jt = nodes_[u].begin (); jt != nodes_[u].end (); ++jt) {
// skip if different trees
if (cut_[jt->first] != tree_label) continue;
std::vector<std::size_t>& components,
GMM& background_GMM, GMM& foreground_GMM)
{
- const std::size_t indices_size = static_cast<std::size_t> (indices.size ());
+ const auto indices_size = static_cast<std::size_t> (indices.size ());
// Step 4: Assign each pixel to the component which maximizes its probability
for (std::size_t idx = 0; idx < indices_size; ++idx)
{
*
*/
-#include <boost/version.hpp>
-
#include <pcl/point_types.h>
#include <pcl/impl/instantiate.hpp>
#include <pcl/segmentation/min_cut_segmentation.h>
find_package(GLEW)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" OFF)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS opengl glew)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS opengl glew)
PCL_ADD_DOC("${SUBSYS_NAME}")
};
struct Vertex {
- Vertex() {}
+ Vertex() = default;
// Vertex(Eigen::Vector3f pos, Eigen::Vector3f norm) : pos(pos), norm(norm) {}
Vertex(Eigen::Vector3f pos, Eigen::Vector3f rgb) : pos(pos), rgb(rgb) {}
Eigen::Vector3f pos;
pcl::simulation::gllib::Program::Program() { program_id_ = glCreateProgram(); }
-pcl::simulation::gllib::Program::~Program() {}
+pcl::simulation::gllib::Program::~Program() = default;
int
pcl::simulation::gllib::Program::getUniformLocation(const std::string& name) const
pcl::simulation::PointCloudModel::~PointCloudModel()
{
- delete vertices_;
- delete colors_;
+ delete[] vertices_;
+ delete[] colors_;
}
void
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, nullptr);
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (const GLvoid*)12);
+ glVertexAttribPointer(
+ 1, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, reinterpret_cast<const GLvoid*>(12));
glDrawArrays(GL_QUADS, 0, 4);
display_score_image(const float* score_buffer)
{
int npixels = range_likelihood_->getWidth() * range_likelihood_->getHeight();
- std::uint8_t* score_img = new std::uint8_t[npixels * 3];
+ auto* score_img = new std::uint8_t[npixels * 3];
float min_score = score_buffer[0];
float max_score = score_buffer[0];
display_depth_image(const float* depth_buffer, int width, int height)
{
int npixels = width * height;
- std::uint8_t* depth_img = new std::uint8_t[npixels * 3];
+ auto* depth_img = new std::uint8_t[npixels * 3];
float min_depth = depth_buffer[0];
float max_depth = depth_buffer[0];
kd = 2047;
int pval = t_gamma[kd];
- std::uint8_t lb = static_cast<std::uint8_t>(pval & 0xff);
+ auto lb = static_cast<std::uint8_t>(pval & 0xff);
switch (pval >> 8) {
case 0:
depth_img[3 * i + 0] = 255;
display_score_image(const float* score_buffer)
{
int npixels = range_likelihood_->getWidth() * range_likelihood_->getHeight();
- std::uint8_t* score_img = new std::uint8_t[npixels * 3];
+ auto* score_img = new std::uint8_t[npixels * 3];
float min_score = score_buffer[0];
float max_score = score_buffer[0];
display_depth_image(const float* depth_buffer, int width, int height)
{
int npixels = width * height;
- std::uint8_t* depth_img = new std::uint8_t[npixels * 3];
+ auto* depth_img = new std::uint8_t[npixels * 3];
float min_depth = depth_buffer[0];
float max_depth = depth_buffer[0];
float z = -zf * zn / ((zf - zn) * (d - zf / (zf - zn)));
float b = 0.075f;
float f = 580.0f;
- std::uint16_t kd = static_cast<std::uint16_t>(1090 - b * f / z * 8);
+ auto kd = static_cast<std::uint16_t>(1090 - b * f / z * 8);
if (kd > 2047)
kd = 2047;
#include <GL/gl.h>
#endif
-#include <cfloat>
#include <cmath>
#include <iostream>
+#include <limits>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
using GeometryHandlerPtr = GeometryHandler::Ptr;
using GeometryHandlerConstPtr = GeometryHandler::ConstPtr;
-#define NORMALS_SCALE 0.01
-#define PC_SCALE 0.001
+constexpr double NORMALS_SCALE = 0.01;
+constexpr double PC_SCALE = 0.001;
std::uint16_t t_gamma[2048];
Scene::Ptr scene_;
int y_s = 0;
if (!p_file_indices.empty()) {
- y_s =
- static_cast<int>(std::floor(sqrt(static_cast<float>(p_file_indices.size()))));
+ y_s = static_cast<int>(
+ std::floor(std::sqrt(static_cast<float>(p_file_indices.size()))));
x_s = y_s + static_cast<int>(std::ceil(
(p_file_indices.size() / static_cast<double>(y_s)) - y_s));
print_highlight("Preparing to load ");
}
else if (!vtk_file_indices.empty()) {
y_s = static_cast<int>(
- std::floor(sqrt(static_cast<float>(vtk_file_indices.size()))));
+ std::floor(std::sqrt(static_cast<float>(vtk_file_indices.size()))));
x_s = y_s + static_cast<int>(std::ceil(
(vtk_file_indices.size() / static_cast<double>(y_s)) - y_s));
print_highlight("Preparing to load ");
pcl::visualization::PCLHistogramVisualizer::Ptr ph;
// Using min_p, max_p to set the global Y min/max range for the histogram
- float min_p = FLT_MAX;
- float max_p = -FLT_MAX;
+ float min_p = std::numeric_limits<float>::max();
+ float max_p = std::numeric_limits<float>::lowest();
int k = 0, l = 0, viewport = 0;
// Load the data files
std::string fname)
{
int npixels = rl_->getWidth() * rl_->getHeight();
- std::uint8_t* score_img = new std::uint8_t[npixels * 3];
+ auto* score_img = new std::uint8_t[npixels * 3];
float min_score = score_buffer[0];
float max_score = score_buffer[0];
std::string fname)
{
int npixels = rl_->getWidth() * rl_->getHeight();
- std::uint8_t* depth_img = new std::uint8_t[npixels * 3];
+ auto* depth_img = new std::uint8_t[npixels * 3];
float min_depth = depth_buffer[0];
float max_depth = depth_buffer[0];
float z = -zf * zn / ((zf - zn) * (d - zf / (zf - zn)));
float b = 0.075;
float f = 580.0;
- std::uint16_t kd = static_cast<std::uint16_t>(1090 - b * f / z * 8);
+ auto kd = static_cast<std::uint16_t>(1090 - b * f / z * 8);
if (kd > 2047)
kd = 2047;
std::string fname)
{
int npixels = rl_->getWidth() * rl_->getHeight();
- unsigned short* depth_img = new unsigned short[npixels];
+ auto* depth_img = new unsigned short[npixels];
float min_depth = depth_buffer[0];
float max_depth = depth_buffer[0];
std::string fname)
{
int npixels = rl_->getWidth() * rl_->getHeight();
- std::uint8_t* rgb_img = new std::uint8_t[npixels * 3];
+ auto* rgb_img = new std::uint8_t[npixels * 3];
for (int y = 0; y < height_; ++y) {
for (int x = 0; x < width_; ++x) {
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
DigitalElevationMapBuilder();
/** \brief Empty destructor. */
- ~DigitalElevationMapBuilder();
+ ~DigitalElevationMapBuilder() override;
/** \brief Set resolution of the DEM.
* \param[in] resolution_column the column resolution.
{}
template <typename PointT>
-pcl::DisparityMapConverter<PointT>::~DisparityMapConverter()
-{}
+pcl::DisparityMapConverter<PointT>::~DisparityMapConverter() = default;
template <typename PointT>
inline void
bool repeat);
/** \brief Virtual destructor. */
- ~StereoGrabberBase() noexcept;
+ ~StereoGrabberBase() noexcept override;
/** \brief Starts playing the list of Stereo images if frames_per_second is > 0.
* Otherwise it works as a trigger: publishes only the next pair in the list. */
class PCL_EXPORTS GrayStereoMatching : public StereoMatching {
public:
GrayStereoMatching();
- ~GrayStereoMatching();
+ ~GrayStereoMatching() override;
/** \brief stereo processing, it computes a disparity map stored internally by the
* class
class PCL_EXPORTS BlockBasedStereoMatching : public GrayStereoMatching {
public:
BlockBasedStereoMatching();
- ~BlockBasedStereoMatching(){};
+ ~BlockBasedStereoMatching() override = default;
/** \brief setter for the radius of the squared window
* \param[in] radius radius of the squared window used to compute the block-based
public:
AdaptiveCostSOStereoMatching();
- ~AdaptiveCostSOStereoMatching(){};
+ ~AdaptiveCostSOStereoMatching() override = default;
/** \brief setter for the radius (half length) of the column used for cost aggregation
* \param[in] radius radius (half length) of the column used for cost aggregation; the
: resolution_column_(64), resolution_disparity_(32), min_points_in_cell_(1)
{}
-pcl::DigitalElevationMapBuilder::~DigitalElevationMapBuilder() {}
+pcl::DigitalElevationMapBuilder::~DigitalElevationMapBuilder() = default;
void
pcl::DigitalElevationMapBuilder::setResolution(std::size_t resolution_column,
const float kHeightMin = -0.5f;
const float kHeightMax = 1.5f;
const float kHeightResolution = 0.01f;
- const std::size_t kHeightBins =
+ const auto kHeightBins =
static_cast<std::size_t>((kHeightMax - kHeightMin) / kHeightResolution);
// Histogram for initializing other height histograms.
FeatureHistogram height_histogram_example(kHeightBins, kHeightMin, kHeightMax);
// Calculate index of histograms.
std::size_t index_column = column / kColumnStep;
- std::size_t index_disparity = static_cast<std::size_t>(
+ auto index_disparity = static_cast<std::size_t>(
(disparity - disparity_threshold_min_) / kDisparityStep);
std::size_t index = index_column + index_disparity * resolution_column_;
float** acc = new float*[width_];
for (int d = 0; d < width_; d++) {
- acc[d] = new float[max_disp_];
- memset(acc[d], 0, sizeof(float) * max_disp_);
+ acc[d] = new float[max_disp_]{};
}
// data structures for Scanline Optimization
float** fwd = new float*[width_];
float** bck = new float*[width_];
for (int d = 0; d < width_; d++) {
- fwd[d] = new float[max_disp_];
- memset(fwd[d], 0, sizeof(float) * max_disp_);
- bck[d] = new float[max_disp_];
- memset(bck[d], 0, sizeof(float) * max_disp_);
+ fwd[d] = new float[max_disp_]{};
+ bck[d] = new float[max_disp_]{};
}
// spatial distance init
int sad_max = std::numeric_limits<int>::max();
- int* acc = new int[max_disp_];
- memset(acc, 0, sizeof(int) * max_disp_);
+ int* acc = new int[max_disp_]{};
int** v = new int*[width_];
for (int d = 0; d < width_; d++) {
- v[d] = new int[max_disp_];
- memset(v[d], 0, sizeof(int) * max_disp_);
+ v[d] = new int[max_disp_]{};
}
// First row
#include <pcl/stereo/stereo_grabber.h>
#include <pcl/PCLPointCloud2.h> // for PCLPointCloud2
-#include <pcl/point_types.h>
///////////////////////////////////////////////////////////////////////////////////////////
//////////////////////// GrabberImplementation //////////////////////
// TODO: do median filter
int side = radius * 2 + 1;
- short int* out = new short int[width_ * height_];
- memset(out, 0, width_ * height_ * sizeof(short int));
+ auto* out = new short int[width_ * height_]{};
- short int* v = new short int[side * side];
+ auto* v = new short int[side * side];
for (int y = radius; y < height_ - radius; y++) {
for (int x = radius; x < width_ - radius; x++) {
vMap->at(x, y) = invalid_val;
}
else {
- unsigned char val =
+ auto val =
static_cast<unsigned char>(std::floor(scale * disp_map_[y * width_ + x]));
vMap->at(x, y).r = val;
vMap->at(x, y).g = val;
}
//////////////////////////////////////////////////////////////////////////////
-pcl::GrayStereoMatching::GrayStereoMatching() {}
+pcl::GrayStereoMatching::GrayStereoMatching() = default;
//////////////////////////////////////////////////////////////////////////////
-pcl::GrayStereoMatching::~GrayStereoMatching() {}
+pcl::GrayStereoMatching::~GrayStereoMatching() = default;
//////////////////////////////////////////////////////////////////////////////
void
int area = n * n;
int threshold = 31;
- int* v = new int[width_];
- memset(v, 0, sizeof(int) * width_);
+ int* v = new int[width_]{};
for (int x = 0; x < n; x++)
for (int y = 0; y < n; y++)
img[(y - radius - 1) * width_ + x + radius];
sum += v[x + radius] - v[x - radius - 1];
- short int temp = static_cast<short int>(img[y * width_ + x] - (sum / area));
+ auto temp = static_cast<short int>(img[y * width_ + x] - (sum / area));
if (temp < -threshold)
pp_img[y * width_ + x] = 0;
void
pcl::GrayStereoMatching::imgFlip(unsigned char*& img)
{
- unsigned char* temp_row = new unsigned char[width_];
+ auto* temp_row = new unsigned char[width_];
for (int j = 0; j < height_; j++) {
- memcpy(temp_row, img + j * width_, sizeof(unsigned char) * width_);
+ std::copy(img + j * width_, img + j * width_ + width_, temp_row);
for (int i = 0; i < width_; i++) {
img[j * width_ + i] = temp_row[width_ - 1 - i];
}
pp_trg_img_ = nullptr;
}
- memset(disp_map_, 0, sizeof(short int) * height_ * width_);
+ std::fill_n(disp_map_, height_ * width_, 0);
if (is_pre_proc_) {
preProcessing(ref_img, pp_ref_img_);
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS qhull vtk)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS qhull vtk)
PCL_ADD_DOC("${SUBSYS_NAME}")
Polynomial< Degree > polys[Degree+1];
Polynomial< Degree >& operator[] ( int idx ) { return polys[idx]; }
const Polynomial< Degree >& operator[] ( int idx ) const { return polys[idx]; }
- void printnl( void ) const { for( int d=0 ; d<=Degree ; d++ ) polys[d].printnl(); }
+ void printnl( ) const { for( int d=0 ; d<=Degree ; d++ ) polys[d].printnl(); }
BSplineComponents scale( double s ) const { BSplineComponents b ; for( int d=0 ; d<=Degree ; d++ ) b[d] = polys[d].scale(s) ; return b; }
BSplineComponents shift( double s ) const { BSplineComponents b ; for( int d=0 ; d<=Degree ; d++ ) b[d] = polys[d].shift(s) ; return b; }
};
PPolynomial<Degree>* baseFunctions;
BSplineComponents* baseBSplines;
- BSplineData(void);
- ~BSplineData(void);
+ BSplineData();
+ virtual ~BSplineData();
virtual void setDotTables( int flags );
virtual void clearDotTables( int flags );
virtual void setValueTables( int flags,double smooth=0);
virtual void setValueTables( int flags,double valueSmooth,double normalSmooth);
- virtual void clearValueTables(void);
+ virtual void clearValueTables();
void setSampleSpan( int idx , int& start , int& end , double smooth=0 ) const;
template< int Degree >
struct BSplineElementCoefficients
{
- int coeffs[Degree+1];
- BSplineElementCoefficients( void ) { memset( coeffs , 0 , sizeof( int ) * ( Degree+1 ) ); }
+ int coeffs[Degree+1] = {};
+ BSplineElementCoefficients( ) = default;
int& operator[]( int idx ){ return coeffs[idx]; }
const int& operator[]( int idx ) const { return coeffs[idx]; }
};
// Coefficients are ordered as "/" "-" "\"
int denominator;
- BSplineElements( void ) { denominator = 1; }
+ BSplineElements( ) { denominator = 1; }
BSplineElements( int res , int offset , int boundary=NONE );
void upSample( BSplineElements& high ) const;
}
template< int Degree , class Real >
- BSplineData<Degree,Real>::BSplineData( void )
+ BSplineData<Degree,Real>::BSplineData( )
{
vvDotTable = dvDotTable = ddDotTable = NULL;
valueTables = dValueTables = NULL;
}
template< int Degree , class Real >
- BSplineData< Degree , Real >::~BSplineData(void)
+ BSplineData< Degree , Real >::~BSplineData()
{
if( functionCount )
{
template<int Degree,class Real>
- void BSplineData<Degree,Real>::clearValueTables(void){
+ void BSplineData<Degree,Real>::clearValueTables(){
delete[] valueTables;
delete[] dValueTables;
valueTables=dValueTables=NULL;
{
public:
std::vector<Point3D<float> > inCorePoints;
+
+ virtual ~CoredMeshData() = default;
virtual void resetIterator( void ) = 0;
virtual int addOutOfCorePoint( const Point3D<float>& p ) = 0;
value = ( p1[0] * p2[0] + p1[1] * p2[1] + p1[2] * p2[2] ) / ( p2[0] * p2[0] + p2[1] * p2[1] + p2[2] * p2[2] );
}
};
+
+ virtual ~CoredMeshData2() = default;
+
std::vector< Vertex > inCorePoints;
virtual void resetIterator( void ) = 0;
void set( TreeOctNode& root );
struct CornerIndices
{
- int idx[pcl::poisson::Cube::CORNERS];
- CornerIndices( void ) { memset( idx , -1 , sizeof( int ) * pcl::poisson::Cube::CORNERS ); }
+ int idx[pcl::poisson::Cube::CORNERS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ CornerIndices( void ) = default;
int& operator[] ( int i ) { return idx[i]; }
const int& operator[] ( int i ) const { return idx[i]; }
};
int getMaxCornerCount( const TreeOctNode* rootNode , int depth , int maxDepth , int threads ) const ;
struct EdgeIndices
{
- int idx[pcl::poisson::Cube::EDGES];
- EdgeIndices( void ) { memset( idx , -1 , sizeof( int ) * pcl::poisson::Cube::EDGES ); }
+ int idx[pcl::poisson::Cube::EDGES] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ EdgeIndices( void ) = default;
int& operator[] ( int i ) { return idx[i]; }
const int& operator[] ( int i ) const { return idx[i]; }
};
template<class T>
SparseMatrix<T>& SparseMatrix<T>::operator *= (const T& V)
{
- for (int i=0; i<this->Rows(); i++)
+ for (int i=0; i<rows; i++)
{
- for(int ii=0;ii<m_ppElements[i].size();i++){m_ppElements[i][ii].Value*=V;}
+ for(int ii=0;ii<rowSizes[i];ii++){m_ppElements[i][ii].Value*=V;}
}
return *this;
}
template<class T>
SparseMatrix<T> SparseMatrix<T>::Multiply( const SparseMatrix<T>& M ) const
{
- SparseMatrix<T> R( this->Rows(), M.Columns() );
- for(int i=0; i<R.Rows(); i++){
- for(int ii=0;ii<m_ppElements[i].size();ii++){
+ SparseMatrix<T> R( rows, M._maxEntriesPerRow );
+ for(int i=0; i<R.rows; i++){
+ for(int ii=0;ii<rowSizes[i];ii++){
int N=m_ppElements[i][ii].N;
T Value=m_ppElements[i][ii].Value;
- for(int jj=0;jj<M.m_ppElements[N].size();jj++){
+ for(int jj=0;jj<M.rowSizes[N];jj++){
R(i,M.m_ppElements[N][jj].N) += Value * M.m_ppElements[N][jj].Value;
}
}
template<class T>
SparseMatrix<T> SparseMatrix<T>::Transpose() const
{
- SparseMatrix<T> M( this->Columns(), this->Rows() );
+ SparseMatrix<T> M( _maxEntriesPerRow, rows );
- for (int i=0; i<this->Rows(); i++)
+ for (int i=0; i<rows; i++)
{
- for(int ii=0;ii<m_ppElements[i].size();ii++){
+ for(int ii=0;ii<rowSizes[i];ii++){
M(m_ppElements[i][ii].N,i) = m_ppElements[i][ii].Value;
}
}
class BilateralUpsampling: public CloudSurfaceProcessing<PointInT, PointOutT>
{
public:
- typedef shared_ptr<BilateralUpsampling<PointInT, PointOutT> > Ptr;
- typedef shared_ptr<const BilateralUpsampling<PointInT, PointOutT> > ConstPtr;
+ using Ptr = shared_ptr<BilateralUpsampling<PointInT, PointOutT> >;
+ using ConstPtr = shared_ptr<const BilateralUpsampling<PointInT, PointOutT> >;
using PCLBase<PointInT>::input_;
using PCLBase<PointInT>::indices_;
};
/** \brief Empty destructor */
- ~ConcaveHull () {}
+ ~ConcaveHull () override = default;
/** \brief Compute a concave hull for all points given
*
}
/** \brief Empty destructor */
- ~ConvexHull () {}
+ ~ConvexHull () override = default;
/** \brief Compute a convex hull for all points given.
*
using MeshProcessing::input_mesh_;
using MeshProcessing::initCompute;
/** \brief Empty constructor */
- EarClipping ()
- {
- };
+ EarClipping () = default;
protected:
/** \brief a Pointer to the point cloud data. */
/** \brief Data leaf. */
struct Leaf
{
- Leaf () {}
+ Leaf () = default;
pcl::Indices data_indices;
Eigen::Vector4f pt_on_surface;
Eigen::Vector3f vect_at_grid_pt;
};
- typedef std::unordered_map<int, Leaf, std::hash<int>, std::equal_to<>, Eigen::aligned_allocator<std::pair<const int, Leaf>>> HashMap;
+ using HashMap = std::unordered_map<int, Leaf, std::hash<int>, std::equal_to<>, Eigen::aligned_allocator<std::pair<const int, Leaf>>>;
/** \brief Constructor. */
GridProjection ();
GridProjection (double in_resolution);
/** \brief Destructor. */
- ~GridProjection ();
+ ~GridProjection () override;
/** \brief Set the size of the grid cell
* \param resolution the size of the grid cell
/** \brief Class get name method. */
std::string getClassName () const override { return ("GridProjection"); }
+ /** \brief Output will be scaled up by this factor, if previously scaled down by scaleInputDataPoint. */
+ double cloud_scale_factor_ = 1.0;
+
public:
PCL_MAKE_ALIGNED_OPERATOR_NEW
};
float val_exp_depth = val_exp_depth_matrix (static_cast<Eigen::MatrixXf::Index> (x - x_w + window_size_),
static_cast<Eigen::MatrixXf::Index> (y - y_w + window_size_));
- Eigen::VectorXf::Index d_color = static_cast<Eigen::VectorXf::Index> (
+ auto d_color = static_cast<Eigen::VectorXf::Index> (
std::abs ((*input_)[y_w * input_->width + x_w].r - (*input_)[y * input_->width + x].r) +
std::abs ((*input_)[y_w * input_->width + x_w].g - (*input_)[y * input_->width + x].g) +
std::abs ((*input_)[y_w * input_->width + x_w].b - (*input_)[y * input_->width + x].b));
// Facets are tetrahedrons (3d)
if (!facet->upperdelaunay)
{
- vertexT *anyVertex = static_cast<vertexT*> (facet->vertices->e[0].p);
+ auto *anyVertex = static_cast<vertexT*> (facet->vertices->e[0].p);
double *center = facet->center;
double r = qh_pointdist (anyVertex->point,center,dim_);
{
// Check if the distance from any vertex to the facet->center
// (center of the voronoi cell) is smaller than alpha
- vertexT *anyVertex = static_cast<vertexT*>(facet->vertices->e[0].p);
+ auto *anyVertex = static_cast<vertexT*>(facet->vertices->e[0].p);
double r = (sqrt ((anyVertex->point[0] - facet->center[0]) *
(anyVertex->point[0] - facet->center[0]) +
(anyVertex->point[1] - facet->center[1]) *
alpha_shape_sorted.resize (vertices);
// iterate over edges until they are empty!
- std::map<int, std::vector<int> >::iterator curr = edges.begin ();
+ auto curr = edges.begin ();
int next = - 1;
std::vector<bool> used (vertices, false); // used to decide which direction should we take!
std::vector<int> pcd_idx_start_polygons;
// Set the state of the point
state_[R_] = is_boundary ? BOUNDARY : COMPLETED;
- std::vector<int>::iterator first_gap_after = angleIdx.end ();
- std::vector<int>::iterator last_gap_before = angleIdx.begin ();
+ auto first_gap_after = angleIdx.end ();
+ auto last_gap_before = angleIdx.begin ();
int nr_gaps = 0;
- for (std::vector<int>::iterator it = angleIdx.begin (); it != angleIdx.end () - 1; ++it)
+ for (auto it = angleIdx.begin (); it != angleIdx.end () - 1; ++it)
{
if (gaps[*it])
{
Eigen::Vector2f S1;
Eigen::Vector2f S2;
std::vector<int> to_erase;
- for (std::vector<int>::iterator it = angleIdx.begin()+1; it != angleIdx.end()-1; ++it)
+ for (auto it = angleIdx.begin()+1; it != angleIdx.end()-1; ++it)
{
if (gaps[*(it-1)])
angle_so_far = 0;
else
break;
bool can_delete = true;
- for (std::vector<int>::iterator curr_it = prev_it+1; curr_it != it+1; ++curr_it)
+ for (auto curr_it = prev_it+1; curr_it != it+1; ++curr_it)
{
tmp_ = coords_[angles_[*curr_it].index] - proj_qp_;
X[0] = tmp_.dot(u_);
}
for (const auto &idx : to_erase)
{
- for (std::vector<int>::iterator iter = angleIdx.begin(); iter != angleIdx.end(); ++iter)
+ for (auto iter = angleIdx.begin(); iter != angleIdx.end(); ++iter)
if (idx == *iter)
{
angleIdx.erase(iter);
changed_1st_fn_ = false;
changed_2nd_fn_ = false;
new2boundary_ = NONE;
- for (std::vector<int>::iterator it = angleIdx.begin()+1; it != angleIdx.end()-1; ++it)
+ for (auto it = angleIdx.begin()+1; it != angleIdx.end()-1; ++it)
{
current_index_ = angles_[*it].index;
template <typename PointNT> void
pcl::GridProjection<PointNT>::scaleInputDataPoint (double scale_factor)
{
+ cloud_scale_factor_ = scale_factor;
+ PCL_DEBUG ("[pcl::GridProjection::scaleInputDataPoint] scale_factor=%g\n", scale_factor);
for (auto& point: *data_) {
point.getVector3fMap() /= static_cast<float> (scale_factor);
}
std::vector <double> pt_union_weight (pt_union_indices.size ());
Eigen::Vector3f out_vector (0, 0, 0);
double sum = 0.0;
- double mag = 0.0;
for (std::size_t i = 0; i < pt_union_indices.size (); ++i)
{
Eigen::Vector4f pp ((*data_)[pt_union_indices[i]].x, (*data_)[pt_union_indices[i]].y, (*data_)[pt_union_indices[i]].z, 0);
pt_union_dist[i] = (pp - p).squaredNorm ();
pt_union_weight[i] = pow (M_E, -pow (pt_union_dist[i], 2.0) / gaussian_scale_);
- mag += pow (M_E, -pow (sqrt (pt_union_dist[i]), 2.0) / gaussian_scale_);
sum += pt_union_weight[i];
}
// Copy the data from surface_ to cloud
for (std::size_t i = 0; i < cloud.size (); ++i)
{
- cloud[i].x = surface_[i].x ();
- cloud[i].y = surface_[i].y ();
- cloud[i].z = surface_[i].z ();
+ cloud[i].x = cloud_scale_factor_*surface_[i].x ();
+ cloud[i].y = cloud_scale_factor_*surface_[i].y ();
+ cloud[i].z = cloud_scale_factor_*surface_[i].z ();
}
pcl::toPCLPointCloud2 (cloud, output.cloud);
}
// Copy the data from surface_ to cloud
for (std::size_t i = 0; i < points.size (); ++i)
{
- points[i].x = surface_[i].x ();
- points[i].y = surface_[i].y ();
- points[i].z = surface_[i].z ();
+ points[i].x = cloud_scale_factor_*surface_[i].x ();
+ points[i].y = cloud_scale_factor_*surface_[i].y ();
+ points[i].z = cloud_scale_factor_*surface_[i].z ();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
-pcl::MarchingCubes<PointNT>::~MarchingCubes ()
-{
-}
+pcl::MarchingCubes<PointNT>::~MarchingCubes () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
-pcl::MarchingCubesHoppe<PointNT>::~MarchingCubesHoppe ()
-{
-}
+pcl::MarchingCubesHoppe<PointNT>::~MarchingCubesHoppe () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
-pcl::MarchingCubesRBF<PointNT>::~MarchingCubesRBF ()
-{
-}
+pcl::MarchingCubesRBF<PointNT>::~MarchingCubesRBF () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::MarchingCubesRBF<PointNT>::voxelizeData ()
{
// Initialize data structures
- const unsigned int N = static_cast<unsigned int> (input_->size ());
+ const auto N = static_cast<unsigned int> (input_->size ());
Eigen::MatrixXd M (2*N, 2*N),
d (2*N, 1);
// Reset or initialize the collection of indices
corresponding_input_indices_.reset (new PointIndices);
+ normals_.reset (new NormalCloud); // always init this since it is dereferenced in performUpsampling
// Check if normals have to be computed/saved
if (compute_normals_)
{
- normals_.reset (new NormalCloud);
// Copy the header
normals_->header = input_->header;
// Clear the fields in case the method exits before computation
{
corresponding_input_indices_.reset (new PointIndices);
- MLSVoxelGrid voxel_grid (input_, indices_, voxel_size_);
+ MLSVoxelGrid voxel_grid (input_, indices_, voxel_size_, dilation_iteration_num_);
for (int iteration = 0; iteration < dilation_iteration_num_; ++iteration)
voxel_grid.dilate ();
- for (typename MLSVoxelGrid::HashMap::iterator m_it = voxel_grid.voxel_grid_.begin (); m_it != voxel_grid.voxel_grid_.end (); ++m_it)
+ for (auto m_it = voxel_grid.voxel_grid_.begin (); m_it != voxel_grid.voxel_grid_.end (); ++m_it)
{
// Get 3D position of point
Eigen::Vector3f pos;
if (num_neighbors >= nr_coeff)
{
if (!weight_func)
- weight_func = [=] (const double sq_dist) { return this->computeMLSWeight (sq_dist, search_radius * search_radius); };
+ weight_func = [this, search_radius] (const double sq_dist) { return this->computeMLSWeight (sq_dist, search_radius * search_radius); };
// Allocate matrices and vectors to hold the data used for the polynomial fit
Eigen::VectorXd weight_vec (num_neighbors);
template <typename PointInT, typename PointOutT>
pcl::MovingLeastSquares<PointInT, PointOutT>::MLSVoxelGrid::MLSVoxelGrid (PointCloudInConstPtr& cloud,
IndicesPtr &indices,
- float voxel_size) :
+ float voxel_size,
+ int dilation_iteration_num) :
voxel_grid_ (), data_size_ (), voxel_size_ (voxel_size)
{
pcl::getMinMax3D (*cloud, *indices, bounding_min_, bounding_max_);
+ bounding_min_ -= Eigen::Vector4f::Constant(voxel_size_ * (dilation_iteration_num + 1));
+ bounding_max_ += Eigen::Vector4f::Constant(voxel_size_ * (dilation_iteration_num + 1));
Eigen::Vector4f bounding_box_size = bounding_max_ - bounding_min_;
const double max_size = (std::max) ((std::max)(bounding_box_size.x (), bounding_box_size.y ()), bounding_box_size.z ());
// Put initial cloud in voxel grid
- data_size_ = static_cast<std::uint64_t> (1.5 * max_size / voxel_size_);
+ data_size_ = static_cast<std::uint64_t> (std::ceil(max_size / voxel_size_));
for (std::size_t i = 0; i < indices->size (); ++i)
if (std::isfinite ((*cloud)[(*indices)[i]].x))
{
pcl::MovingLeastSquares<PointInT, PointOutT>::MLSVoxelGrid::dilate ()
{
HashMap new_voxel_grid = voxel_grid_;
- for (typename MLSVoxelGrid::HashMap::iterator m_it = voxel_grid_.begin (); m_it != voxel_grid_.end (); ++m_it)
+ for (auto m_it = voxel_grid_.begin (); m_it != voxel_grid_.end (); ++m_it)
{
Eigen::Vector3i index;
getIndexIn3D (m_it->first, index);
#define MEMORY_ALLOCATOR_BLOCK_SIZE 1<<12
#include <cstdarg>
-#include <string>
using namespace pcl;
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
-pcl::Poisson<PointNT>::~Poisson ()
-{
-}
+pcl::Poisson<PointNT>::~Poisson () = default;
//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
#ifndef PCL_SURFACE_RECONSTRUCTION_IMPL_H_
#define PCL_SURFACE_RECONSTRUCTION_IMPL_H_
-#include <pcl/conversions.h> // for toPCLPointCloud2
+#include <pcl/conversions.h> // for pcl::toPCLPointCloud2
#include <pcl/search/kdtree.h> // for KdTree
#include <pcl/search/organized.h> // for OrganizedNeighbor
}
/** \brief Destructor. */
- ~MarchingCubes ();
+ ~MarchingCubes () override;
/** \brief Method that sets the iso level of the surface to be extracted.
}
/** \brief Destructor. */
- ~MarchingCubesHoppe ();
+ ~MarchingCubesHoppe () override;
/** \brief Convert the point cloud into voxel data.
*/
* "Reconstruction and representation of 3D objects with radial basis functions"
* SIGGRAPH '01
*
+ * \note This algorithm in its current implementation may not be suitable for very
+ * large point clouds, due to high memory requirements.
* \author Alexandru E. Ichim
* \ingroup surface
*/
}
/** \brief Destructor. */
- ~MarchingCubesRBF ();
+ ~MarchingCubesRBF () override;
/** \brief Convert the point cloud into voxel data.
*/
class MovingLeastSquares : public CloudSurfaceProcessing<PointInT, PointOutT>
{
public:
- typedef shared_ptr<MovingLeastSquares<PointInT, PointOutT> > Ptr;
- typedef shared_ptr<const MovingLeastSquares<PointInT, PointOutT> > ConstPtr;
+ using Ptr = shared_ptr<MovingLeastSquares<PointInT, PointOutT> >;
+ using ConstPtr = shared_ptr<const MovingLeastSquares<PointInT, PointOutT> >;
using PCLBase<PointInT>::input_;
using PCLBase<PointInT>::indices_;
{};
/** \brief Empty destructor */
- ~MovingLeastSquares () {}
+ ~MovingLeastSquares () override = default;
/** \brief Set whether the algorithm should also store the normals computed
MLSVoxelGrid (PointCloudInConstPtr& cloud,
IndicesPtr &indices,
- float voxel_size);
+ float voxel_size,
+ int dilation_iteration_num);
void
dilate ();
point[i] = static_cast<Eigen::Vector3f::Scalar> (index_3d[i]) * voxel_size_ + bounding_min_[i];
}
- typedef std::map<std::uint64_t, Leaf> HashMap;
+ using HashMap = std::map<std::uint64_t, Leaf>;
HashMap voxel_grid_;
Eigen::Vector4f bounding_min_, bounding_max_;
std::uint64_t data_size_;
*/
FittingCurve2d (NurbsDataCurve2d *data, const ON_NurbsCurve &nc);
+ /** \brief Default virtual destructor. */
+ virtual
+ ~FittingCurve2d() = default;
+
/** \brief Find the element in which the parameter xi lies.
* \param[in] xi value in parameter domain of the B-Spline curve.
* \param[in] elements the vector of elements of the curve.
* \param[in] nc B-Spline curve used for fitting. */
FittingCurve2dAPDM (NurbsDataCurve2d *data, const ON_NurbsCurve &nc);
+ /** \brief Default virtual destructor. */
+ virtual
+ ~FittingCurve2dAPDM() = default;
+
/** \brief Find the element in which the parameter xi lies.
* \param[in] xi value in parameter domain of the B-Spline curve.
* \param[in] elements the vector of elements of the curve.
*/
FittingCurve2dPDM (NurbsDataCurve2d *data, const ON_NurbsCurve &nc);
+ /** \brief Default virtual destructor. */
+ virtual
+ ~FittingCurve2dPDM() = default;
+
/** \brief Find the element in which the parameter xi lies.
* \param[in] xi value in parameter domain of the B-Spline curve.
* \param[in] elements the vector of elements of the curve.
* \param[in] nurbs set of B-Spline surface used for fitting. */
GlobalOptimization (const std::vector<NurbsDataSurface*> &data, const std::vector<ON_NurbsSurface*> &nurbs);
+ /** \brief Default virtual destructor. */
+ virtual
+ ~GlobalOptimization() = default;
+
/** \brief Set common boundary points two NURBS should lie on
* \param[in] boundary vector of boundary points.
* \param[in] nurbs_indices vector of 2 NURBS indices sharing the boundary point. */
};
/** \brief Destructor. */
- ~OrganizedFastMesh () {};
+ ~OrganizedFastMesh () override = default;
/** \brief Set a maximum edge length.
* Using not only the scalar \a a, but also \a b and \a c, allows for using a distance threshold in the form of:
Poisson ();
/** \brief Destructor. */
- ~Poisson ();
+ ~Poisson () override;
/** \brief Create the surface.
* \param[out] output the resultant polygonal mesh
class CloudSurfaceProcessing : public PCLBase<PointInT>
{
public:
- typedef shared_ptr<CloudSurfaceProcessing<PointInT, PointOutT> > Ptr;
- typedef shared_ptr<const CloudSurfaceProcessing<PointInT, PointOutT> > ConstPtr;
+ using Ptr = shared_ptr<CloudSurfaceProcessing<PointInT, PointOutT> >;
+ using ConstPtr = shared_ptr<const CloudSurfaceProcessing<PointInT, PointOutT> >;
using PCLBase<PointInT>::input_;
using PCLBase<PointInT>::indices_;
{};
/** \brief Empty destructor */
- ~CloudSurfaceProcessing () {}
+ ~CloudSurfaceProcessing () override = default;
/** \brief Process the input cloud and store the results
* \param[out] output the cloud where the results will be stored
using PolygonMeshConstPtr = PolygonMesh::ConstPtr;
/** \brief Constructor. */
- MeshProcessing () {}
+ MeshProcessing () = default;
/** \brief Destructor. */
- virtual ~MeshProcessing () {}
+ virtual ~MeshProcessing () = default;
/** \brief Set the input mesh that we want to process
* \param[in] input the input polygonal mesh
PCLSurfaceBase () : tree_ () {}
/** \brief Empty destructor */
- ~PCLSurfaceBase () {}
+ ~PCLSurfaceBase () override = default;
/** \brief Provide an optional pointer to a search object.
* \param[in] tree a pointer to the spatial search object.
SurfaceReconstruction () : check_tree_ (true) {}
/** \brief Destructor. */
- ~SurfaceReconstruction () {}
+ ~SurfaceReconstruction () override = default;
/** \brief Base method for surface reconstruction for all points given in
* <setInputCloud (), setIndices ()>
MeshConstruction () : check_tree_ (true) {}
/** \brief Destructor. */
- ~MeshConstruction () {}
+ ~MeshConstruction () override = default;
/** \brief Base method for surface reconstruction for all points given in
* <setInputCloud (), setIndices ()>
using ConstPtr = shared_ptr<const SimplificationRemoveUnusedVertices>;
/** \brief Constructor. */
- SimplificationRemoveUnusedVertices () {};
+ SimplificationRemoveUnusedVertices () = default;
/** \brief Destructor. */
- ~SimplificationRemoveUnusedVertices () {};
+ ~SimplificationRemoveUnusedVertices () = default;
/** \brief Simply a polygonal mesh.
* \param[in] input the input mesh
using PCLBase<PointT>::initCompute;
public:
- typedef shared_ptr<SurfelSmoothing<PointT, PointNT> > Ptr;
- typedef shared_ptr<const SurfelSmoothing<PointT, PointNT> > ConstPtr;
+ using Ptr = shared_ptr<SurfelSmoothing<PointT, PointNT> >;
+ using ConstPtr = shared_ptr<const SurfelSmoothing<PointT, PointNT> >;
using PointCloudIn = pcl::PointCloud<PointT>;
using PointCloudInPtr = typename pcl::PointCloud<PointT>::Ptr;
}
/** \brief Destructor. */
- ~TextureMapping ()
- {
- }
+ ~TextureMapping () = default;
/** \brief Set mesh scale control
* \param[in] f
m_arrowlength = src.m_arrowlength;
m_arrowwidth = src.m_arrowwidth;
m_centermark = src.m_centermark;
- m_dimunits = src.m_dimunits;;
+ m_dimunits = src.m_dimunits;
m_arrowtype = src.m_arrowtype;
m_angularunits = src.m_angularunits;
m_lengthformat = src.m_lengthformat;
bool ON_BinaryArchive::WriteBigSize(std::size_t sz)
{
ON__UINT64 u = (ON__UINT64)sz;
- return WriteInt64(1,(ON__INT64*)&u);;
+ return WriteInt64(1,(ON__INT64*)&u);
}
bool ON_BinaryArchive::ReadBigSize( std::size_t* sz )
return m_active_id_count;
}
+#if (_MSC_VER >= 1930 && _MSC_VER <= 1939)
+// Solves internal compiler error on MSVC 2022
+// (see https://github.com/microsoft/vcpkg/issues/19561)
+#pragma optimize("", off)
+#endif
struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::FirstElement() const
{
struct SN_ELEMENT* e=0;
}
return e;
}
+#if (_MSC_VER >= 1930 && _MSC_VER <= 1939)
+#pragma optimize("", on)
+#endif
struct ON_SerialNumberMap::SN_ELEMENT* ON_SerialNumberMap::LastElement() const
{
// map and clamp the tcs that hang over. If the mesh
// has edges near the texture seam, the picture will
// still look ok.
- float f0=0.0f, f1=0.0f, twopitc = (float)two_pi_tc;;
+ float f0=0.0f, f1=0.0f, twopitc = (float)two_pi_tc;
//int f0cnt=0, f1cnt=0;
if ( 1 == ftc.quad[0] ) f0 += ftc.Tx[0]; else if ( 4 == ftc.quad[0] ) f1 += twopitc-ftc.Tx[0];
if ( 1 == ftc.quad[1] ) f0 += ftc.Tx[1]; else if ( 4 == ftc.quad[1] ) f1 += twopitc-ftc.Tx[1];
ON_2dPoint::ON_2dPoint(const ON_4fPoint& h)
{
const double w = (h.w != 1.0f && h.w != 0.0f) ? 1.0/((double)h.w) : 1.0;
- x *= w*h.x;
- y *= w*h.y;
+ x = w*h.x;
+ y = w*h.y;
}
ON_2dPoint::ON_2dPoint(const ON_2fVector& v)
ON_String ON_String::Mid(int i, int count) const
{
- ON_String(s);
+ ON_String s;
if ( i >= 0 && i < Length() && count > 0 ) {
if ( count > Length() - i )
count = Length() - i;
ON_wString ON_wString::Mid(int i, int count) const
{
- ON_wString(s);
+ ON_wString s;
if ( i >= 0 && i < Length() && count > 0 ) {
if ( count > Length() - i )
count = Length() - i;
//////////////////////
// Polynomial Roots //
//////////////////////
-#include <math.h>
#include <pcl/surface/3rdparty/poisson4/factor.h>
+#include <cmath>
+
namespace pcl
{
namespace poisson
namespace poisson
{
- TriangulationEdge::TriangulationEdge(void){pIndex[0]=pIndex[1]=tIndex[0]=tIndex[1]=-1;}
- TriangulationTriangle::TriangulationTriangle(void){eIndex[0]=eIndex[1]=eIndex[2]=-1;}
+ TriangulationEdge::TriangulationEdge(){pIndex[0]=pIndex[1]=tIndex[0]=tIndex[1]=-1;}
+ TriangulationTriangle::TriangulationTriangle(){eIndex[0]=eIndex[1]=eIndex[2]=-1;}
/////////////////////////
// CoredVectorMeshData //
/////////////////////////
- CoredVectorMeshData::CoredVectorMeshData( void ) { oocPointIndex = polygonIndex = 0; }
- void CoredVectorMeshData::resetIterator ( void ) { oocPointIndex = polygonIndex = 0; }
+ CoredVectorMeshData::CoredVectorMeshData( ) { oocPointIndex = polygonIndex = 0; }
+ void CoredVectorMeshData::resetIterator ( ) { oocPointIndex = polygonIndex = 0; }
int CoredVectorMeshData::addOutOfCorePoint(const Point3D<float>& p){
oocPoints.push_back(p);
return int(oocPoints.size())-1;
}
else return 0;
}
- int CoredVectorMeshData::outOfCorePointCount(void){return int(oocPoints.size());}
- int CoredVectorMeshData::polygonCount( void ) { return int( polygons.size() ); }
+ int CoredVectorMeshData::outOfCorePointCount(){return int(oocPoints.size());}
+ int CoredVectorMeshData::polygonCount( ) { return int( polygons.size() ); }
/////////////////////////
// CoredVectorMeshData //
/////////////////////////
- CoredVectorMeshData2::CoredVectorMeshData2( void ) { oocPointIndex = polygonIndex = 0; }
- void CoredVectorMeshData2::resetIterator ( void ) { oocPointIndex = polygonIndex = 0; }
+ CoredVectorMeshData2::CoredVectorMeshData2( ) { oocPointIndex = polygonIndex = 0; }
+ void CoredVectorMeshData2::resetIterator ( ) { oocPointIndex = polygonIndex = 0; }
int CoredVectorMeshData2::addOutOfCorePoint( const CoredMeshData2::Vertex& v )
{
oocPoints.push_back( v );
}
else return 0;
}
- int CoredVectorMeshData2::outOfCorePointCount(void){return int(oocPoints.size());}
- int CoredVectorMeshData2::polygonCount( void ) { return int( polygons.size() ); }
+ int CoredVectorMeshData2::outOfCorePointCount(){return int(oocPoints.size());}
+ int CoredVectorMeshData2::polygonCount( ) { return int( polygons.size() ); }
}
}
*
*/
+#include <limits>
#include <pcl/surface/on_nurbs/closing_boundary.h>
#include <Eigen/Geometry> // for cross
{
Eigen::Vector3d current = start;
- double error1 (DBL_MAX);
- double error2 (DBL_MAX);
+ double error1 (std::numeric_limits<double>::max());
+ double error2 (std::numeric_limits<double>::max());
Eigen::Vector3d p1, p2, tu1, tu2, tv1, tv2;
{
Eigen::Vector3d current = start;
- double error1 (DBL_MAX);
- double error2 (DBL_MAX);
+ double error1 (std::numeric_limits<double>::max());
+ double error2 (std::numeric_limits<double>::max());
Eigen::Vector3d p1, p2, tu1, tu2, tv1, tv2;
{
Eigen::Vector3d current = start;
- double error1 (DBL_MAX);
- double error2 (DBL_MAX);
+ double error1 (std::numeric_limits<double>::max());
+ double error2 (std::numeric_limits<double>::max());
Eigen::Vector3d p1, p2, tu1, tu2, tv1, tv2;
*/
#include <pcl/surface/on_nurbs/fitting_curve_2d.h>
+#include <limits>
#include <stdexcept>
#include <Eigen/LU> // for inverse
eigenvalues /= s; // seems that the eigenvalues are dependent on the number of points (???)
Eigen::Matrix2d eigenvectors_inv = eigenvectors.inverse ();
- Eigen::Vector2d v_max (-DBL_MAX, -DBL_MAX);
- Eigen::Vector2d v_min (DBL_MAX, DBL_MAX);
+ Eigen::Vector2d v_max(std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest());
+ Eigen::Vector2d v_min (std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max());
for (unsigned i = 0; i < s; i++)
{
Eigen::Vector2d p (eigenvectors_inv * (data->interior[i] - mean));
std::vector<double> elements = getElementVector (nurbs);
Eigen::Vector2d min_pt;
- double min_param (DBL_MAX);
- double min_dist (DBL_MAX);
- error = DBL_MAX;
+ double min_param (std::numeric_limits<double>::max());
+ double min_dist (std::numeric_limits<double>::max());
+ error = std::numeric_limits<double>::max();
int is_corner (-1);
for (std::size_t i = 0; i < elements.size () - 1; i++)
//
// if (phint == NULL)
// {
-// double d_shortest (DBL_MAX);
+// double d_shortest (std::numeric_limits<double>::max());
// for (unsigned i = 0; i < elements.size () - 1; i++)
// {
// double d;
Eigen::Vector2d r = p - pt;
double d_shortest_hint = r.squaredNorm ();
- double d_shortest_elem (DBL_MAX);
+ double d_shortest_elem (std::numeric_limits<double>::max());
// evaluate elements
std::vector<double> elements = pcl::on_nurbs::FittingCurve2d::getElementVector (nurbs);
std::vector<double> elements = pcl::on_nurbs::FittingCurve2d::getElementVector (nurbs);
double points[2];
- double d_shortest (DBL_MAX);
+ double d_shortest (std::numeric_limits<double>::max());
double seg = 1.0 / (nurbs.Order () - 1);
for (std::size_t i = 0; i < elements.size () - 1; i++)
#include <pcl/surface/on_nurbs/fitting_curve_2d_apdm.h>
#include <pcl/pcl_macros.h>
+#include <limits>
#include <stdexcept>
#include <Eigen/Geometry> // for cross
std::vector<double> elements = getElementVector (nurbs);
Eigen::Vector2d min_pt;
- double min_param (DBL_MAX);
- double min_dist (DBL_MAX);
- error = DBL_MAX;
+ double min_param (std::numeric_limits<double>::max());
+ double min_dist (std::numeric_limits<double>::max());
+ error = std::numeric_limits<double>::max();
int is_corner (-1);
for (std::size_t i = 0; i < elements.size () - 1; i++)
//
// if (phint == NULL)
// {
-// double d_shortest (DBL_MAX);
+// double d_shortest (std::numeric_limits<double>::max());
// for (unsigned i = 0; i < elements.size () - 1; i++)
// {
// double d;
Eigen::Vector2d r = p - pt;
double d_shortest_hint = r.squaredNorm ();
- double d_shortest_elem (DBL_MAX);
+ double d_shortest_elem (std::numeric_limits<double>::max());
// evaluate elements
std::vector<double> elements = pcl::on_nurbs::FittingCurve2dAPDM::getElementVector (nurbs);
std::vector<double> elements = pcl::on_nurbs::FittingCurve2dAPDM::getElementVector (nurbs);
double points[2];
- double d_shortest (DBL_MAX);
+ double d_shortest (std::numeric_limits<double>::max());
double seg = 1.0 / (nurbs.Order () - 1);
for (std::size_t i = 0; i < elements.size () - 1; i++)
#include <pcl/surface/on_nurbs/fitting_curve_2d_pdm.h>
#include <pcl/pcl_macros.h>
+#include <limits>
#include <stdexcept>
using namespace pcl;
std::vector<double> elements = getElementVector (nurbs);
Eigen::Vector2d min_pt;
- double min_param (DBL_MAX);
- double min_dist (DBL_MAX);
- error = DBL_MAX;
+ double min_param (std::numeric_limits<double>::max());
+ double min_dist (std::numeric_limits<double>::max());
+ error = std::numeric_limits<double>::max();
int is_corner (-1);
for (std::size_t i = 0; i < elements.size () - 1; i++)
//
// if (phint == NULL)
// {
-// double d_shortest (DBL_MAX);
+// double d_shortest (std::numeric_limits<double>::max());
// for (unsigned i = 0; i < elements.size () - 1; i++)
// {
// double d;
Eigen::Vector2d r = p - pt;
double d_shortest_hint = r.squaredNorm ();
- double d_shortest_elem (DBL_MAX);
+ double d_shortest_elem (std::numeric_limits<double>::max());
// evaluate elements
std::vector<double> elements = pcl::on_nurbs::FittingCurve2dPDM::getElementVector (nurbs);
std::vector<double> elements = pcl::on_nurbs::FittingCurve2dPDM::getElementVector (nurbs);
double points[2];
- double d_shortest (DBL_MAX);
+ double d_shortest (std::numeric_limits<double>::max());
double seg = 1.0 / (nurbs.Order () - 1);
for (std::size_t i = 0; i < elements.size () - 1; i++)
#include <pcl/surface/on_nurbs/fitting_curve_pdm.h>
#include <pcl/pcl_macros.h>
+#include <limits>
#include <stdexcept>
using namespace pcl;
std::vector<double> elements = getElementVector (nurbs);
double points[3];
- double d_shortest (DBL_MAX);
+ double d_shortest (std::numeric_limits<double>::max());
for (std::size_t i = 0; i < elements.size () - 1; i++)
{
*
*/
+#include <limits>
#include <stdexcept>
#include <pcl/surface/on_nurbs/fitting_cylinder_pdm.h>
#include <pcl/pcl_macros.h>
eigenvalues /= s; // seems that the eigenvalues are dependent on the number of points (???)
Eigen::Vector3d v_max (0.0, 0.0, 0.0);
- Eigen::Vector3d v_min (DBL_MAX, DBL_MAX, DBL_MAX);
+ Eigen::Vector3d v_min(std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max());
for (unsigned i = 0; i < s; i++)
{
Eigen::Vector3d p (eigenvectors.inverse () * (data->interior[i] - mean));
data->mean = mean;
Eigen::Vector3d v_max (0.0, 0.0, 0.0);
- Eigen::Vector3d v_min (DBL_MAX, DBL_MAX, DBL_MAX);
+ Eigen::Vector3d v_min(std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max());
for (unsigned i = 0; i < s; i++)
{
Eigen::Vector3d p (axes.inverse () * (data->interior[i] - mean));
*
*/
+#include <limits>
#include <stdexcept>
#include <pcl/surface/on_nurbs/fitting_sphere_pdm.h>
#include <pcl/pcl_macros.h>
{
Eigen::Vector3d mean = NurbsTools::computeMean (data->interior);
- Eigen::Vector3d _min (DBL_MAX, DBL_MAX, DBL_MAX);
- Eigen::Vector3d _max (-DBL_MAX, -DBL_MAX, -DBL_MAX);
+ Eigen::Vector3d _min(std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max());
+ Eigen::Vector3d _max(std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest());
for (const auto &i : data->interior)
{
Eigen::Vector3d p = i - mean;
#include <pcl/pcl_macros.h>
#include <Eigen/Cholesky> // for ldlt
+#include <limits>
#include <stdexcept>
using namespace pcl;
FittingSurfaceIM::computeIndexBoundingBox (pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud,
const std::vector<int> &indices)
{
- Eigen::Vector4d bb = Eigen::Vector4d (DBL_MAX, 0, DBL_MAX, 0);
+ Eigen::Vector4d bb = Eigen::Vector4d(
+ std::numeric_limits<double>::max(), 0, std::numeric_limits<double>::max(), 0);
const pcl::PointCloud<pcl::PointXYZRGB> &cloud_ref = *cloud;
for (const auto &index : indices)
std::vector<double> elementsU = getElementVector (nurbs, 0);
std::vector<double> elementsV = getElementVector (nurbs, 1);
- double d_shortest (DBL_MAX);
+ double d_shortest (std::numeric_limits<double>::max());
for (std::size_t i = 0; i < elementsU.size () - 1; i++)
{
for (std::size_t j = 0; j < elementsV.size () - 1; j++)
#include <Eigen/Cholesky> // for ldlt
#include <Eigen/Geometry> // for cross
#include <Eigen/LU> // for inverse
+#include <limits>
#include <stdexcept>
using namespace pcl;
eigenvalues /= s; // seems that the eigenvalues are dependent on the number of points (???)
Eigen::Matrix3d eigenvectors_inv = eigenvectors.inverse ();
- Eigen::Vector3d v_max (-DBL_MAX, -DBL_MAX, -DBL_MAX);
- Eigen::Vector3d v_min (DBL_MAX, DBL_MAX, DBL_MAX);
+ Eigen::Vector3d v_max(std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest());
+ Eigen::Vector3d v_min(std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max());
for (unsigned i = 0; i < s; i++)
{
Eigen::Vector3d p (eigenvectors_inv * (m_data->interior[i] - mean));
std::vector<double> elementsU = getElementVector (nurbs, 0);
std::vector<double> elementsV = getElementVector (nurbs, 1);
- double d_shortest (DBL_MAX);
+ double d_shortest (std::numeric_limits<double>::max());
for (std::size_t i = 0; i < elementsU.size () - 1; i++)
{
for (std::size_t j = 0; j < elementsV.size () - 1; j++)
*/
#include <iostream>
+#include <limits>
#include <stdexcept>
#include <map>
#include <algorithm>
throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n");
std::size_t idx = 0;
- double dist2 (DBL_MAX);
+ double dist2 (std::numeric_limits<double>::max());
for (std::size_t i = 0; i < data.size (); i++)
{
double d2 = (data[i] - p).squaredNorm ();
throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n");
std::size_t idx = 0;
- double dist2 (DBL_MAX);
+ double dist2 (std::numeric_limits<double>::max());
for (std::size_t i = 0; i < data.size (); i++)
{
double d2 = (data[i] - p).squaredNorm ();
std::size_t idx = 0;
idxcp = 0;
double dist2 (0.0);
- double dist2cp (DBL_MAX);
+ double dist2cp (std::numeric_limits<double>::max());
for (std::size_t i = 0; i < data.size (); i++)
{
Eigen::Vector2d v = (data[i] - p);
void
NurbsTools::computeBoundingBox (const ON_NurbsCurve &nurbs, Eigen::Vector3d &_min, Eigen::Vector3d &_max)
{
- _min = Eigen::Vector3d (DBL_MAX, DBL_MAX, DBL_MAX);
- _max = Eigen::Vector3d (-DBL_MAX, -DBL_MAX, -DBL_MAX);
+ _min = Eigen::Vector3d (std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
+ _max = Eigen::Vector3d(std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest());
for (int i = 0; i < nurbs.CVCount (); i++)
{
ON_3dPoint p;
void
NurbsTools::computeBoundingBox (const ON_NurbsSurface &nurbs, Eigen::Vector3d &_min, Eigen::Vector3d &_max)
{
- _min = Eigen::Vector3d (DBL_MAX, DBL_MAX, DBL_MAX);
- _max = Eigen::Vector3d (-DBL_MAX, -DBL_MAX, -DBL_MAX);
+ _min = Eigen::Vector3d(std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::max());
+ _max = Eigen::Vector3d(std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::lowest());
for (int i = 0; i < nurbs.CVCount (0); i++)
{
for (int j = 0; j < nurbs.CVCount (1); j++)
if (unsigned (this->m_data.boundary.size ()) != num_bnd)
{
- printf ("[SequentialFitter::grow] %lu %u\n", this->m_data.boundary.size (), num_bnd);
+ printf ("[SequentialFitter::grow] %zu %u\n", this->m_data.boundary.size (), num_bnd);
throw std::runtime_error ("[SequentialFitter::grow] size of boundary and boundary parameters do not match.");
}
if (this->m_boundary_indices->indices.size () != num_bnd)
{
- printf ("[SequentialFitter::grow] %lu %u\n", this->m_boundary_indices->indices.size (), num_bnd);
+ printf ("[SequentialFitter::grow] %zu %u\n", this->m_boundary_indices->indices.size (), num_bnd);
throw std::runtime_error ("[SequentialFitter::grow] size of boundary indices and boundary parameters do not match.");
}
std::vector<std::uint32_t> out_idx_tmp;
pcl::on_nurbs::vector_vec2d out_pc_tmp;
- for (const unsigned int &vi : poly.vertices)
+ for (const auto &vi : poly.vertices)
{
if (pt_is_in[vi])
in++;
std::vector<std::uint32_t> out_idx_tmp;
pcl::on_nurbs::vector_vec2d out_pc_tmp;
- for (const unsigned int &vi : poly.vertices)
+ for (const auto &vi : poly.vertices)
{
if (pt_is_in[vi])
in++;
{
for (int i = 0; i < nr_polygons; i++)
{
- unsigned int nr_points_in_polygon = static_cast<unsigned int> (mesh.polygons[i].vertices.size ());
+ auto nr_points_in_polygon = static_cast<unsigned int> (mesh.polygons[i].vertices.size ());
vtk_mesh_polygons->InsertNextCell (nr_points_in_polygon);
for (unsigned int j = 0; j < nr_points_in_polygon; j++)
vtk_mesh_polygons->InsertCellPoint(mesh.polygons[i].vertices[j]);
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
set(build TRUE)
set(REASON "Disabled by default")
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
PCL_ADD_TEST(common_bearing_angle_image test_bearing_angle_image FILES test_bearing_angle_image.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_polygon_mesh test_polygon_mesh_concatenate FILES test_polygon_mesh.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_point_type_conversion test_common_point_type_conversion FILES test_point_type_conversion.cpp LINK_WITH pcl_gtest pcl_common)
+PCL_ADD_COMPILETIME_AND_RUNTIME_TEST(common_point_type_construction test_common_point_type_construction FILES test_point_type_construction.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_point_type_static_member_functions test_common_point_type_static_member_functions FILES test_point_type_static_member_functions.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_colors test_colors FILES test_colors.cpp LINK_WITH pcl_gtest pcl_common)
PCL_ADD_TEST(common_type_traits test_type_traits FILES test_type_traits.cpp LINK_WITH pcl_gtest pcl_common)
Indices indices;
PointXYZ point;
PointCloud<PointXYZ> cloud;
- Eigen::Vector4f centroid;
+ Eigen::Vector4f centroid = Eigen::Vector4f::Random();
+ const Eigen::Vector4f old_centroid = centroid;
// test empty cloud which is dense
cloud.is_dense = true;
EXPECT_EQ (compute3DCentroid (cloud, centroid), 0);
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
// test empty cloud non_dense
cloud.is_dense = false;
EXPECT_EQ (compute3DCentroid (cloud, centroid), 0);
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
- // test non-empty cloud non_dense
+ // test non-empty cloud non_dense (with only invalid points)
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
EXPECT_EQ (compute3DCentroid (cloud, centroid), 0);
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
- // test non-empty cloud non_dense
+ // test non-empty cloud non_dense (with only invalid points)
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
indices.push_back (1);
EXPECT_EQ (compute3DCentroid (cloud, indices, centroid), 0);
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
cloud.clear ();
indices.clear ();
Indices indices;
PointXYZ point;
PointCloud<PointXYZ> cloud;
- Eigen::Vector4d centroid;
+ Eigen::Vector4d centroid = Eigen::Vector4d::Random();
+ const Eigen::Vector4d old_centroid = centroid;
// test empty cloud which is dense
cloud.is_dense = true;
EXPECT_EQ (compute3DCentroid (cloud, centroid), 0);
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
// test empty cloud non_dense
cloud.is_dense = false;
EXPECT_EQ (compute3DCentroid (cloud, centroid), 0);
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
- // test non-empty cloud non_dense
+ // test non-empty cloud non_dense (with only invalid points)
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
EXPECT_EQ (compute3DCentroid (cloud, centroid), 0);
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
- // test non-empty cloud non_dense
+ // test non-empty cloud non_dense (with only invalid points)
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
indices.push_back (1);
EXPECT_EQ (compute3DCentroid (cloud, indices, centroid), 0);
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
cloud.clear ();
indices.clear ();
EXPECT_EQ (8, compute3DCentroid (it, centroid_f));
EXPECT_EQ_VECTORS (Eigen::Vector4f (0.f, 0.f, 0.f, 1.f), centroid_f);
+
+ const Eigen::Vector4f old_centroid = centroid_f;
+ indices.clear ();
+ indices.push_back (cloud.size () - 1);
+ ConstCloudIterator<PointXYZ> it2 (cloud, indices);
+ // zero valid points and centroid remains unchanged
+ EXPECT_EQ (0, compute3DCentroid (it2, centroid_f));
+ EXPECT_EQ (old_centroid, centroid_f);
}
}
PointXYZ point;
Indices indices;
Eigen::Vector4f centroid;
- Eigen::Matrix3f covariance_matrix;
+ Eigen::Matrix3f covariance_matrix = Eigen::Matrix3f::Random();
+ const Eigen::Matrix3f old_covariance_matrix = covariance_matrix;
centroid [0] = 0;
centroid [1] = 0;
// test empty cloud which is dense
cloud.is_dense = true;
EXPECT_EQ (computeCovarianceMatrix (cloud, centroid, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
// test empty cloud non_dense
cloud.is_dense = false;
EXPECT_EQ (computeCovarianceMatrix (cloud, centroid, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
- // test non-empty cloud non_dense
+ // test non-empty cloud non_dense (with only invalid points)
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
EXPECT_EQ (computeCovarianceMatrix (cloud, centroid, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
- // test non-empty cloud non_dense
+ // test non-empty cloud non_dense (with only invalid points)
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
indices.push_back (1);
EXPECT_EQ (computeCovarianceMatrix (cloud, indices, centroid, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
cloud.clear ();
indices.clear ();
PointXYZ point;
Indices indices;
Eigen::Vector4f centroid;
- Eigen::Matrix3f covariance_matrix;
+ Eigen::Matrix3f covariance_matrix = Eigen::Matrix3f::Random();
+ const Eigen::Matrix3f old_covariance_matrix = covariance_matrix;
centroid [0] = 0;
centroid [1] = 0;
// test empty cloud which is dense
cloud.is_dense = true;
EXPECT_EQ (computeCovarianceMatrixNormalized (cloud, centroid, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
// test empty cloud non_dense
cloud.is_dense = false;
EXPECT_EQ (computeCovarianceMatrixNormalized (cloud, centroid, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
// test non-empty cloud non_dense
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
EXPECT_EQ (computeCovarianceMatrixNormalized (cloud, centroid, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
// test non-empty cloud non_dense
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
indices.push_back (1);
EXPECT_EQ (computeCovarianceMatrixNormalized (cloud, indices, centroid, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
cloud.clear ();
indices.clear ();
PointCloud<PointXYZ> cloud;
PointXYZ point;
Indices indices;
- Eigen::Matrix3f covariance_matrix;
+ Eigen::Matrix3f covariance_matrix = Eigen::Matrix3f::Random();
+ const Eigen::Matrix3f old_covariance_matrix = covariance_matrix;
// test empty cloud which is dense
cloud.is_dense = true;
EXPECT_EQ (computeCovarianceMatrix (cloud, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
// test empty cloud non_dense
cloud.is_dense = false;
EXPECT_EQ (computeCovarianceMatrix (cloud, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
// test non-empty cloud non_dense
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
EXPECT_EQ (computeCovarianceMatrix (cloud, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
// test non-empty cloud non_dense
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
indices.push_back (1);
EXPECT_EQ (computeCovarianceMatrix (cloud, indices, covariance_matrix), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
cloud.clear ();
indices.clear ();
PointCloud<PointXYZ> cloud;
PointXYZ point;
Indices indices;
- Eigen::Matrix3f covariance_matrix;
- Eigen::Vector4f centroid;
+ Eigen::Matrix3f covariance_matrix = Eigen::Matrix3f::Random();
+ Eigen::Vector4f centroid = Eigen::Vector4f::Random();
+ const Eigen::Matrix3f old_covariance_matrix = covariance_matrix;
+ const Eigen::Vector4f old_centroid = centroid;
// test empty cloud which is dense
cloud.is_dense = true;
EXPECT_EQ (computeMeanAndCovarianceMatrix (cloud, covariance_matrix, centroid), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
// test empty cloud non_dense
cloud.is_dense = false;
EXPECT_EQ (computeMeanAndCovarianceMatrix (cloud, covariance_matrix, centroid), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
// test non-empty cloud non_dense
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
EXPECT_EQ (computeMeanAndCovarianceMatrix (cloud, covariance_matrix, centroid), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
// test non-empty cloud non_dense
point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
cloud.push_back (point);
indices.push_back (1);
EXPECT_EQ (computeMeanAndCovarianceMatrix (cloud, indices, covariance_matrix, centroid), 0);
+ EXPECT_EQ (old_covariance_matrix, covariance_matrix); // cov. matrix remains unchanged
+ EXPECT_EQ (old_centroid, centroid); // centroid remains unchanged
cloud.clear ();
indices.clear ();
EXPECT_EQ (output.height, 640);
EXPECT_EQ (output.width, 480);
EXPECT_EQ (output.size (), 480*640);
- for(pcl::PointCloud<pcl::PointXYZ>::const_iterator points_it = output.begin ();
- points_it != output.end ();
- ++points_it)
+ for(const auto& point_out : output)
{
- EXPECT_GE (points_it->x, 0);
- EXPECT_LT (points_it->x, 1);
- EXPECT_GE (points_it->y, -1);
- EXPECT_LT (points_it->y, 1);
- EXPECT_GE (points_it->z, -2.5);
- EXPECT_LT (points_it->z, 1.5);
+ EXPECT_GE (point_out.x, 0);
+ EXPECT_LT (point_out.x, 1);
+ EXPECT_GE (point_out.y, -1);
+ EXPECT_LT (point_out.y, 1);
+ EXPECT_GE (point_out.z, -2.5);
+ EXPECT_LT (point_out.z, 1.5);
}
}
EXPECT_EQ (output.height, 640);
EXPECT_EQ (output.width, 480);
EXPECT_EQ (output.size (), 480*640);
- for(pcl::PointCloud<pcl::PointXY>::const_iterator points_it = output.begin ();
- points_it != output.end ();
- ++points_it)
+ for(const auto& point_out : output)
{
- EXPECT_GE (points_it->x, 0);
- EXPECT_LT (points_it->x, 1);
- EXPECT_GE (points_it->y, -1);
- EXPECT_LT (points_it->y, 1);
+ EXPECT_GE (point_out.x, 0);
+ EXPECT_LT (point_out.x, 1);
+ EXPECT_GE (point_out.y, -1);
+ EXPECT_LT (point_out.y, 1);
}
}
EXPECT_EQ (output.height, 640);
EXPECT_EQ (output.width, 480);
EXPECT_EQ (output.size (), 480*640);
- for(pcl::PointCloud<pcl::PointXYZ>::const_iterator points_it = output.begin ();
- points_it != output.end ();
- ++points_it)
+ for(const auto& point_out : output)
{
- EXPECT_GE (points_it->x, -3);
- EXPECT_LT (points_it->x, 3);
- EXPECT_GE (points_it->y, -3);
- EXPECT_LT (points_it->y, 3);
- EXPECT_GE (points_it->z, -3);
- EXPECT_LT (points_it->z, 3);
+ EXPECT_GE (point_out.x, -3);
+ EXPECT_LT (point_out.x, 3);
+ EXPECT_GE (point_out.y, -3);
+ EXPECT_LT (point_out.y, 3);
+ EXPECT_GE (point_out.z, -3);
+ EXPECT_LT (point_out.z, 3);
}
}
EXPECT_EQ (output.height, 640);
EXPECT_EQ (output.width, 480);
EXPECT_EQ (output.size (), 480*640);
- for(pcl::PointCloud<pcl::PointXY>::const_iterator points_it = output.begin ();
- points_it != output.end ();
- ++points_it)
+ for(const auto& point_out : output)
{
- EXPECT_GE (points_it->x, -3);
- EXPECT_LT (points_it->x, 3);
- EXPECT_GE (points_it->y, -3);
- EXPECT_LT (points_it->y, 3);
+ EXPECT_GE (point_out.x, -3);
+ EXPECT_LT (point_out.x, 3);
+ EXPECT_GE (point_out.y, -3);
+ EXPECT_LT (point_out.y, 3);
}
}
EXPECT_EQ (p2.x, scalar / 2.0f * p0.x + scalar / 2.0f * p1.x);
EXPECT_EQ (p2.y, scalar / 2.0f * p0.y + scalar / 2.0f * p1.y);
EXPECT_EQ (p2.z, scalar / 2.0f * p0.z + scalar / 2.0f * p1.z);
+
+ { // Addition and addition assignment
+ pcl::PointXYZ point1(1.0f, -0.5f, 2.0f), point2(4.0f, -1.5f, -1.0f);
+ float scalar1 = 2.0f;
+ auto res1 = point1 + point2;
+ EXPECT_XYZ_EQ (res1, pcl::PointXYZ(5.0f, -2.0f, 1.0f));
+ auto res2 = point1 + scalar1;
+ EXPECT_XYZ_EQ (res2, pcl::PointXYZ(3.0f, 1.5f, 4.0f));
+ auto res3 = scalar1 + point1;
+ EXPECT_XYZ_EQ (res3, pcl::PointXYZ(3.0f, 1.5f, 4.0f));
+ point1 += point2;
+ EXPECT_XYZ_EQ (point1, pcl::PointXYZ(5.0f, -2.0f, 1.0f));
+ point2 += scalar1;
+ EXPECT_XYZ_EQ (point2, pcl::PointXYZ(6.0f, 0.5f, 1.0f));
+ }
+ { // Subtraction and subtraction assignment
+ pcl::PointXYZ point1(1.0f, -0.5f, 2.0f), point2(4.0f, -1.5f, -1.0f);
+ float scalar1 = 2.0f;
+ auto res1 = point1 - point2;
+ EXPECT_XYZ_EQ (res1, pcl::PointXYZ(-3.0f, 1.0f, 3.0f));
+ auto res2 = point1 - scalar1;
+ EXPECT_XYZ_EQ (res2, pcl::PointXYZ(-1.0f, -2.5f, 0.0f));
+ auto res3 = scalar1 - point1;
+ EXPECT_XYZ_EQ (res3, pcl::PointXYZ(1.0f, 2.5f, 0.0f));
+ point1 -= point2;
+ EXPECT_XYZ_EQ (point1, pcl::PointXYZ(-3.0f, 1.0f, 3.0f));
+ point2 -= scalar1;
+ EXPECT_XYZ_EQ (point2, pcl::PointXYZ(2.0f, -3.5f, -3.0f));
+ }
+ { // Multiplication and multiplication assignment
+ pcl::PointXYZ point1(1.0f, -0.5f, 2.0f), point2(4.0f, -1.5f, -1.0f);
+ float scalar1 = 2.0f;
+ auto res2 = point1 * scalar1;
+ EXPECT_XYZ_EQ (res2, pcl::PointXYZ(2.0f, -1.0f, 4.0f));
+ auto res3 = scalar1 * point1;
+ EXPECT_XYZ_EQ (res3, pcl::PointXYZ(2.0f, -1.0f, 4.0f));
+ point2 *= scalar1;
+ EXPECT_XYZ_EQ (point2, pcl::PointXYZ(8.0f, -3.0f, -2.0f));
+ }
+ { // Division and division assignment
+ pcl::PointXYZ point1(1.0f, -0.5f, 2.0f), point2(4.0f, -2.0f, -1.0f);
+ float scalar1 = 2.0f;
+ auto res2 = point1 / scalar1;
+ EXPECT_XYZ_EQ (res2, pcl::PointXYZ(0.5f, -0.25f, 1.0f));
+ auto res3 = scalar1 / point1;
+ EXPECT_XYZ_EQ (res3, pcl::PointXYZ(2.0f, -4.0f, 1.0f));
+ point2 /= scalar1;
+ EXPECT_XYZ_EQ (point2, pcl::PointXYZ(2.0f, -1.0f, -0.5f));
+ }
}
//////////////////////////////////////////////////////////////////////////////
{
pca.project (point, projected);
pca.reconstruct (projected, reconstructed);
- EXPECT_NEAR_VECTORS (reconstructed.getVector3fMap (), point.getVector3fMap (), 2.5e-4);
+ EXPECT_NEAR_VECTORS (reconstructed.getVector3fMap (), point.getVector3fMap (), 5e-4);
}
}
for(std::size_t i = 0; i < cloud.size(); i++)
EXPECT_NEAR_VECTORS (cloud[i].getVector3fMap (),
cloud_reconstructed[i].getVector3fMap (),
- 2.5e-4);
+ 5e-4);
}
catch (pcl::InitFailedException &/*e*/)
{
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2014-, Open Perception Inc.
+ *
+ * All rights reserved
+ */
+
+#include <pcl/test/gtest.h>
+#include <pcl/pcl_tests.h>
+#include <pcl/point_types.h>
+
+using namespace pcl;
+using namespace pcl::test;
+
+TEST (PointTypeConstruction, PointXYZDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZ pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZThreeScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZ pt(2.0f, 3.0f, 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZIDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZI pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZIFourScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZI pt(2.0f, 3.0f, 4.0f, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity, 5.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZLDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZL pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_INT_EQ(pt.label, 0u);
+}
+
+TEST (PointTypeConstruction, PointXYZLFourScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZL pt(2.0f, 3.0f, 4.0f, 5u);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_INT_EQ(pt.label, 5u);
+}
+
+TEST (PointTypeConstruction, IntensityDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::Intensity pt;
+ PCL_EXPECT_FLOAT_EQ(pt.intensity, 0.0f);
+}
+
+TEST (PointTypeConstruction, IntensityOneScalarConstruction)
+{
+ PCL_CONSTEXPR const pcl::Intensity pt(1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity, 1.0f);
+}
+
+TEST (PointTypeConstruction, Intensity8uDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::Intensity8u pt;
+ PCL_EXPECT_INT_EQ(pt.intensity, std::uint8_t{});
+}
+
+TEST (PointTypeConstruction, Intensity8uOneScalarConstruction)
+{
+ PCL_CONSTEXPR const pcl::Intensity8u pt(1u);
+ PCL_EXPECT_INT_EQ(pt.intensity, 1u);
+}
+
+TEST (PointTypeConstruction, Intensity32uDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::Intensity32u pt;
+ PCL_EXPECT_INT_EQ(pt.intensity, std::uint32_t{});
+}
+
+TEST (PointTypeConstruction, Intensity32uOneScalarConstruction)
+{
+ PCL_CONSTEXPR const pcl::Intensity32u pt(1u);
+ PCL_EXPECT_INT_EQ(pt.intensity, std::uint32_t{1u});
+}
+
+TEST (PointTypeConstruction, LabelDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::Label pt;
+ PCL_EXPECT_INT_EQ(pt.label, 0u);
+}
+
+TEST (PointTypeConstruction, LabelOneScalarConstruction)
+{
+ PCL_CONSTEXPR const pcl::Label pt(1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.label, 1u);
+}
+
+TEST (PointTypeConstruction, PointXYZRGBADefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZRGBA pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 0u);
+ PCL_EXPECT_INT_EQ(pt.g, 0u);
+ PCL_EXPECT_INT_EQ(pt.b, 0u);
+ PCL_EXPECT_INT_EQ(pt.a, 255u);
+}
+
+TEST (PointTypeConstruction, PointXYZRGBASevenScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZRGBA pt(2.0f, 3.0f, 4.0f, 2u, 3u, 4u, 5u);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 2u);
+ PCL_EXPECT_INT_EQ(pt.g, 3u);
+ PCL_EXPECT_INT_EQ(pt.b, 4u);
+ PCL_EXPECT_INT_EQ(pt.a, 5u);
+}
+
+TEST (PointTypeConstruction, PointXYZRGBDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZRGB pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 0u);
+ PCL_EXPECT_INT_EQ(pt.g, 0u);
+ PCL_EXPECT_INT_EQ(pt.b, 0u);
+}
+
+TEST (PointTypeConstruction, PointXYZRGBSixScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZRGB pt(2.0f, 3.0f, 4.0f, 2u, 3u, 4u);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 2u);
+ PCL_EXPECT_INT_EQ(pt.g, 3u);
+ PCL_EXPECT_INT_EQ(pt.b, 4u);
+}
+
+TEST (PointTypeConstruction, PointXYZRGBLDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZRGBL pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 0u);
+ PCL_EXPECT_INT_EQ(pt.g, 0u);
+ PCL_EXPECT_INT_EQ(pt.b, 0u);
+ PCL_EXPECT_INT_EQ(pt.label, 0u);
+}
+
+TEST (PointTypeConstruction, PointXYZRGBLSevenScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZRGBL pt(2.0f, 3.0f, 4.0f, 2u, 3u, 4u, 5u);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 2u);
+ PCL_EXPECT_INT_EQ(pt.g, 3u);
+ PCL_EXPECT_INT_EQ(pt.b, 4u);
+ PCL_EXPECT_INT_EQ(pt.label, 5u);
+}
+
+TEST (PointTypeConstruction, PointXYZLABDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZLAB pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.L, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.a, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.b, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZLABSixScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZLAB pt(2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.L, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.a, 6.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.b, 7.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZHSVDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZHSV pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.h, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.s, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.v, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZHSVSixScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZHSV pt(2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.h, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.s, 6.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.v, 7.0f);
+}
+
+TEST (PointTypeConstruction, PointXYDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXY pt;
+ PCL_EXPECT_FLOAT_EQ(pt.x, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.y, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointXYTwoScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXY pt(1.0f, 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.x, 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.y, 2.0f);
+}
+
+TEST (PointTypeConstruction, PointUVDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointUV pt;
+ PCL_EXPECT_FLOAT_EQ(pt.u, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.v, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointUVTwoScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointUV pt(1.0f, 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.u, 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.v, 2.0f);
+}
+
+TEST (PointTypeConstruction, NormalDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::Normal pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 0.0f);
+}
+
+TEST (PointTypeConstruction, NormalFourScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::Normal pt(2.0f, 3.0f, 4.0f, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 5.0f);
+}
+
+TEST (PointTypeConstruction, AxisDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::Axis pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+}
+
+TEST (PointTypeConstruction, AxisThreeScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::Axis pt(2.0f, 3.0f, 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+}
+
+TEST (PointTypeConstruction, PointNormalDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointNormal pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+}
+
+TEST (PointTypeConstruction, PointNormalSixScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointNormal pt(2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 6.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 7.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+}
+
+
+TEST (PointTypeConstruction, PointXYZRGBNormalDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZRGBNormal pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 0u);
+ PCL_EXPECT_INT_EQ(pt.g, 0u);
+ PCL_EXPECT_INT_EQ(pt.b, 0u);
+ PCL_EXPECT_INT_EQ(pt.a, 255u);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZRGBNormalTenScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZRGBNormal pt(2.0f, 3.0f, 4.0f, 5u, 6u, 7u, 8.0f, 9.0f, 10.0f, 11.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 8.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 9.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 10.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 5u);
+ PCL_EXPECT_INT_EQ(pt.g, 6u);
+ PCL_EXPECT_INT_EQ(pt.b, 7u);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 11.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZINormalDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZINormal pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZINormalTenScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZINormal pt(2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 6.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 7.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 8.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 9.0f);
+}
+
+TEST (PointTypeConstruction, PointXYZLNormalDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZLNormal pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_INT_EQ(pt.label, 0u);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 0.0f);
+
+}
+
+TEST (PointTypeConstruction, PointXYZLNormalTenScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointXYZLNormal pt(2.0f, 3.0f, 4.0f, 5u, 6.0f, 7.0f, 8.0f, 9.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 6.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 7.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 8.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_INT_EQ(pt.label, 5u);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 9.0f);
+}
+
+TEST (PointTypeConstruction, PointWithRangeDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointWithRange pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.range, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointWithRangeFourScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointWithRange pt(2.0f, 3.0f, 4.0f, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.range, 5.0f);
+}
+
+TEST (PointTypeConstruction, PointWithViewpointDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointWithViewpoint pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.vp_x, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.vp_y, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.vp_z, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointWithViewpointSixScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointWithViewpoint pt(2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.vp_x, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.vp_y, 6.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.vp_z, 7.0f);
+}
+
+TEST (PointTypeConstruction, MomentInvariantsDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::MomentInvariants pt;
+ PCL_EXPECT_FLOAT_EQ(pt.j1, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.j2, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.j3, 0.0f);
+}
+
+TEST (PointTypeConstruction, MomentInvariantsThreeScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::MomentInvariants pt(1.0f, 2.0f, 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.j1, 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.j2, 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.j3, 3.0f);
+}
+
+TEST (PointTypeConstruction, PrincipalRadiiRSDDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PrincipalRadiiRSD pt;
+ PCL_EXPECT_FLOAT_EQ(pt.r_min, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.r_max, 0.0f);
+}
+
+TEST (PointTypeConstruction, PrincipalRadiiRSDScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PrincipalRadiiRSD pt(1.0f, 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.r_min, 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.r_max, 2.0f);
+}
+
+TEST (PointTypeConstruction, BoundaryDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::Boundary pt;
+ PCL_EXPECT_INT_EQ(pt.boundary_point, std::uint8_t{});
+}
+
+TEST (PointTypeConstruction, BoundaryOneScalarConstruction)
+{
+ PCL_CONSTEXPR const pcl::Boundary pt(1u);
+ PCL_EXPECT_INT_EQ(pt.boundary_point, std::uint8_t{1u});
+}
+
+TEST (PointTypeConstruction, PrincipalCurvaturesDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PrincipalCurvatures pt;
+ PCL_EXPECT_FLOAT_EQ(pt.principal_curvature_x, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.principal_curvature_y, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.principal_curvature_z, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.pc1, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.pc2, 0.0f);
+}
+
+TEST (PointTypeConstruction, PrincipalCurvaturesFiveScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PrincipalCurvatures pt(2.0f, 3.0f, 4.0f, 5.0f, 6.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.principal_curvature_x, 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.principal_curvature_y, 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.principal_curvature_z, 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.pc1, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.pc2, 6.0f);
+}
+
+TEST (PointTypeConstruction, ReferenceFrameDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::ReferenceFrame pt;
+ PCL_EXPECT_FLOAT_EQ(pt.rf[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[3], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[4], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[5], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[6], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[7], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[8], 0.0f);
+}
+
+TEST (PointTypeConstruction, ReferenceFrameArrayOfScalarsConstruction)
+{
+ PCL_CONSTEXPR const float values[9]{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f };
+ PCL_CONSTEXPR const pcl::ReferenceFrame pt(values);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[0], values[0]);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[1], values[1]);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[2], values[2]);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[3], values[3]);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[4], values[4]);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[5], values[5]);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[6], values[6]);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[7], values[7]);
+ PCL_EXPECT_FLOAT_EQ(pt.rf[8], values[8]);
+}
+
+
+namespace pcl
+{
+
+// to be replaced with std:: when C++20 is available
+// implementations taken from cppreference.com
+
+template<class InputIt, class UnaryPredicate>
+constexpr InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q)
+{
+ for (; first != last; ++first) {
+ if (!q(*first)) {
+ return first;
+ }
+ }
+ return last;
+}
+
+template <class InputIt, class UnaryPredicate>
+constexpr bool all_of(InputIt first, InputIt last, UnaryPredicate p)
+{
+ return pcl::find_if_not(first, last, p) == last;
+}
+
+// may be replaced with lambda when C++17 is available
+constexpr bool is_equal_to_zero(float value)
+{
+ return value == 0.0f;
+}
+
+}
+
+template <typename T> class PointTypesWithRawArrayMemberTest : public ::testing::Test { };
+using PointTypesWithRawArrayMember
+ = ::testing::Types<
+ pcl::FPFHSignature33,
+ pcl::VFHSignature308,
+ pcl::GRSDSignature21,
+ pcl::ESFSignature640,
+ pcl::GASDSignature512,
+ pcl::GASDSignature984,
+ pcl::GASDSignature7992,
+ pcl::GFPFHSignature16>;
+TYPED_TEST_SUITE (PointTypesWithRawArrayMemberTest, PointTypesWithRawArrayMember);
+
+TYPED_TEST (PointTypesWithRawArrayMemberTest, ConstexprDefaultConstructionTests)
+{
+ PCL_CONSTEXPR const TypeParam pt;
+ PCL_EXPECT_TRUE(pcl::all_of(std::cbegin(pt.histogram), std::cend(pt.histogram), &pcl::is_equal_to_zero));
+}
+
+TEST (PointTypeConstuction, BRISKSignature512DefaultConstruction)
+{
+ PCL_CONSTEXPR const BRISKSignature512 pt;
+ PCL_EXPECT_TRUE(pcl::all_of(std::cbegin(pt.descriptor), std::cend(pt.descriptor), &pcl::is_equal_to_zero));
+}
+
+TEST (PointTypeConstruction, Narf36DefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::Narf36 pt;
+ PCL_EXPECT_FLOAT_EQ(pt.x, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.y, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.z, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.roll, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.pitch, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.yaw, 0.0f);
+}
+
+TEST (PointTypeConstruction, Narf36ThreeScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::Narf36 pt{1.0f, 2.0f, 3.0f};
+ PCL_EXPECT_FLOAT_EQ(pt.x, 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.y, 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.z, 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.roll, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.pitch, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.yaw, 0.0f);
+}
+
+TEST (PointTypeConstruction, Narf36SixScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::Narf36 pt{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
+ PCL_EXPECT_FLOAT_EQ(pt.x, 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.y, 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.z, 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.roll, 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.pitch, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.yaw, 6.0f);
+}
+
+TEST (PointTypeConstruction, BorderDescriptionDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::BorderDescription pt;
+ PCL_EXPECT_INT_EQ(pt.x, 0);
+ PCL_EXPECT_INT_EQ(pt.y, 0);
+}
+
+
+TEST (PointTypeConstruction, BorderDescriptionTwoScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::BorderDescription pt{1, 2};
+ PCL_EXPECT_INT_EQ(pt.x, 1);
+ PCL_EXPECT_INT_EQ(pt.y, 2);
+}
+
+TEST (PointTypeConstruction, IntensityGradientDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::IntensityGradient pt;
+ PCL_EXPECT_FLOAT_EQ(pt.gradient_x, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.gradient_y, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.gradient_z, 0.0f);
+}
+
+TEST (PointTypeConstruction, IntensityGradientThreeScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::IntensityGradient pt{1.0f, 2.0f, 3.0f};
+ PCL_EXPECT_FLOAT_EQ(pt.gradient_x, 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.gradient_y, 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.gradient_z, 3.0f);
+}
+
+TEST (PointTypeConstruction, PointWithScaleDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointWithScale pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.scale, 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.angle, -1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.response, 0.0f);
+ PCL_EXPECT_INT_EQ(pt.octave, 0);
+}
+
+TEST (PointTypeConstruction, PointWithScaleSevenScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointWithScale pt{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7};
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.scale, 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.angle, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.response, 6.0f);
+ PCL_EXPECT_INT_EQ(pt.octave, 7);
+}
+
+TEST (PointTypeConstruction, PointSurfelDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointSurfel pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 0u);
+ PCL_EXPECT_INT_EQ(pt.g, 0u);
+ PCL_EXPECT_INT_EQ(pt.b, 0u);
+ PCL_EXPECT_INT_EQ(pt.a, 0u);
+ PCL_EXPECT_FLOAT_EQ(pt.radius, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.confidence, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointSurfelTenScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointSurfel pt{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7u, 8u, 9u, 10u, 11.0f, 12.0f, 13.0f};
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[0], 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[1], 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[2], 6.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data_n[3], 0.0f);
+ PCL_EXPECT_INT_EQ(pt.r, 7u);
+ PCL_EXPECT_INT_EQ(pt.g, 8u);
+ PCL_EXPECT_INT_EQ(pt.b, 9u);
+ PCL_EXPECT_INT_EQ(pt.a, 10u);
+ PCL_EXPECT_FLOAT_EQ(pt.radius, 11.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.confidence, 12.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.curvature, 13.0f);
+}
+
+TEST (PointTypeConstruction, PointDEMDefaultConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointDEM pt;
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity_variance, 0.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.height_variance, 0.0f);
+}
+
+TEST (PointTypeConstruction, PointDEMSixScalarsConstruction)
+{
+ PCL_CONSTEXPR const pcl::PointDEM pt{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
+ PCL_EXPECT_FLOAT_EQ(pt.data[0], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[1], 2.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[2], 3.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.data[3], 1.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity, 4.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.intensity_variance, 5.0f);
+ PCL_EXPECT_FLOAT_EQ(pt.height_variance, 6.0f);
+}
+
+int
+main (int argc, char** argv)
+{
+ testing::InitGoogleTest (&argc, argv);
+ return (RUN_ALL_TESTS ());
+}
EXPECT_EQ (cloud_d.height, cloud_f.height);
}
+TEST (PCL, PointXY)
+{
+ Eigen::Matrix<float, 2, 2> A;
+ A << 1.0, 0.0, 0.0, -1.0;
+ Eigen::Affine2f tf{A};
+ pcl::PointCloud<pcl::PointXY> p,q;
+
+ p.push_back (pcl::PointXY ( 3.0, 1.0));
+ p.push_back (pcl::PointXY ( 2.0, 3.0));
+
+ pcl::transformPointCloud(p,q,tf,true);
+ ASSERT_EQ(p.size(),q.size());
+ for (std::size_t i = 0; i < q.size () ;i++)
+ {
+ EXPECT_FLOAT_EQ(q[i].x, p[i].x);
+ EXPECT_FLOAT_EQ(q[i].y, -p[i].y);
+ }
+
+ float theta = 30.0;
+ Eigen::Matrix<float, 2, 2> B;
+ B << cosf(theta),-sinf(theta), cosf(theta), sinf(theta);
+ Eigen::Affine2f tf2{B};
+ pcl::PointCloud<pcl::PointXY> cloud_in,cloud_out;
+
+ cloud_in.push_back (pcl::PointXY ( 3.0, 1.0));
+ cloud_in.push_back (pcl::PointXY ( 2.0, 3.0));
+
+ pcl::transformPointCloud(cloud_in,cloud_out,tf2,true);
+ ASSERT_EQ(cloud_in.size(),cloud_out.size());
+ for (std::size_t i = 0;i < cloud_out.size () ;i++)
+ {
+ EXPECT_FLOAT_EQ(cloud_out[i].x, ((cloud_in[i].x * cosf(theta)) - (cloud_in[i].y * sinf(theta))));
+ EXPECT_FLOAT_EQ(cloud_out[i].y, ((cloud_in[i].x * cosf(theta)) + (cloud_in[i].y * sinf(theta))));
+ }
+
+ Eigen::Matrix<float, 2, 3> C;
+ C << 1, 0, 1, 0, 1, 2;
+ Eigen::Affine2f t{C};
+ pcl::PointCloud<pcl::PointXY> c_in,c_out;
+
+ c_in.push_back (pcl::PointXY ( 3.0, 1.0));
+ c_in.push_back (pcl::PointXY ( 2.0, 3.0));
+
+ pcl::transformPointCloud(c_in,c_out,t,true);
+ for (std::size_t i = 0; i < c_out.size ();i++)
+ {
+ EXPECT_FLOAT_EQ(c_out[i].x, (c_in[i].x + 1));
+ EXPECT_FLOAT_EQ(c_out[i].y, (c_in[i].y + 2));
+ }
+}
+
/* ---[ */
int
main (int argc, char** argv)
EXPECT_EQ (cloud2.width, 5);
EXPECT_EQ (cloud2.height, 80);
EXPECT_EQ (cloud2.size (), 5*80);
- for (PointCloud<PointXYZ>::const_iterator pit = cloud2.begin (); pit != cloud2.end (); ++pit)
+ for (const auto& point : cloud2)
{
- EXPECT_NEAR (pit->x, 0.1, 1e-3);
- EXPECT_NEAR (pit->y, 0.2, 1e-3);
- EXPECT_NEAR (pit->z, 0.3, 1e-3);
+ EXPECT_NEAR (point.x, 0.1, 1e-3);
+ EXPECT_NEAR (point.y, 0.2, 1e-3);
+ EXPECT_NEAR (point.z, 0.3, 1e-3);
}
}
for (std::uint32_t i = 0; i < 10; ++i)
cloud2[i] = PointXYZ (5.0f * static_cast<float>(i) + 0, 5.0f * static_cast<float> (i) + 1, 5.0f * static_cast<float> (i) + 2);
- std::uint32_t old_size = static_cast<std::uint32_t> (cloud.size ());
+ auto old_size = static_cast<std::uint32_t> (cloud.size ());
cloud.insert (cloud.begin (), cloud2.begin (), cloud2.end ());
EXPECT_EQ (cloud.width, cloud.size ());
EXPECT_EQ (cloud.height, 1);
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
// computeCovarianceMatrix (indices)
Eigen::Matrix3f covariance_matrix;
- computeCovarianceMatrix (cloud, indices, centroid3, covariance_matrix);
+ auto result = computeCovarianceMatrix (cloud, indices, centroid3, covariance_matrix);
+ ASSERT_GT (result, 0);
EXPECT_NEAR (covariance_matrix (0, 0), 0.710046, 1e-4);
EXPECT_NEAR (covariance_matrix (0, 1), -0.234843, 1e-4);
EXPECT_NEAR (covariance_matrix (0, 2), 0.0704933, 1e-4);
EXPECT_NEAR (covariance_matrix (2, 2), 0.195448, 1e-4);
// computeCovarianceMatrix
- computeCovarianceMatrix (cloud, centroid3, covariance_matrix);
+ result = computeCovarianceMatrix (cloud, centroid3, covariance_matrix);
+ ASSERT_GT (result, 0);
EXPECT_NEAR (covariance_matrix (0, 0), 0.710046, 1e-4);
EXPECT_NEAR (covariance_matrix (0, 1), -0.234843, 1e-4);
EXPECT_NEAR (covariance_matrix (0, 2), 0.0704933, 1e-4);
EXPECT_NEAR (covariance_matrix (2, 2), 0.195448, 1e-4);
// computeCovarianceMatrixNormalized (indices)
- computeCovarianceMatrixNormalized (cloud, indices, centroid3, covariance_matrix);
+ result = computeCovarianceMatrixNormalized (cloud, indices, centroid3, covariance_matrix);
+ ASSERT_GT (result, 0);
EXPECT_NEAR (covariance_matrix (0, 0), 1.7930e-03, 1e-5);
EXPECT_NEAR (covariance_matrix (0, 1), -5.9304e-04, 1e-5);
EXPECT_NEAR (covariance_matrix (0, 2), 1.7801e-04, 1e-5);
EXPECT_NEAR (covariance_matrix (2, 2), 4.9356e-04, 1e-5);
// computeCovarianceMatrixNormalized
- computeCovarianceMatrixNormalized (cloud, centroid3, covariance_matrix);
+ result = computeCovarianceMatrixNormalized (cloud, centroid3, covariance_matrix);
+ ASSERT_GT (result, 0);
EXPECT_NEAR (covariance_matrix (0, 0), 1.7930e-03, 1e-5);
EXPECT_NEAR (covariance_matrix (0, 1), -5.9304e-04, 1e-5);
EXPECT_NEAR (covariance_matrix (0, 2), 1.7801e-04, 1e-5);
// set nans for odd fields
if (xIdx & 1)
{
- data[row_stride * yIdx + element_stride * xIdx] = std::numeric_limits<float>::quiet_NaN ();;
- data[row_stride * yIdx + element_stride * xIdx + 1] = std::numeric_limits<float>::quiet_NaN ();;
- data[row_stride * yIdx + element_stride * xIdx + 2] = std::numeric_limits<float>::quiet_NaN ();;
+ data[row_stride * yIdx + element_stride * xIdx] = std::numeric_limits<float>::quiet_NaN ();
+ data[row_stride * yIdx + element_stride * xIdx + 1] = std::numeric_limits<float>::quiet_NaN ();
+ data[row_stride * yIdx + element_stride * xIdx + 2] = std::numeric_limits<float>::quiet_NaN ();
}
else
{
!std::isfinite(output (u, v).normal_z))
continue;
- if (std::abs(fabs (output (u, v).normal_z) - 1) > 1e-2)
+ if (std::abs(std::abs (output (u, v).normal_z) - 1) > 1e-2)
{
std::cout << "T:" << u << " , " << v << " : " << output (u, v).normal_x << " , " << output (u, v).normal_y << " , " << output (u, v).normal_z <<std::endl;
}
!std::isfinite(output (u, v).normal_z))
continue;
- if (std::abs(fabs (output (u, v).normal_z) - 1) > 1e-2)
+ if (std::abs(std::abs (output (u, v).normal_z) - 1) > 1e-2)
{
std::cout << "T:" << u << " , " << v << " : " << output (u, v).normal_x << " , " << output (u, v).normal_y << " , " << output (u, v).normal_z <<std::endl;
}
!std::isfinite(output (u, v).normal_z))
continue;
- if (std::abs(fabs (output (u, v).normal_z) - 1) > 1e-2)
+ if (std::abs(std::abs (output (u, v).normal_z) - 1) > 1e-2)
{
std::cout << "T:" << u << " , " << v << " : " << output (u, v).normal_x << " , " << output (u, v).normal_y << " , " << output (u, v).normal_z <<std::endl;
}
std::vector <float> eccentricity;
feature_extractor.getMomentOfInertia (moment_of_inertia);
feature_extractor.getEccentricity (eccentricity);
- unsigned int m_size = static_cast <unsigned int> (moment_of_inertia.size ());
- unsigned int e_size = static_cast <unsigned int> (eccentricity.size ());
+ auto m_size = static_cast <unsigned int> (moment_of_inertia.size ());
+ auto e_size = static_cast <unsigned int> (eccentricity.size ());
EXPECT_EQ (m_size, e_size);
EXPECT_NE (0, m_size);
}
return (-1);
}
- cloud = (new pcl::PointCloud<pcl::PointXYZ> ())->makeShared ();
+ cloud.reset (new pcl::PointCloud<pcl::PointXYZ> ());
if (pcl::io::loadPCDFile (argv[1], *cloud) < 0)
{
std::cerr << "Failed to read test file. Please download `lamppost.pcd` and pass its path to the test." << std::endl;
class DummySearch : public pcl::search::Search<PointT>
{
public:
- virtual int nearestKSearch (const PointT &point, int k, pcl::Indices &k_indices,
- std::vector<float> &k_sqr_distances ) const
+ int nearestKSearch (const PointT &point, int k, pcl::Indices &k_indices,
+ std::vector<float> &k_sqr_distances ) const override
{
pcl::utils::ignore(point);
return k;
}
- virtual int radiusSearch (const PointT& point, double radius, pcl::Indices& k_indices,
- std::vector<float>& k_sqr_distances, unsigned int max_nn = 0 ) const
+ int radiusSearch (const PointT& point, double radius, pcl::Indices& k_indices,
+ std::vector<float>& k_sqr_distances, unsigned int max_nn = 0 ) const override
{
pcl::utils::ignore(point, radius, k_indices, k_sqr_distances);
struct FPFHTest<FPFHEstimationOMP<PointT, PointT, FPFHSignature33> >
: public ::testing::Test
{
- // Default Constructor is defined to instantiate 4 threads
- FPFHTest<FPFHEstimationOMP<PointT, PointT, FPFHSignature33> > ()
- : fpfh (4)
- {}
-
- FPFHEstimationOMP<PointT, PointT, FPFHSignature33> fpfh;
+ FPFHEstimationOMP<PointT, PointT, FPFHSignature33> fpfh{4}; // 4 threads
};
// Types which will be instantiated
// Compare to independently verified values
const RIFTDescriptor &rift = rift_output[220];
- float correct_rift_feature_values[32];
- unsigned major, minor, patch;
- std::sscanf (FLANN_VERSION_, "%u.%u.%u", &major, &minor, &patch);
- if (PCL_VERSION_CALC (major, minor, patch) > PCL_VERSION_CALC (1, 8, 4))
- {
- const float data[32] = {0.0052f, 0.0349f, 0.0647f, 0.0881f, 0.0042f, 0.0131f, 0.0346f, 0.0030f,
- 0.0076f, 0.0218f, 0.0463f, 0.0030f, 0.0087f, 0.0288f, 0.0920f, 0.0472f,
- 0.0211f, 0.0420f, 0.0726f, 0.0669f, 0.0090f, 0.0901f, 0.1274f, 0.2185f,
- 0.0147f, 0.1222f, 0.3568f, 0.4348f, 0.0149f, 0.0806f, 0.2787f, 0.6864f};
- std::copy (data, data + 32, correct_rift_feature_values);
- }
- else
- {
- const float data[32] = {0.0187f, 0.0349f, 0.0647f, 0.0881f, 0.0042f, 0.0131f, 0.0346f, 0.0030f,
- 0.0076f, 0.0218f, 0.0463f, 0.0030f, 0.0087f, 0.0288f, 0.0920f, 0.0472f,
- 0.0076f, 0.0420f, 0.0726f, 0.0669f, 0.0090f, 0.0901f, 0.1274f, 0.2185f,
- 0.0147f, 0.1222f, 0.3568f, 0.4348f, 0.0149f, 0.0806f, 0.2787f, 0.6864f};
- std::copy (data, data + 32, correct_rift_feature_values);
- }
+ const float correct_rift_feature_values[32] =
+ {0.0052f, 0.0349f, 0.0647f, 0.0881f, 0.0042f, 0.0131f, 0.0346f, 0.0030f,
+ 0.0076f, 0.0218f, 0.0463f, 0.0030f, 0.0087f, 0.0288f, 0.0920f, 0.0472f,
+ 0.0211f, 0.0420f, 0.0726f, 0.0669f, 0.0090f, 0.0901f, 0.1274f, 0.2185f,
+ 0.0147f, 0.1222f, 0.3568f, 0.4348f, 0.0149f, 0.0806f, 0.2787f, 0.6864f};
for (int i = 0; i < 32; ++i)
EXPECT_NEAR (rift.histogram[i], correct_rift_feature_values[i], 1e-4);
}
return (-1);
}
- cloud = (new pcl::PointCloud<pcl::PointXYZ> ())->makeShared ();
+ cloud.reset (new pcl::PointCloud<pcl::PointXYZ> ());
if (pcl::io::loadPCDFile (argv[1], *cloud) < 0)
{
std::cerr << "Failed to read test file. Please download `rops_cloud.pcd` and pass its path to the test." << std::endl;
struct SHOTShapeTest<SHOTEstimationOMP<PointXYZ, Normal, SHOT352> >
: public ::testing::Test
{
- // Default Constructor is defined to instantiate 4 threads
- SHOTShapeTest<SHOTEstimationOMP<PointXYZ, Normal, SHOT352> > ()
- : shot (4)
- {}
-
- SHOTEstimationOMP<PointXYZ, Normal, SHOT352> shot;
+ SHOTEstimationOMP<PointXYZ, Normal, SHOT352> shot{4}; // 4 threads
};
// Types which will be instantiated
struct SHOTShapeAndColorTest<SHOTColorEstimationOMP<PointXYZRGBA, Normal, SHOT1344> >
: public ::testing::Test
{
- // Default Constructor is defined to instantiate 4 threads
- SHOTShapeAndColorTest<SHOTColorEstimationOMP<PointXYZRGBA, Normal, SHOT1344> > ()
- : shot (true, true, 4)
- {}
-
- SHOTColorEstimationOMP<PointXYZRGBA, Normal, SHOT1344> shot;
+ SHOTColorEstimationOMP<PointXYZRGBA, Normal, SHOT1344> shot{true, true, 4}; // 4 threads
};
// Types which will be instantiated
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
FILES test_uniform_sampling.cpp
LINK_WITH pcl_gtest pcl_common pcl_filters)
+PCL_ADD_TEST(filters_farthest_point_sampling test_farthest_point_sampling
+ FILES test_farthest_point_sampling.cpp
+ LINK_WITH pcl_gtest pcl_filters pcl_io
+ ARGUMENTS "${PCL_SOURCE_DIR}/test/bunny.pcd")
+
PCL_ADD_TEST(filters_convolution test_convolution
FILES test_convolution.cpp
LINK_WITH pcl_gtest pcl_filters)
if (value <= lower_bound) return colormap[0];
if (value >= upper_bound) return colormap.back();
float step_size = (upper_bound - lower_bound) / static_cast<float>(colormap.size() - 1);
- std::size_t lower_index = static_cast<std::size_t>((value - lower_bound) / step_size);
+ auto lower_index = static_cast<std::size_t>((value - lower_bound) / step_size);
value -= (lower_bound + static_cast<float>(lower_index) * step_size);
if (value == 0) return colormap[lower_index];
auto interpolate = [](std::uint8_t lower, std::uint8_t upper, float step_size, float value) {
float y1 = -2.0f + (4.0f / (float)input->height) * (float)r;
float x2 = -M_PI + (2.0f * M_PI / (float)input->width) * (float)c;
float y2 = -2.0f + (4.0f / (float)input->height) * (float)r;
- float z = x1 * exp(-(x1 * x1 + y1 * y1)) * 2.5f + sin(x2) * sin(y2);
+ float z = x1 * std::exp(-(x1 * x1 + y1 * y1)) * 2.5f + std::sin(x2) * std::sin(y2);
(*input) (c, r) = interpolate_color(-1.6f, 1.6f, z);
}
float y1 = -2.0f + (4.0f / (float)input->height) * (float)r;
float x2 = -M_PI + (2.0f * M_PI / (float)input->width) * (float)c;
float y2 = -2.0f + (4.0f / (float)input->height) * (float)r;
- float z = x1 * exp(-(x1 * x1 + y1 * y1)) * 2.5f + sin(x2) * sin(y2);
+ float z = x1 * std::exp(-(x1 * x1 + y1 * y1)) * 2.5f + std::sin(x2) * std::sin(y2);
RGB color = interpolate_color(-1.6f, 1.6f, z);
(*input) (c, r).x = x1;
(*input) (c, r).y = y1;
class PCLCropHullTestFixture : public ::testing::Test
{
public:
- using CropHullTestTraits = typename std::tuple_element<0, TupleType>::type;
- using RandomGeneratorType = typename std::tuple_element<1, TupleType>::type;
+ using CropHullTestTraits = std::tuple_element_t<0, TupleType>;
+ using RandomGeneratorType = std::tuple_element_t<1, TupleType>;
PCLCropHullTestFixture()
{
std::tuple<CropHullTestTraits3d, RandomGenerator<456>>
>;
using CropHullTestTypes = ::testing::Types<
- std::tuple_element<0, CropHullTestTraits2dList>::type,
- std::tuple_element<1, CropHullTestTraits2dList>::type,
- std::tuple_element<2, CropHullTestTraits2dList>::type,
- std::tuple_element<0, CropHullTestTraits3dList>::type,
- std::tuple_element<1, CropHullTestTraits3dList>::type,
- std::tuple_element<2, CropHullTestTraits3dList>::type
+ std::tuple_element_t<0, CropHullTestTraits2dList>,
+ std::tuple_element_t<1, CropHullTestTraits2dList>,
+ std::tuple_element_t<2, CropHullTestTraits2dList>,
+ std::tuple_element_t<0, CropHullTestTraits3dList>,
+ std::tuple_element_t<1, CropHullTestTraits3dList>,
+ std::tuple_element_t<2, CropHullTestTraits3dList>
>;
TYPED_TEST_SUITE(PCLCropHullTestFixture, CropHullTestTypes);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// this test will pass only for 2d case //
-template <class T>
-struct PCLCropHullTestFixture2dCrutch : PCLCropHullTestFixture<T>
-{};
-using CropHullTestTraits2dTypes = ::testing::Types<
- std::tuple_element<0, CropHullTestTraits2dList>::type,
- std::tuple_element<1, CropHullTestTraits2dList>::type,
- std::tuple_element<2, CropHullTestTraits2dList>::type
- >;
-TYPED_TEST_SUITE(PCLCropHullTestFixture2dCrutch, CropHullTestTraits2dTypes);
-
-TYPED_TEST (PCLCropHullTestFixture2dCrutch, test_crop_inside)
+TYPED_TEST (PCLCropHullTestFixture, test_crop_inside)
{
for (auto & entry : this->data_)
{
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2020-, Open Perception, Inc.
+ *
+ * All rights reserved.
+ */
+
+#include <pcl/test/gtest.h>
+#include <pcl/point_cloud.h>
+#include <pcl/io/pcd_io.h>
+#include <pcl/point_types.h>
+#include <pcl/common/io.h>
+#include <pcl/filters/farthest_point_sampling.h>
+
+#include <cmath>
+#include <random>
+
+using namespace pcl;
+PointCloud<PointXYZ>::Ptr cloud_in (new PointCloud<PointXYZ>);
+const static int CLOUD_SIZE = 10;
+const static int SAMPLE_SIZE = CLOUD_SIZE -1;
+std::vector<float> x_values;
+
+TEST (FarthestPointSampling, farthest_point_sampling)
+{
+ PointCloud<PointXYZ> cloud_out;
+ FarthestPointSampling<PointXYZ> fps;
+ fps.setInputCloud(cloud_in);
+
+ //set a seed, and identify first sample point
+ std::random_device rd;
+ int random_seed = rd();
+ fps.setSeed(random_seed);
+ fps.setSample(1);
+ fps.filter(cloud_out);
+ float first_element = cloud_out.points[0].x;
+
+ //identify index of first element
+ std::vector<float>::iterator itr;
+ itr = std::find(x_values.begin(), x_values.end(), first_element);
+ int first_index = std::distance(x_values.begin(), itr);
+
+ //resample cloud with the same seed
+ fps.setSeed(random_seed);
+ fps.setSample(SAMPLE_SIZE);
+ fps.filter(cloud_out);
+
+ //check get methods
+ std::size_t sample_value = fps.getSample();
+ int seed_value = fps.getSeed();
+
+ //assert seed value and sample value and sample cloud size
+ EXPECT_EQ(seed_value, random_seed);
+ EXPECT_EQ(sample_value, SAMPLE_SIZE);
+ EXPECT_EQ (cloud_out.points.size(), SAMPLE_SIZE);
+
+ //check if each element is in the correct order
+ //by default, filtered indices should be sorted in order of distance
+ int point_index, expected_index;
+ for (int j = 1; j < SAMPLE_SIZE; j++)
+ {
+ itr = std::find(x_values.begin(), x_values.end(), cloud_out.points[j].x);
+ point_index = std::distance(x_values.begin(), itr);
+
+ if ((CLOUD_SIZE -j) == first_index)
+ expected_index = 0;
+ else
+ expected_index = CLOUD_SIZE - j;
+
+ EXPECT_EQ (point_index, expected_index);
+ }
+}
+
+int
+main (int argc, char** argv)
+{
+ // Fill in the cloud data
+ cloud_in->width = CLOUD_SIZE;
+ cloud_in->height = 1;
+ cloud_in->is_dense = false;
+ cloud_in->points.resize (cloud_in->width * cloud_in->height);
+
+ x_values.push_back(0);
+
+ for (std::size_t i = 1; i < CLOUD_SIZE; ++i)
+ {
+ x_values.push_back(std::pow(3,i-1));
+ cloud_in->points[i].x = x_values[i];
+ cloud_in->points[i].y = 0;
+ cloud_in->points[i].z = 0;
+ }
+
+ testing::InitGoogleTest (&argc, argv);
+ return (RUN_ALL_TESTS ());
+}
+
removed = fc.getRemovedIndices ();
EXPECT_EQ (removed->size (), input->size ());
+ // Should filter all points in the input cloud
+ fc.setNegative (false);
+ fc.setKeepOrganized (false);
+ fc.setRegionOfInterest (0.5f, 0.5f, 1.0f, 1.0f);
+ fc.filter (*output);
+ EXPECT_EQ (output->size (), input->size ());
+ removed = fc.getRemovedIndices ();
+ EXPECT_EQ (removed->size (), 0);
+ // Check invalid ROI values
+ EXPECT_THROW (fc.setRegionOfInterest (0.5f, 0.5f, 0.0f, 0.0f), PCLException);
+ EXPECT_THROW (fc.setRegionOfInterest (-0.4f, 0.0f, 8.2f, -1.3f), PCLException);
+
+ // Test on real point cloud, cut out milk cartoon in milk_cartoon_all_small_clorox.pcd
+ pcl::PointCloud <pcl::PointXYZ>::Ptr model (new pcl::PointCloud <pcl::PointXYZ>);
+ pcl::copyPointCloud (*cloud_organized, *model);
+
+ Eigen::Matrix4f cam2robot;
+ cam2robot << 0, 0, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1;
+ // Cut out object based on ROI
+ fc.setInputCloud (model);
+ fc.setNegative (false);
+ fc.setVerticalFOV (43);
+ fc.setHorizontalFOV (57);
+ fc.setNearPlaneDistance (0);
+ fc.setFarPlaneDistance (0.9);
+ fc.setRegionOfInterest (0.44f, 0.30f, 0.16f, 0.38f);
+ fc.setCameraPose (cam2robot);
+ fc.filter (*output);
+ // Should extract milk cartoon with 13541 points
+ EXPECT_EQ (output->size (), 13541);
+ removed = fc.getRemovedIndices ();
+ EXPECT_EQ (removed->size (), model->size () - output->size ());
+ // Cut out object based on field of view
+ fc.setRegionOfInterest (0.5f, 0.5f, 1.0f, 1.0f); // reset ROI
+ fc.setVerticalFOV (-22, 6);
+ fc.setHorizontalFOV (-22.5, -13.5);
+ fc.filter (*output);
+ // Should extract "all" laundry detergent with 10689 points
+ EXPECT_EQ (output->size (), 10689);
+ removed = fc.getRemovedIndices ();
+ EXPECT_EQ (removed->size (), model->size () - output->size ());
}
//////////////////////////////////////////////////////////////////////////////////////////////
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
float d_alpha = float(M_PI / angular_resolution);
for (unsigned idx = 0; idx < angular_resolution; ++idx)
{
- unsigned x_end = unsigned (length * std::cos (float(idx) * d_alpha) + center_x + 0.5);
- unsigned y_end = unsigned (length * std::sin (float(idx) * d_alpha) + center_y + 0.5);
+ auto x_end = unsigned (length * std::cos (float(idx) * d_alpha) + center_x + 0.5);
+ auto y_end = unsigned (length * std::sin (float(idx) * d_alpha) + center_y + 0.5);
// right
checkGeneralLine (center_x, center_y, x_end, y_end, cloud, true);
float d_alpha = float(2.0 * M_PI / angular_resolution);
for (unsigned idx = 0; idx < angular_resolution; ++idx)
{
- unsigned x_end = unsigned (length * std::cos (float(idx) * d_alpha) + center_x + 0.5);
- unsigned y_end = unsigned (length * std::sin (float(idx) * d_alpha) + center_y + 0.5);
+ auto x_end = unsigned (length * std::cos (float(idx) * d_alpha) + center_x + 0.5);
+ auto y_end = unsigned (length * std::sin (float(idx) * d_alpha) + center_y + 0.5);
// right
checkGeneralLine (center_x, center_y, x_end, y_end, cloud, false);
template <class ContainerT> bool
isCircularPermutation (const ContainerT& expected, const ContainerT& actual, const bool verbose = false)
{
- const unsigned int n = static_cast <unsigned int> (expected.size ());
+ const auto n = static_cast <unsigned int> (expected.size ());
EXPECT_EQ (n, actual.size ());
if (n != actual.size ())
{
template <class ContainerT> bool
isCircularPermutationVec (const std::vector <ContainerT> &expected, const std::vector <ContainerT> &actual, const bool verbose = false)
{
- const unsigned int n = static_cast<unsigned int> (expected.size ());
+ const auto n = static_cast<unsigned int> (expected.size ());
EXPECT_EQ (n, actual.size ());
if (n != actual.size ())
{
set(build TRUE)
set(REASON "")
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
#if !defined(REGISTER_TYPED_TEST_SUITE_P)
#define REGISTER_TYPED_TEST_SUITE_P REGISTER_TYPED_TEST_CASE_P
#endif
+
+/**
+ * \brief Macro choose between compile-time and run-time tests depending on the value of PCL_RUN_TESTS_AT_COMPILE_TIME
+ *
+ * \ingroup test
+ */
+#if PCL_RUN_TESTS_AT_COMPILE_TIME == true
+ #define PCL_CONSTEXPR constexpr
+ #define PCL_EXPECT_TRUE(...) \
+ static_assert(__VA_ARGS__, #__VA_ARGS__)
+ #define PCL_EXPECT_FLOAT_EQ(val1, val2) \
+ static_assert((val1) == (val2), "")
+ #define PCL_EXPECT_INT_EQ(val1, val2) \
+ static_assert((val1) == (val2), "")
+#else
+ #define PCL_CONSTEXPR
+ #define PCL_EXPECT_TRUE(...) \
+ EXPECT_TRUE(__VA_ARGS__) << (#__VA_ARGS__);
+ #define PCL_EXPECT_FLOAT_EQ(val1, val2) \
+ EXPECT_FLOAT_EQ((val1), (val2))
+ #define PCL_EXPECT_INT_EQ(val1, val2) \
+ EXPECT_EQ((val1), (val2))
+#endif
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
FILES test_io.cpp
LINK_WITH pcl_gtest pcl_io)
+PCL_ADD_TEST(io_split test_split
+ FILES test_split.cpp
+ LINK_WITH pcl_gtest pcl_io)
+
PCL_ADD_TEST(io_iterators test_iterators
FILES test_iterators.cpp
LINK_WITH pcl_gtest pcl_io)
fs.open ("all_types.pcd");
fs << "# .PCD v0.7 - Point Cloud Data file format\n"
"VERSION 0.7\n"
- "FIELDS a1 a2 a3 a4 a5 a6 a7 a8\n"
- "SIZE 1 1 2 2 4 4 4 8\n"
- "TYPE I U I U I U F F\n"
- "COUNT 1 2 1 2 1 2 1 2\n"
+ "FIELDS a1 a2 a3 a4 a5 a6 a7 a8 a9 a10\n"
+ "SIZE 1 1 2 2 4 4 4 8 8 8\n"
+ "TYPE I U I U I U F F I U\n"
+ "COUNT 1 2 1 2 1 2 1 2 1 2\n"
"WIDTH 1\n"
"HEIGHT 1\n"
"VIEWPOINT 0 0 0 1 0 0 0\n"
"POINTS 1\n"
"DATA ascii\n"
- "-50 250 251 -250 2500 2501 -250000 250000 250001 250.05 -250.05 -251.05";
+ "-50 250 251 -250 2500 2501 -250000 250000 250001 250.05 -250.05 -251.05 -5000000000 10000000000 10000000001";
fs.close ();
pcl::PCLPointCloud2 blob;
EXPECT_NE (res, -1);
EXPECT_EQ (blob.width, 1);
EXPECT_EQ (blob.height, 1);
- EXPECT_EQ (blob.data.size (), 1 + 1 * 2 + 2 * 1 + 2 * 2 + 4 * 1 + 4 * 2 + 4 * 1 + 8 * 2);
+ EXPECT_EQ (blob.data.size (), 1 * 1 + 1 * 2 + // {,u}int8_t
+ 2 * 1 + 2 * 2 + // {,u}in16_t
+ 4 * 1 + 4 * 2 + // {,u}int32_t
+ 4 * 1 + 8 * 2 + // f32, f64
+ 8 * 1 + 8 * 2); // {,u}int64_t
EXPECT_TRUE (blob.is_dense);
- EXPECT_EQ (blob.fields.size (), 8);
+ EXPECT_EQ (blob.fields.size (), 10);
// Check fields
EXPECT_EQ (blob.fields[0].name, "a1");
EXPECT_EQ (blob.fields[1].name, "a2");
EXPECT_EQ (blob.fields[5].name, "a6");
EXPECT_EQ (blob.fields[6].name, "a7");
EXPECT_EQ (blob.fields[7].name, "a8");
+ EXPECT_EQ (blob.fields[8].name, "a9");
+ EXPECT_EQ (blob.fields[9].name, "a10");
EXPECT_EQ (blob.fields[0].offset, 0);
- EXPECT_EQ (blob.fields[1].offset, 1);
- EXPECT_EQ (blob.fields[2].offset, 1 + 1 * 2);
- EXPECT_EQ (blob.fields[3].offset, 1 + 1 * 2 + 2 * 1);
- EXPECT_EQ (blob.fields[4].offset, 1 + 1 * 2 + 2 * 1 + 2 * 2);
- EXPECT_EQ (blob.fields[5].offset, 1 + 1 * 2 + 2 * 1 + 2 * 2 + 4 * 1);
- EXPECT_EQ (blob.fields[6].offset, 1 + 1 * 2 + 2 * 1 + 2 * 2 + 4 * 1 + 4 * 2);
- EXPECT_EQ (blob.fields[7].offset, 1 + 1 * 2 + 2 * 1 + 2 * 2 + 4 * 1 + 4 * 2 + 4 * 1);
+ EXPECT_EQ (blob.fields[1].offset, blob.fields[0].offset + 1); // 1 int8_t
+ EXPECT_EQ (blob.fields[2].offset, blob.fields[1].offset + 1 * 2); // 2 uint8_t
+ EXPECT_EQ (blob.fields[3].offset, blob.fields[2].offset + 2 * 1); // 1 int16_t
+ EXPECT_EQ (blob.fields[4].offset, blob.fields[3].offset + 2 * 2); // 2 uint16_t
+ EXPECT_EQ (blob.fields[5].offset, blob.fields[4].offset + 4 * 1); // 1 int32_t
+ EXPECT_EQ (blob.fields[6].offset, blob.fields[5].offset + 4 * 2); // 2 uint32_t
+ EXPECT_EQ (blob.fields[7].offset, blob.fields[6].offset + 4 * 1); // 1 float
+ EXPECT_EQ (blob.fields[8].offset, blob.fields[7].offset + 8 * 2); // 2 doubles
+ EXPECT_EQ (blob.fields[9].offset, blob.fields[8].offset + 8 * 1); // 1 int64_t
EXPECT_EQ (blob.fields[0].count, 1);
EXPECT_EQ (blob.fields[1].count, 2);
EXPECT_EQ (blob.fields[5].count, 2);
EXPECT_EQ (blob.fields[6].count, 1);
EXPECT_EQ (blob.fields[7].count, 2);
+ EXPECT_EQ (blob.fields[8].count, 1);
+ EXPECT_EQ (blob.fields[9].count, 2);
EXPECT_EQ (blob.fields[0].datatype, pcl::PCLPointField::INT8);
EXPECT_EQ (blob.fields[1].datatype, pcl::PCLPointField::UINT8);
EXPECT_EQ (blob.fields[5].datatype, pcl::PCLPointField::UINT32);
EXPECT_EQ (blob.fields[6].datatype, pcl::PCLPointField::FLOAT32);
EXPECT_EQ (blob.fields[7].datatype, pcl::PCLPointField::FLOAT64);
+ EXPECT_EQ (blob.fields[8].datatype, pcl::PCLPointField::INT64);
+ EXPECT_EQ (blob.fields[9].datatype, pcl::PCLPointField::UINT64);
std::int8_t b1;
std::uint8_t b2;
std::uint32_t b6;
float b7;
double b8;
+ std::int64_t b9;
+ std::uint64_t b10;
+
memcpy (&b1, &blob.data[blob.fields[0].offset], sizeof (std::int8_t));
EXPECT_FLOAT_EQ (b1, -50);
memcpy (&b2, &blob.data[blob.fields[1].offset], sizeof (std::uint8_t));
EXPECT_FLOAT_EQ (b2, 250);
memcpy (&b2, &blob.data[blob.fields[1].offset + sizeof (std::uint8_t)], sizeof (std::uint8_t));
EXPECT_FLOAT_EQ (b2, 251);
+
memcpy (&b3, &blob.data[blob.fields[2].offset], sizeof (std::int16_t));
EXPECT_FLOAT_EQ (b3, -250);
memcpy (&b4, &blob.data[blob.fields[3].offset], sizeof (std::uint16_t));
EXPECT_FLOAT_EQ (b4, 2500);
memcpy (&b4, &blob.data[blob.fields[3].offset + sizeof (std::uint16_t)], sizeof (std::uint16_t));
EXPECT_FLOAT_EQ (b4, 2501);
+
memcpy (&b5, &blob.data[blob.fields[4].offset], sizeof (std::int32_t));
EXPECT_FLOAT_EQ (float (b5), float (-250000));
memcpy (&b6, &blob.data[blob.fields[5].offset], sizeof (std::uint32_t));
EXPECT_FLOAT_EQ (float (b6), float (250000));
memcpy (&b6, &blob.data[blob.fields[5].offset + sizeof (std::uint32_t)], sizeof (std::uint32_t));
EXPECT_FLOAT_EQ (float (b6), float (250001));
+
memcpy (&b7, &blob.data[blob.fields[6].offset], sizeof (float));
EXPECT_FLOAT_EQ (b7, 250.05f);
memcpy (&b8, &blob.data[blob.fields[7].offset], sizeof (double));
memcpy (&b8, &blob.data[blob.fields[7].offset + sizeof (double)], sizeof (double));
EXPECT_FLOAT_EQ (float (b8), -251.05f);
+ memcpy (&b9, &blob.data[blob.fields[8].offset], sizeof (std::int64_t));
+ EXPECT_EQ (b9, -5000000000);
+ memcpy (&b10, &blob.data[blob.fields[9].offset], sizeof (std::uint64_t));
+ EXPECT_EQ (b10, 10000000000);
+ memcpy (&b10, &blob.data[blob.fields[9].offset + sizeof (std::uint64_t)], sizeof (std::uint64_t));
+ EXPECT_EQ (b10, 10000000001);
+
remove ("all_types.pcd");
}
EXPECT_EQ (bool (cloud_blob.is_dense), cloud.is_dense);
EXPECT_EQ (std::size_t (cloud_blob.data.size () * 2), // PointXYZI is 16*2 (XYZ+1, Intensity+3)
cloud_blob.width * cloud_blob.height * sizeof (PointXYZI)); // test for loadPCDFile ()
+ remove ("test_pcl_io.pcd");
// Convert from blob to data type
fromPCLPointCloud2 (cloud_blob, cloud);
EXPECT_FLOAT_EQ (cloud[nr_p - 1].z, last.z); // test for fromPCLPointCloud2 ()
EXPECT_FLOAT_EQ (cloud[nr_p - 1].intensity, last.intensity); // test for fromPCLPointCloud2 ()
- // Save as ASCII
+ // Save as binary
try
{
w.write<PointXYZI> ("test_pcl_io_binary.pcd", cloud, true);
pcl::Indices indices (cloud.width * cloud.height / 2);
for (int i = 0; i < static_cast<int> (indices.size ()); ++i) indices[i] = i;
- // Save as ASCII
+ // Save as binary
try
{
w.write<PointXYZI> ("test_pcl_io_binary.pcd", cloud, indices, true);
EXPECT_EQ (bool (cloud_blob.is_dense), cloud.is_dense);
EXPECT_EQ (std::size_t (cloud_blob.data.size () * 2), // PointXYZI is 16*2 (XYZ+1, Intensity+3)
cloud_blob.width * cloud_blob.height * sizeof (PointXYZI)); // test for loadPCDFile ()
+ remove ("test_pcl_io_binary.pcd");
// Convert from blob to data type
fromPCLPointCloud2 (cloud_blob, cloud);
EXPECT_TRUE (cloud_blob.is_dense);
EXPECT_EQ (std::size_t (cloud_blob.data.size () * 2), // PointXYZI is 16*2 (XYZ+1, Intensity+3)
cloud_blob.width * cloud_blob.height * sizeof (PointXYZI)); // test for loadPCDFile ()
+ remove ("test_pcl_io_ascii.pcd");
// Convert from blob to data type
fromPCLPointCloud2 (cloud_blob, cloud);
EXPECT_FLOAT_EQ (cloud[0].y, first.y); // test for fromPCLPointCloud2 ()
EXPECT_FLOAT_EQ (cloud[0].z, first.z); // test for fromPCLPointCloud2 ()
EXPECT_FLOAT_EQ (cloud[0].intensity, first.intensity); // test for fromPCLPointCloud2 ()
-
- remove ("test_pcl_io_ascii.pcd");
- remove ("test_pcl_io_binary.pcd");
- remove ("test_pcl_io.pcd");
}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+TEST (PCL, EmptyCloudToPCD)
+{
+ pcl::PointCloud<pcl::PointXYZ> cloud;
+ int res = pcl::io::savePCDFileASCII("ascii.pcd", cloud);
+ EXPECT_EQ (res, 0);
+ pcl::PointCloud<pcl::PointXYZ> cloud_in_ascii;
+ cloud_in_ascii.width = 10; // Make sure loadPCDFile overwrites this
+ cloud_in_ascii.height = 10; // Make sure loadPCDFile overwrites this
+ res = pcl::io::loadPCDFile("ascii.pcd", cloud_in_ascii);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ(cloud.width, cloud_in_ascii.width);
+ EXPECT_EQ(cloud.height, cloud_in_ascii.height);
+ remove ("ascii.pcd");
+
+ pcl::Indices indices;
+ res = pcl::io::savePCDFile("ascii_indices.pcd", cloud, indices);
+ EXPECT_EQ (0, res);
+ pcl::PointCloud<pcl::PointXYZ> cloud_in_indices;
+ cloud_in_indices.width = 10; // Make sure loadPCDFile overwrites this
+ res = pcl::io::loadPCDFile("ascii_indices.pcd", cloud_in_indices);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ(cloud.width, cloud_in_indices.width);
+ EXPECT_EQ(1, cloud_in_indices.height); // if we specify indices height must be 1
+ remove ("ascii_indices.pcd");
+
+ res = pcl::io::savePCDFileBinary("binary.pcd", cloud);
+ EXPECT_EQ (0, res);
+ pcl::PointCloud<pcl::PointXYZ> cloud_in_binary;
+ cloud_in_binary.width = 10; // Make sure loadPCDFile overwrites this
+ cloud_in_binary.height = 10; // Make sure loadPCDFile overwrites this
+ res = pcl::io::loadPCDFile("binary.pcd", cloud_in_binary);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ(cloud.width, cloud_in_binary.width);
+ EXPECT_EQ(cloud.height, cloud_in_binary.height);
+ remove ("binary.pcd");
+
+ res = pcl::io::savePCDFileBinaryCompressed("binary_compressed.pcd", cloud);
+ EXPECT_EQ (0, res);
+ pcl::PointCloud<pcl::PointXYZ> cloud_in_compressed;
+ cloud_in_compressed.width = 10; // Make sure loadPCDFile overwrites this
+ cloud_in_compressed.height = 10; // Make sure loadPCDFile overwrites this
+ res = pcl::io::loadPCDFile("binary_compressed.pcd", cloud_in_compressed);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ(cloud.width, cloud_in_compressed.width);
+ EXPECT_EQ(cloud.height, cloud_in_compressed.height);
+ remove ("binary_compressed.pcd");
+
+ // Data initialization for pcl::PCLPointCloud2 interface
+ pcl::PCLPointCloud2 cloud2;
+ pcl::PCLPointField x, y, z;
+ x.name = "x";
+ x.datatype = pcl::PCLPointField::FLOAT32;
+ y.name = "y";
+ y.datatype = pcl::PCLPointField::FLOAT32;
+ z.name = "z";
+ z.datatype = pcl::PCLPointField::FLOAT32;
+ cloud2.fields.push_back(x);
+ cloud2.fields.push_back(y);
+ cloud2.fields.push_back(z);
+ cloud2.is_dense = true;
+
+ res = pcl::io::savePCDFile ("ascii_pc2.pcd", cloud2,
+ Eigen::Vector4f::Zero (),
+ Eigen::Quaternionf::Identity ());
+ EXPECT_EQ (0, res);
+ pcl::PCLPointCloud2 cloud2_in_ascii;
+ cloud2_in_ascii.width = 10;
+ cloud2_in_ascii.height = 10;
+ res = loadPCDFile ("ascii_pc2.pcd", cloud2_in_ascii);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ (cloud2.width, cloud2_in_ascii.width);
+ EXPECT_EQ (cloud2.height, cloud2_in_ascii.height);
+ remove ("ascii_pc2.pcd");
+
+ res = pcl::io::savePCDFile ("binary_pc2.pcd", cloud2,
+ Eigen::Vector4f::Zero (),
+ Eigen::Quaternionf::Identity (),
+ true);
+ EXPECT_EQ (0, res);
+
+ pcl::PCLPointCloud2 cloud2_in_binary;
+ cloud2_in_binary.width = 10;
+ cloud2_in_binary.height = 10;
+ res = loadPCDFile ("binary_pc2.pcd", cloud2_in_binary);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ (cloud2.width, cloud2_in_binary.width);
+ EXPECT_EQ (cloud2.height, cloud2_in_binary.height);
+ remove ("binary_pc2.pcd");
+
+ PCDWriter w;
+ res = w.writeBinaryCompressed ("compressed_pc2.pcd", cloud2);
+ EXPECT_EQ (0, res);
+ pcl::PCLPointCloud2 cloud2_in_compressed;
+ cloud2_in_compressed.width = 10;
+ cloud2_in_compressed.height = 10;
+ res = loadPCDFile ("compressed_pc2.pcd", cloud2_in_compressed);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ (cloud2.width, cloud2_in_compressed.width);
+ EXPECT_EQ (cloud2.height, cloud2_in_compressed.height);
+ remove ("compressed_pc2.pcd");
+
+ // Test when WIDTH and HEIGHT are not defined
+ std::ofstream fs;
+ fs.open ("incomplete_ascii.pcd");
+ fs << "# .PCD v0.5 - Point Cloud Data file format\n"
+ "VERSION 0.5\n"
+ "FIELDS x y z intensity\n"
+ "SIZE 4 4 4 4\n"
+ "TYPE F F F F\n"
+ "COUNT 1 1 1 1\n"
+ "POINTS 2\n"
+ "DATA ascii\n"
+ "1 2 3 4\n"
+ "5 6 7 8";
+ fs.close ();
+ pcl::PCLPointCloud2 incomplete_cloud2_in;
+ res = loadPCDFile ("incomplete_ascii.pcd", incomplete_cloud2_in);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ (2, incomplete_cloud2_in.width);
+ EXPECT_EQ (1, incomplete_cloud2_in.height);
+ EXPECT_EQ (true, bool (incomplete_cloud2_in.is_dense));
+ EXPECT_EQ (2 * 4 * 4, std::size_t (incomplete_cloud2_in.data.size ()));
+ remove ("incomplete_ascii.pcd");
+
+ // Test when HEIGHT are not defined
+ fs.open ("incomplete_height_ascii.pcd");
+ fs << "# .PCD v0.7 - Point Cloud Data file format\n"
+ "VERSION 0.7\n"
+ "FIELDS x y z intensity\n"
+ "SIZE 4 4 4 4\n"
+ "TYPE F F F F\n"
+ "COUNT 1 1 1 1\n"
+ "WIDTH 2\n"
+ "POINTS 2\n"
+ "DATA ascii\n"
+ "1 2 3 4\n"
+ "5 6 7 8";
+ fs.close ();
+ pcl::PCLPointCloud2 incomplete_height_cloud2_in;
+ res = loadPCDFile ("incomplete_height_ascii.pcd", incomplete_height_cloud2_in);
+ EXPECT_EQ (0, res);
+ EXPECT_EQ (2, incomplete_height_cloud2_in.width);
+ EXPECT_EQ (1, incomplete_height_cloud2_in.height);
+ EXPECT_EQ (true, bool (incomplete_height_cloud2_in.is_dense));
+ EXPECT_EQ (2 * 4 * 4, std::size_t (incomplete_height_cloud2_in.data.size ()));
+ remove ("incomplete_height_ascii.pcd");
+
+ // Test invalid height
+ fs.open ("invalid_height_ascii.pcd");
+ fs << "# .PCD v0.7 - Point Cloud Data file format\n"
+ "VERSION 0.7\n"
+ "FIELDS x y z intensity\n"
+ "SIZE 4 4 4 4\n"
+ "TYPE F F F F\n"
+ "COUNT 1 1 1 1\n"
+ "WIDTH 2\n"
+ "HEIGHT a\n"
+ "POINTS 2\n"
+ "DATA ascii\n"
+ "1 2 3 4\n"
+ "5 6 7 8";
+ fs.close ();
+ pcl::PCLPointCloud2 invalid_height_cloud2_in;
+ res = loadPCDFile ("invalid_height_ascii.pcd", invalid_height_cloud2_in);
+ EXPECT_EQ (-1, res);
+ remove ("invalid_height_ascii.pcd");
+
+ // Test for no field data
+ pcl::PCLPointCloud2 empty_cloud;
+ res = pcl::io::savePCDFile ("empty_cloud_ascii.pcd", empty_cloud,
+ Eigen::Vector4f::Zero (),
+ Eigen::Quaternionf::Identity ());
+ EXPECT_EQ (-1, res);
+ remove ("empty_cloud_ascii.pcd");
+
+ res = pcl::io::savePCDFile ("empty_cloud_binary.pcd", empty_cloud,
+ Eigen::Vector4f::Zero (),
+ Eigen::Quaternionf::Identity (),
+ true);
+ EXPECT_EQ (-1, res);
+ remove ("empty_cloud_binary.pcd");
+
+ EXPECT_THROW(w.writeBinaryCompressed ("empty_cloud_compressed.pcd", empty_cloud),
+ pcl::IOException);
+ remove ("empty_cloud_compressed.pcd");
+}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (PCL, PCDReaderWriter)
{
EXPECT_EQ (blob2.height, blob.height);
EXPECT_EQ (data_type, 2); // since it was written by writeBinaryCompressed(), it should be compressed.
- const unsigned char *data = reinterpret_cast<const unsigned char *> (pcd_str.data ());
+ const auto *data = reinterpret_cast<const unsigned char *> (pcd_str.data ());
res = reader.readBodyBinary (data, blob2, pcd_version, data_type == 2, data_idx);
PointCloud<PointXYZRGBNormal> cloud2;
pcl::fromPCLPointCloud2 (blob2, cloud2);
{
PCL_WARN ("Failed to set locale, skipping test.\n");
}
- int res = writer.writeASCII<PointXYZ> ("test_pcl_io_ascii.pcd", cloud);
+ int res = writer.writeASCII<PointXYZ> ("test_pcl_io_ascii_locale.pcd", cloud);
EXPECT_EQ (res, 0);
PCDReader reader;
{
PCL_WARN ("Failed to set locale, skipping test.\n");
}
- reader.read<PointXYZ> ("test_pcl_io_ascii.pcd", cloud2);
+ reader.read<PointXYZ> ("test_pcl_io_ascii_locale.pcd", cloud2);
std::locale::global (std::locale::classic ());
EXPECT_EQ (cloud2.width, cloud.width);
{
}
- remove ("test_pcl_io_ascii.pcd");
+ remove ("test_pcl_io_ascii_locale.pcd");
#endif
}
{
Point mean (0,0,0);
- for (PointCloud::iterator it = cloud.begin(); it != cloud.end(); ++it)
+ for (auto it = cloud.begin(); it != cloud.end(); ++it)
{
for (int i=0;i<3;i++) mean.data[i] += it->data[i];
}
#include <pcl/test/gtest.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
-#include <pcl/octree/octree.h>
#include <pcl/io/pcd_io.h>
#include <pcl/compression/octree_pointcloud_compression.h>
#include <pcl/compression/compression_profiles.h>
TYPED_TEST (OctreeDeCompressionTest, RandomClouds)
{
- srand(static_cast<unsigned int> (time(NULL)));
+ srand(static_cast<unsigned int> (time(nullptr)));
for (const double MAX_XYZ : {1.0, 1024.0}) { // Small clouds, large clouds
// iterate over all pre-defined compression profiles
for (int compression_profile = pcl::io::LOW_RES_ONLINE_COMPRESSION_WITHOUT_COLOR;
// Generate a random cloud. Put it into the encoder several times and make
// sure that the decoded cloud has correct width and height each time.
const double MAX_XYZ = 1.0;
- srand(static_cast<unsigned int> (time(NULL)));
+ srand(static_cast<unsigned int> (time(nullptr)));
// iterate over all pre-defined compression profiles
for (int compression_profile = pcl::io::LOW_RES_ONLINE_COMPRESSION_WITHOUT_COLOR;
compression_profile != pcl::io::COMPRESSION_PROFILE_COUNT; ++compression_profile) {
pcl::PointCloud<pcl::PointXYZRGB>::Ptr input_cloud_ptr (new pcl::PointCloud<pcl::PointXYZRGB>);
// load point cloud from file, when present
- if (pcd_file == NULL) return;
+ if (pcd_file == nullptr) return;
int rv = pcl::io::loadPCDFile(pcd_file, *input_cloud_ptr);
float voxel_sizes[] = { 0.1, 0.01 };
{}
- ~PLYTest () { remove (mesh_file_ply_.c_str ()); }
+ ~PLYTest () override { remove (mesh_file_ply_.c_str ()); }
std::string mesh_file_ply_;
};
remove ("test_mesh_rgba_binary.ply");
}
+TEST (PCL, PLYPolygonMeshSpecificFieldOrder)
+{ // test a specific order of xyz, rgba, and normal fields
+ pcl::PolygonMesh mesh;
+ auto add_field = [](std::vector<pcl::PCLPointField>& fields, const std::string& name, const pcl::uindex_t offset, const std::uint8_t datatype)
+ { fields.emplace_back(); fields.back().name = name; fields.back().offset = offset; fields.back().datatype = datatype; fields.back().count = 1; };
+ add_field(mesh.cloud.fields, "x", 0, pcl::PCLPointField::PointFieldTypes::FLOAT32);
+ add_field(mesh.cloud.fields, "y", 4, pcl::PCLPointField::PointFieldTypes::FLOAT32);
+ add_field(mesh.cloud.fields, "z", 8, pcl::PCLPointField::PointFieldTypes::FLOAT32);
+ add_field(mesh.cloud.fields, "normal_x", 12, pcl::PCLPointField::PointFieldTypes::FLOAT32);
+ add_field(mesh.cloud.fields, "normal_y", 16, pcl::PCLPointField::PointFieldTypes::FLOAT32);
+ add_field(mesh.cloud.fields, "normal_z", 20, pcl::PCLPointField::PointFieldTypes::FLOAT32);
+ add_field(mesh.cloud.fields, "rgba", 24, pcl::PCLPointField::PointFieldTypes::UINT32);
+ mesh.cloud.height = mesh.cloud.width = 1;
+ mesh.cloud.data.resize(28);
+ const float x = 0.0, y = 1.0, z = 2.0, normal_x = 1.0, normal_y = 0.0, normal_z = 0.0;
+ const std::uint32_t rgba = 0x326496;
+ memcpy(&mesh.cloud.data[0], &x, sizeof(float));
+ memcpy(&mesh.cloud.data[4], &y, sizeof(float));
+ memcpy(&mesh.cloud.data[8], &z, sizeof(float));
+ memcpy(&mesh.cloud.data[12], &normal_x, sizeof(float));
+ memcpy(&mesh.cloud.data[16], &normal_y, sizeof(float));
+ memcpy(&mesh.cloud.data[20], &normal_z, sizeof(float));
+ memcpy(&mesh.cloud.data[24], &rgba, sizeof(std::uint32_t));
+
+ pcl::io::savePLYFileBinary("test_mesh_xyzrgbnormal_binary.ply", mesh);
+ pcl::PolygonMesh mesh_in_binary;
+ pcl::io::loadPLYFile("test_mesh_xyzrgbnormal_binary.ply", mesh_in_binary);
+ ASSERT_EQ (mesh.cloud.data.size(), mesh_in_binary.cloud.data.size());
+ for(std::size_t i=0; i<mesh.cloud.data.size(); ++i) {
+ EXPECT_EQ (mesh.cloud.data[i], mesh_in_binary.cloud.data[i]);
+ }
+ remove ("test_mesh_xyzrgbnormal_binary.ply");
+
+ pcl::io::savePLYFile("test_mesh_xyzrgbnormal_ascii.ply", mesh);
+ pcl::PolygonMesh mesh_in_ascii;
+ pcl::io::loadPLYFile("test_mesh_xyzrgbnormal_ascii.ply", mesh_in_ascii);
+ ASSERT_EQ (mesh.cloud.data.size(), mesh_in_ascii.cloud.data.size());
+ for(std::size_t i=0; i<mesh.cloud.data.size(); ++i) {
+ EXPECT_EQ (mesh.cloud.data[i], mesh_in_ascii.cloud.data[i]);
+ }
+ remove ("test_mesh_xyzrgbnormal_ascii.ply");
+}
TEST (PCL, PLYPolygonMeshUintIndices)
{
pcie.setColorMode (pcie.COLORS_MONO);
ASSERT_TRUE (pcie.extract (cloud, image));
- unsigned short* data = reinterpret_cast<unsigned short*> (&image.data[0]);
+ auto* data = reinterpret_cast<unsigned short*> (&image.data[0]);
EXPECT_EQ ("mono16", image.encoding);
EXPECT_EQ (cloud.width, image.width);
PointCloudImageExtractorFromZField<PointT> pcie;
ASSERT_TRUE (pcie.extract (cloud, image));
- unsigned short* data = reinterpret_cast<unsigned short*> (&image.data[0]);
+ auto* data = reinterpret_cast<unsigned short*> (&image.data[0]);
EXPECT_EQ ("mono16", image.encoding);
EXPECT_EQ (cloud.width, image.width);
PointCloudImageExtractorFromCurvatureField<PointT> pcie;
ASSERT_TRUE (pcie.extract (cloud, image));
- unsigned short* data = reinterpret_cast<unsigned short*> (&image.data[0]);
+ auto* data = reinterpret_cast<unsigned short*> (&image.data[0]);
EXPECT_EQ ("mono16", image.encoding);
EXPECT_EQ (cloud.width, image.width);
PointCloudImageExtractorFromIntensityField<PointT> pcie;
ASSERT_TRUE (pcie.extract (cloud, image));
- unsigned short* data = reinterpret_cast<unsigned short*> (&image.data[0]);
+ auto* data = reinterpret_cast<unsigned short*> (&image.data[0]);
EXPECT_EQ ("mono16", image.encoding);
EXPECT_EQ (cloud.width, image.width);
ASSERT_TRUE (pcie.extract (cloud, image));
{
- unsigned short* data = reinterpret_cast<unsigned short*> (&image.data[0]);
+ auto* data = reinterpret_cast<unsigned short*> (&image.data[0]);
EXPECT_EQ (std::numeric_limits<unsigned short>::max (), data[3]);
}
ASSERT_TRUE (pcie.extract (cloud, image));
{
- unsigned short* data = reinterpret_cast<unsigned short*> (&image.data[0]);
+ auto* data = reinterpret_cast<unsigned short*> (&image.data[0]);
EXPECT_EQ (0, data[3]);
}
}
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Point Cloud Library (PCL) - www.pointclouds.org
+ * Copyright (c) 2014-, Open Perception Inc.
+ *
+ * All rights reserved
+ */
+
+#include <pcl/io/split.h>
+#include <pcl/test/gtest.h>
+
+#include <vector>
+
+TEST(PCL, TestIdentitySplit)
+{
+ std::vector<std::string> tokens;
+
+ // identity test, empty string as input
+ pcl::split(tokens, "", " \r\t");
+ EXPECT_EQ(tokens, std::vector<std::string>());
+}
+
+TEST(PCL, TestNonEmptyDelimitersSplit)
+{
+ std::vector<std::string> tokens;
+
+ // test non-empty string with just the delimiters
+ pcl::split(tokens, "\r\t ", " \r\t");
+ EXPECT_EQ(tokens, std::vector<std::string>());
+}
+
+TEST(PCL, TestTokenWithoutDelimitersSplit)
+{
+ std::vector<std::string> tokens;
+
+ // test a string without delimiters
+ pcl::split(tokens, "abcd", " \r\t");
+ EXPECT_EQ(tokens, std::vector<std::string>{"abcd"});
+}
+
+TEST(PCL, TestSimpleSplit1)
+{
+ std::vector<std::string> tokens;
+ const auto output = std::vector<std::string>{
+ "aabb", "ccdd", "eeff", "gghh", "iijj", "kkll", "mmnn", "oopp"};
+
+ // test simple combination of all the delimiters
+ const std::string input_1 = "aabb ccdd\reeff\tgghh \riijj \tkkll\r\tmmnn \r\toopp";
+ pcl::split(tokens, input_1, " \r\t");
+ EXPECT_EQ(tokens, output);
+}
+
+TEST(PCL, TestSimpleSplit2)
+{
+ std::vector<std::string> tokens;
+ const auto output = std::vector<std::string>{
+ "aabb", "ccdd", "eeff", "gghh", "iijj", "kkll", "mmnn", "oopp"};
+
+ // same as input_1 but we have whitespaces in the front and in the back
+ const std::string input_2 =
+ " aabb ccdd\reeff\tgghh \riijj \tkkll\r\tmmnn \r\toopp ";
+ pcl::split(tokens, input_2, " \r\t");
+ EXPECT_EQ(tokens, output);
+}
+
+TEST(PCL, TestSimpleSplit3)
+{
+ std::vector<std::string> tokens;
+ const auto output = std::vector<std::string>{
+ "aabb", "ccdd", "eeff", "gghh", "iijj", "kkll", "mmnn", "oopp"};
+
+ // same as input_2 but we have some double delimiters
+ const std::string input_3 =
+ " aabb ccdd\r\reeff\t\tgghh \r\r\riijj \t\tkkll\r\t\tmmnn \r\r\toopp ";
+ pcl::split(tokens, input_3, " \r\t");
+ EXPECT_EQ(tokens, output);
+}
+
+/* ---[ */
+int
+main(int argc, char** argv)
+{
+ testing::InitGoogleTest(&argc, argv);
+ return (RUN_ALL_TESTS());
+}
+/* ]--- */
class TimGrabberTest : public ::testing::Test {
protected:
TimGrabberTest () = default;
- ~TimGrabberTest () override {}
+ ~TimGrabberTest () override = default;
std::vector<std::string> packets_;
std::vector<CloudT> correct_clouds_;
TestableTimGrabber grabber_;
- virtual void SetUp () override {
+ 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;
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT (build AND BUILD_io))
return()
for (const auto &k_index : k_indices)
{
- std::set<int>::iterator brute_force_result_it = brute_force_result.find (k_index);
+ auto brute_force_result_it = brute_force_result.find (k_index);
bool ok = brute_force_result_it != brute_force_result.end ();
//if (!ok) std::cerr << k_indices[i] << " is not correct...\n";
//else std::cerr << k_indices[i] << " is correct...\n";
}
float max_dist = 0.0f;
unsigned int counter = 0;
- for (std::multimap<float, int>::iterator it = sorted_brute_force_result.begin (); it != sorted_brute_force_result.end () && counter < no_of_neighbors; ++it)
+ for (auto it = sorted_brute_force_result.begin (); it != sorted_brute_force_result.end () && counter < no_of_neighbors; ++it)
{
max_dist = std::max (max_dist, it->first);
++counter;
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT (build AND BUILD_io))
return()
std::vector<float> scales (nr_scales_per_octave + 3);
for (int i_scale = 0; i_scale <= nr_scales_per_octave + 2; ++i_scale)
{
- scales[i_scale] = base_scale * pow (2.0f, static_cast<float> (i_scale-1) / nr_scales_per_octave);
+ scales[i_scale] = base_scale * std::pow (2.0f, static_cast<float> (i_scale-1) / nr_scales_per_octave);
}
Eigen::MatrixXf diff_of_gauss;
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
// add data to leaf node voxel
int* voxel_container = octreeA.createLeaf(voxels[i].x, voxels[i].y, voxels[i].z);
- data[i] = *voxel_container;
+ *voxel_container = data[i];
}
std::priority_queue<prioPointQueueEntry, pcl::PointCloud<prioPointQueueEntry>::VectorType> pointCandidates;
- // create octree
- OctreePointCloudSearch<PointXYZ> octree (0.1);
- octree.setInputCloud (cloudIn);
-
Indices k_indices;
std::vector<float> k_sqr_distances;
std::vector<float> k_sqr_distances_bruteforce;
for (const std::size_t maxObjsPerLeaf: {0, 5}) {
+ // create octree
+ OctreePointCloudSearch<PointXYZ> octree (0.1);
+ octree.setInputCloud (cloudIn);
+
if (maxObjsPerLeaf != 0)
octree.enableDynamicDepth (maxObjsPerLeaf);
for (unsigned int test_id = 0; test_id < test_runs; test_id++)
pointCandidates.pop ();
// copy results into vectors
- unsigned idx = static_cast<unsigned> (pointCandidates.size ());
+ auto idx = static_cast<unsigned> (pointCandidates.size ());
k_indices_bruteforce.resize (idx);
k_sqr_distances_bruteforce.resize (idx);
while (!pointCandidates.empty ())
srand (static_cast<unsigned int> (time (nullptr)));
- // create octree
- OctreePointCloudSearch<PointXYZ> octree (1);
- octree.setInputCloud (cloudIn);
-
for (const std::size_t maxObjsPerLeaf: {0, 5}) {
+ // create octree
+ OctreePointCloudSearch<PointXYZ> octree (1);
+ octree.setInputCloud (cloudIn);
+
if (maxObjsPerLeaf != 0)
octree.enableDynamicDepth (maxObjsPerLeaf);
for (unsigned int test_id = 0; test_id < test_runs; test_id++)
std::vector<int> cloudSearchBruteforce;
for (std::size_t i = 0; i < cloudIn->size (); i++)
{
- pointDist = sqrt (
+ pointDist = std::sqrt (
((*cloudIn)[i].x - searchPoint.x) * ((*cloudIn)[i].x - searchPoint.x)
+ ((*cloudIn)[i].y - searchPoint.y) * ((*cloudIn)[i].y - searchPoint.y)
+ ((*cloudIn)[i].z - searchPoint.z) * ((*cloudIn)[i].z - searchPoint.z));
auto current = cloudNWRSearch.cbegin ();
while (current != cloudNWRSearch.cend ())
{
- pointDist = sqrt (
+ pointDist = std::sqrt (
((*cloudIn)[*current].x - searchPoint.x) * ((*cloudIn)[*current].x - searchPoint.x)
+ ((*cloudIn)[*current].y - searchPoint.y) * ((*cloudIn)[*current].y - searchPoint.y)
+ ((*cloudIn)[*current].z - searchPoint.z) * ((*cloudIn)[*current].z - searchPoint.z));
OctreeBaseT octree_;
};
-TEST_F (OctreeIteratorBaseTest, CopyConstructor)
-{
- OctreeIteratorBaseT it_a;
- OctreeIteratorBaseT it_b (&octree_, 0);
- OctreeIteratorBaseT it_c (it_b); //Our copy constructor
-
- EXPECT_NE (it_a, it_c);
- EXPECT_EQ (it_b, it_c);
-}
-
-TEST_F (OctreeIteratorBaseTest, CopyAssignment)
-{
- OctreeIteratorBaseT it_a;
- OctreeIteratorBaseT it_b (&octree_, 0);
- OctreeIteratorBaseT it_c;
-
- EXPECT_EQ (it_a, it_c);
- EXPECT_NE (it_b, it_c);
-
- it_c = it_a; //Our copy assignment
- EXPECT_EQ (it_a, it_c);
- EXPECT_NE (it_b, it_c);
-
- it_c = it_b; //Our copy assignment
- EXPECT_NE (it_a, it_c);
- EXPECT_EQ (it_b, it_c);
-}
-
////////////////////////////////////////////////////////
// Iterator fixture setup
////////////////////////////////////////////////////////
// Members
OctreeT oct_a_, oct_b_;
+ const OctreeT const_oct_a_, const_oct_b_;
};
TEST_F (OctreeBaseBeginEndIteratorsTest, Begin)
EXPECT_EQ (it_a_post, it_a_end);
}
+TEST_F (OctreeBaseIteratorsPrePostTest, ConstDefaultIterator)
+{
+ // Useful types
+ using ConstIteratorT = OctreeT::ConstIterator;
+
+ // Default initialization
+ ConstIteratorT it_a_pre;
+ ConstIteratorT it_a_post;
+ ConstIteratorT it_a_end = const_oct_a_.end ();
+
+ // Iterate over every node of the octree const_oct_a_.
+ for (it_a_pre = const_oct_a_.begin (), it_a_post = const_oct_a_.begin ();
+ ((it_a_pre != it_a_end) && (it_a_post != it_a_end)); )
+ {
+ EXPECT_EQ (it_a_pre, it_a_post++);
+ EXPECT_EQ (++it_a_pre, it_a_post);
+ }
+
+ EXPECT_EQ (it_a_pre, it_a_end);
+ EXPECT_EQ (it_a_post, it_a_end);
+}
+
+TEST_F (OctreeBaseIteratorsPrePostTest, ConstLeafNodeDepthFirstIterator)
+{
+ // Useful types
+ using ConstIteratorT = OctreeT::ConstLeafNodeDepthFirstIterator;
+
+ // Default initialization
+ ConstIteratorT it_a_pre;
+ ConstIteratorT it_a_post;
+ ConstIteratorT it_a_end = const_oct_a_.leaf_depth_end ();
+
+ // Iterate over every node of the octree const_oct_a_.
+ for (it_a_pre = const_oct_a_.leaf_depth_begin (), it_a_post = const_oct_a_.leaf_depth_begin ();
+ ((it_a_pre != it_a_end) && (it_a_post != it_a_end)); )
+ {
+ EXPECT_EQ (it_a_pre, it_a_post++);
+ EXPECT_EQ (++it_a_pre, it_a_post);
+ }
+
+ EXPECT_EQ (it_a_pre, it_a_end);
+ EXPECT_EQ (it_a_post, it_a_end);
+}
+
+TEST_F (OctreeBaseIteratorsPrePostTest, ConstDepthFirstIterator)
+{
+ // Useful types
+ using ConstIteratorT = OctreeT::ConstDepthFirstIterator;
+
+ // Default initialization
+ ConstIteratorT it_a_pre;
+ ConstIteratorT it_a_post;
+ ConstIteratorT it_a_end = const_oct_a_.depth_end ();
+
+ // Iterate over every node of the octree const_oct_a_.
+ for (it_a_pre = const_oct_a_.depth_begin (), it_a_post = const_oct_a_.depth_begin ();
+ ((it_a_pre != it_a_end) && (it_a_post != it_a_end)); )
+ {
+ EXPECT_EQ (it_a_pre, it_a_post++);
+ EXPECT_EQ (++it_a_pre, it_a_post);
+ }
+
+ EXPECT_EQ (it_a_pre, it_a_end);
+ EXPECT_EQ (it_a_post, it_a_end);
+}
+
+TEST_F (OctreeBaseIteratorsPrePostTest, ConstBreadthFirstIterator)
+{
+ // Useful types
+ using ConstIteratorT = OctreeT::ConstBreadthFirstIterator;
+
+ // Default initialization
+ ConstIteratorT it_a_pre;
+ ConstIteratorT it_a_post;
+ ConstIteratorT it_a_end = const_oct_a_.breadth_end ();
+
+ // Iterate over every node of the octree const_oct_a_.
+ for (it_a_pre = const_oct_a_.breadth_begin (), it_a_post = const_oct_a_.breadth_begin ();
+ ((it_a_pre != it_a_end) && (it_a_post != it_a_end)); )
+ {
+ EXPECT_EQ (it_a_pre, it_a_post++);
+ EXPECT_EQ (++it_a_pre, it_a_post);
+ }
+
+ EXPECT_EQ (it_a_pre, it_a_end);
+ EXPECT_EQ (it_a_post, it_a_end);
+}
+
+TEST_F (OctreeBaseIteratorsPrePostTest, ConstFixedDepthIterator)
+{
+ // Useful types
+ using ConstIteratorT = OctreeT::ConstFixedDepthIterator;
+
+ // Default initialization
+ ConstIteratorT it_a_pre;
+ ConstIteratorT it_a_post;
+ ConstIteratorT it_a_end = const_oct_a_.fixed_depth_end ();
+
+ for (unsigned int depth = 0; depth <= const_oct_a_.getTreeDepth (); ++depth)
+ {
+ auto it_a_pre = const_oct_a_.fixed_depth_begin (depth);
+ auto it_a_post = const_oct_a_.fixed_depth_begin (depth);
+
+
+ // Iterate over every node at a given depth of the octree const_oct_a_.
+ for (it_a_pre = const_oct_a_.fixed_depth_begin (depth), it_a_post = const_oct_a_.fixed_depth_begin (depth);
+ ((it_a_pre != it_a_end) && (it_a_post != it_a_end)); )
+ {
+ EXPECT_EQ (it_a_pre, it_a_post++);
+ EXPECT_EQ (++it_a_pre, it_a_post);
+ }
+
+ EXPECT_EQ (it_a_pre, it_a_end);
+ EXPECT_EQ (it_a_post, it_a_end);
+ }
+}
+
+TEST_F (OctreeBaseIteratorsPrePostTest, ConstLeafNodeBreadthFirstIterator)
+{
+ // Useful types
+ using ConstIteratorT = OctreeT::ConstLeafNodeBreadthFirstIterator;
+
+ // Default initialization
+ ConstIteratorT it_a_pre;
+ ConstIteratorT it_a_post;
+ ConstIteratorT it_a_end = const_oct_a_.leaf_breadth_end ();
+
+ // Iterate over every node of the octree const_oct_a_.
+ for (it_a_pre = const_oct_a_.leaf_breadth_begin (), it_a_post = const_oct_a_.leaf_breadth_begin ();
+ ((it_a_pre != it_a_end) && (it_a_post != it_a_end)); )
+ {
+ EXPECT_EQ (it_a_pre, it_a_post++);
+ EXPECT_EQ (++it_a_pre, it_a_post);
+ }
+
+ EXPECT_EQ (it_a_pre, it_a_end);
+ EXPECT_EQ (it_a_post, it_a_end);
+}
+
////////////////////////////////////////////////////////
// OctreePointCloudAdjacency Begin/End Iterator Construction
////////////////////////////////////////////////////////
std::srand (42);
// Fill the point cloud
- for (std::vector<std::pair<Eigen::Vector3f, Eigen::Vector3f> >::const_iterator it = voxels.begin ();
- it != voxels.end ();
- ++it)
+ for (const auto& voxel : voxels)
{
const static float eps = std::numeric_limits<float>::epsilon ();
- double x_min = it->first.x () + eps;
- double y_min = it->first.y () + eps;
- double z_min = it->first.z () + eps;
- double x_max = it->second.x () - eps;
- double y_max = it->second.y () - eps;
- double z_max = it->second.z () - eps;
+ double x_min = voxel.first.x () + eps;
+ double y_min = voxel.first.y () + eps;
+ double z_min = voxel.first.z () + eps;
+ double x_max = voxel.second.x () - eps;
+ double y_max = voxel.second.y () - eps;
+ double z_max = voxel.second.z () - eps;
for (unsigned int i = 0; i < nb_pt_in_voxel; ++i)
{
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
clusterer.setInputCloud (model_downsampled_);
clusterer.setSceneCloud (scene_downsampled_);
clusterer.setModelSceneCorrespondences (model_scene_corrs_);
- clusterer.setGCSize (0.015);
+ clusterer.setGCSize (0.001);
clusterer.setGCThreshold (25);
EXPECT_TRUE (clusterer.recognize (rototranslations));
//Assertions
EXPECT_EQ (rototranslations.size (), 1);
- EXPECT_LT (computeRmsE (model_, scene_, rototranslations[0]), 1E-4);
+ EXPECT_LT (computeRmsE (model_, scene_, rototranslations[0]), 1E-4) << std::endl << rototranslations[0] << std::endl << model_downsampled_->size() << std::endl << scene_downsampled_->size() << std::endl << model_scene_corrs_->size() << std::endl;
}
return (-1);
}
- training_cloud = (new pcl::PointCloud<pcl::PointXYZ>)->makeShared();
+ training_cloud.reset (new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile (argv[1], *training_cloud) < 0)
{
std::cerr << "Failed to read test file. Please download `ism_train.pcd` and pass its path to the test." << std::endl;
return (-1);
}
- testing_cloud = (new pcl::PointCloud<pcl::PointXYZ>)->makeShared();
+ testing_cloud.reset (new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile (argv[2], *testing_cloud) < 0)
{
std::cerr << "Failed to read test file. Please download `ism_test.pcd` and pass its path to the test." << std::endl;
return (-1);
}
- training_normals = (new pcl::PointCloud<pcl::Normal>)->makeShared();
- testing_normals = (new pcl::PointCloud<pcl::Normal>)->makeShared();
+ training_normals.reset (new pcl::PointCloud<pcl::Normal>);
+ testing_normals.reset (new pcl::PointCloud<pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
normal_estimator.setRadiusSearch (25.0);
normal_estimator.setInputCloud(training_cloud);
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
#include <pcl/registration/correspondence_rejection_median_distance.h>
#include <pcl/registration/correspondence_rejection_poly.h>
-pcl::PointCloud<pcl::PointXYZ> cloud;
+pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (CorrespondenceRejectors, CorrespondenceRejectionMedianDistance)
TEST (CorrespondenceRejectors, CorrespondenceRejectionPoly)
{
// Size of point cloud
- const int size = static_cast<int> (cloud.size ());
+ const int size = static_cast<int> (cloud->size ());
// Ground truth correspondences
pcl::Correspondences corr (size);
corr[i].index_match += inc;
// Transform the target
- pcl::PointCloud<pcl::PointXYZ> target;
+ pcl::PointCloud<pcl::PointXYZ>::Ptr target(new pcl::PointCloud<pcl::PointXYZ>);
Eigen::Vector3f t(0.1f, 0.2f, 0.3f);
Eigen::Quaternionf q (float (std::cos (0.5*M_PI_4)), 0.0f, 0.0f, float (std::sin (0.5*M_PI_4)));
- pcl::transformPointCloud (cloud, target, t, q);
+ pcl::transformPointCloud (*cloud, *target, t, q);
// Noisify the target with a known seed and N(0, 0.005) using deterministic sampling
pcl::common::NormalGenerator<float> nd(0, 0.005, 1e6);
- for (auto &point : target)
+ for (auto &point : *target)
{
point.x += nd.run();
point.y += nd.run();
point.z += nd.run();
}
- // Ensure deterministic sampling inside the rejector
- std::srand (1e6);
+ // Test rejector with varying seeds
+ const unsigned int seed = std::time(nullptr);
+ std::srand (seed);
// Create a rejection object
pcl::registration::CorrespondenceRejectorPoly<pcl::PointXYZ, pcl::PointXYZ> reject;
- reject.setIterations (10000);
+ reject.setIterations (20000);
reject.setCardinality (3);
- reject.setSimilarityThreshold (0.75f);
- reject.setInputSource (cloud.makeShared ());
- reject.setInputTarget (target.makeShared ());
+ reject.setSimilarityThreshold (0.8f);
+ reject.setInputSource (cloud);
+ reject.setInputTarget (target);
// Run rejection
pcl::Correspondences result;
}
// Input
- if (pcl::io::loadPCDFile (argv[1], cloud) < 0)
+ cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);
+ if (pcl::io::loadPCDFile (argv[1], *cloud) < 0)
{
std::cerr << "Failed to read test file. Please download `bunny.pcd` and pass its path to the test." << std::endl;
return (-1);
// transform the source cloud by a large amount
Eigen::Vector3f initial_offset (1.f, 0.f, 0.f);
float angle = static_cast<float> (M_PI) / 2.f;
- Eigen::Quaternionf initial_rotation (std::cos (angle / 2.f), 0, 0, sin (angle / 2.f));
+ Eigen::Quaternionf initial_rotation (std::cos (angle / 2.f), 0, 0, std::sin (angle / 2.f));
PointCloud<PointXYZ> cloud_source_transformed;
transformPointCloud (cloud_source, cloud_source_transformed, initial_offset, initial_rotation);
*
*/
+#include <limits>
+
#include <pcl/test/gtest.h>
#include <pcl/point_types.h>
// repeat alignment 2 times to increase probability to ~99.99%
const float max_angle3d = 0.1745f, max_translation3d = 1.f;
- float angle3d = FLT_MAX, translation3d = FLT_MAX;
+ float angle3d = std::numeric_limits<float>::max(), translation3d = std::numeric_limits<float>::max();
for (int i = 0; i < 2; i++)
{
kfpcs_ia.align (cloud_source_aligned);
class RegistrationWrapper : public Registration<PointSource, PointTarget>
{
public:
- void computeTransformation (pcl::PointCloud<PointSource> &, const Eigen::Matrix4f&) { }
+ void computeTransformation (pcl::PointCloud<PointSource> &, const Eigen::Matrix4f&) override { }
bool hasValidFeaturesTest ()
{
// Transform the source cloud by a large amount
Eigen::Vector3f initial_offset (100, 0, 0);
float angle = static_cast<float> (M_PI) / 2.0f;
- Eigen::Quaternionf initial_rotation (std::cos (angle / 2), 0, 0, sin (angle / 2));
+ Eigen::Quaternionf initial_rotation (std::cos (angle / 2), 0, 0, std::sin (angle / 2));
PointCloud<PointXYZ> cloud_source_transformed;
transformPointCloud (cloud_source, cloud_source_transformed, initial_offset, initial_rotation);
NormalEstimation<PointXYZ, Normal> norm_est;
norm_est.setSearchMethod (tree);
norm_est.setRadiusSearch (0.05);
- PointCloud<Normal> normals;
+ PointCloud<Normal>::Ptr normals(new PointCloud<Normal>);
FPFHEstimation<PointXYZ, Normal, FPFHSignature33> fpfh_est;
fpfh_est.setSearchMethod (tree);
fpfh_est.setRadiusSearch (0.05);
- PointCloud<FPFHSignature33> features_source, features_target;
+ PointCloud<FPFHSignature33>::Ptr features_source(new PointCloud<FPFHSignature33>), features_target(new PointCloud<FPFHSignature33>);
// Estimate the FPFH features for the source cloud
norm_est.setInputCloud (cloud_source_ptr);
- norm_est.compute (normals);
+ norm_est.compute (*normals);
fpfh_est.setInputCloud (cloud_source_ptr);
- fpfh_est.setInputNormals (normals.makeShared ());
- fpfh_est.compute (features_source);
+ fpfh_est.setInputNormals (normals);
+ fpfh_est.compute (*features_source);
// Estimate the FPFH features for the target cloud
norm_est.setInputCloud (cloud_target_ptr);
- norm_est.compute (normals);
+ norm_est.compute (*normals);
fpfh_est.setInputCloud (cloud_target_ptr);
- fpfh_est.setInputNormals (normals.makeShared ());
- fpfh_est.compute (features_target);
+ fpfh_est.setInputNormals (normals);
+ fpfh_est.compute (*features_target);
// Initialize Sample Consensus Initial Alignment (SAC-IA)
SampleConsensusInitialAlignment<PointXYZ, PointXYZ, FPFHSignature33> reg;
reg.setInputSource (cloud_source_ptr);
reg.setInputTarget (cloud_target_ptr);
- reg.setSourceFeatures (features_source.makeShared ());
- reg.setTargetFeatures (features_target.makeShared ());
+ reg.setSourceFeatures (features_source);
+ reg.setTargetFeatures (features_target);
// Register
reg.align (cloud_reg);
// Transform the source cloud by a large amount
Eigen::Vector3f initial_offset (100, 0, 0);
float angle = static_cast<float> (M_PI) / 2.0f;
- Eigen::Quaternionf initial_rotation (std::cos (angle / 2), 0, 0, sin (angle / 2));
+ Eigen::Quaternionf initial_rotation (std::cos (angle / 2), 0, 0, std::sin (angle / 2));
PointCloud<PointXYZ> cloud_source_transformed;
transformPointCloud (cloud_source, cloud_source_transformed, initial_offset, initial_rotation);
NormalEstimation<PointXYZ, Normal> norm_est;
norm_est.setSearchMethod (tree);
norm_est.setRadiusSearch (0.005);
- PointCloud<Normal> normals;
+ PointCloud<Normal>::Ptr normals(new PointCloud<Normal>);
// FPFH estimator
FPFHEstimation<PointXYZ, Normal, FPFHSignature33> fpfh_est;
fpfh_est.setSearchMethod (tree);
fpfh_est.setRadiusSearch (0.05);
- PointCloud<FPFHSignature33> features_source, features_target;
+ PointCloud<FPFHSignature33>::Ptr features_source(new PointCloud<FPFHSignature33>), features_target(new PointCloud<FPFHSignature33>);
// Estimate the normals and the FPFH features for the source cloud
norm_est.setInputCloud (cloud_source_ptr);
- norm_est.compute (normals);
+ norm_est.compute (*normals);
fpfh_est.setInputCloud (cloud_source_ptr);
- fpfh_est.setInputNormals (normals.makeShared ());
- fpfh_est.compute (features_source);
+ fpfh_est.setInputNormals (normals);
+ fpfh_est.compute (*features_source);
// Estimate the normals and the FPFH features for the target cloud
norm_est.setInputCloud (cloud_target_ptr);
- norm_est.compute (normals);
+ norm_est.compute (*normals);
fpfh_est.setInputCloud (cloud_target_ptr);
- fpfh_est.setInputNormals (normals.makeShared ());
- fpfh_est.compute (features_target);
+ fpfh_est.setInputNormals (normals);
+ fpfh_est.compute (*features_target);
// Initialize Sample Consensus Prerejective with 5x the number of iterations and 1/5 feature kNNs as SAC-IA
SampleConsensusPrerejective<PointXYZ, PointXYZ, FPFHSignature33> reg;
// Set source and target cloud/features
reg.setInputSource (cloud_source_ptr);
reg.setInputTarget (cloud_target_ptr);
- reg.setSourceFeatures (features_source.makeShared ());
- reg.setTargetFeatures (features_target.makeShared ());
+ reg.setSourceFeatures (features_source);
+ reg.setTargetFeatures (features_target);
// Register
reg.align (cloud_reg);
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
EXPECT_NEAR (0, coeff[5], 1e-4);
}
+TEST (SampleConsensusModelLine, SampleValidationPointsEqual)
+{
+ PointCloud<PointXYZ> cloud;
+ cloud.resize (3);
+
+ // The "cheat point" makes it possible to find a set of valid samples and
+ // therefore avoids the log message of an unsuccessful sample validation
+ // being printed a 1000 times without any chance of success.
+ // The order is chosen such that with a known, fixed rng-state/-seed all
+ // validation steps are actually exercised.
+ const pcl::index_t firstKnownEqualPoint = 0;
+ const pcl::index_t secondKnownEqualPoint = 1;
+ const pcl::index_t cheatPointIndex = 2;
+
+ cloud[firstKnownEqualPoint].getVector3fMap () << 0.1f, 0.0f, 0.0f;
+ cloud[secondKnownEqualPoint].getVector3fMap () << 0.1f, 0.0f, 0.0f;
+ cloud[cheatPointIndex].getVector3fMap () << 0.0f, 0.1f, 0.0f; // <-- cheat point
+
+ // Create a shared line model pointer directly and explicitly disable the
+ // random seed for the reasons mentioned above
+ SampleConsensusModelLinePtr model (
+ new SampleConsensusModelLine<PointXYZ> (cloud.makeShared (), /* random = */ false));
+
+ // Algorithm tests
+ pcl::Indices samples;
+ int iterations = 0;
+ model->getSamples(iterations, samples);
+ EXPECT_EQ (samples.size(), 2);
+ // The "cheat point" has to be part of the sample, otherwise something is wrong.
+ // The best option would be to assert on stderr output here, but that doesn't
+ // seem to be that simple.
+ EXPECT_TRUE (std::find(samples.begin (), samples.end (), cheatPointIndex) != samples.end ());
+
+ pcl::Indices forcedSamples = {firstKnownEqualPoint, secondKnownEqualPoint};
+ Eigen::VectorXf modelCoefficients;
+ EXPECT_FALSE (model->computeModelCoefficients (forcedSamples, modelCoefficients));
+}
+
+TEST (SampleConsensusModelLine, SampleValidationPointsValid)
+{
+ PointCloud<PointXYZ> cloud;
+ cloud.resize (2);
+
+ // These two points only differ in one coordinate so this also acts as a
+ // regression test for 36c2bd6209f87dc7c6f56e2c0314e19f9cab95ec
+ cloud[0].getVector3fMap () << 0.0f, 0.0f, 0.0f;
+ cloud[1].getVector3fMap () << 0.1f, 0.0f, 0.0f;
+
+ // Create a shared line model pointer directly
+ SampleConsensusModelLinePtr model (new SampleConsensusModelLine<PointXYZ> (cloud.makeShared ()));
+
+ // Algorithm tests
+ pcl::Indices samples;
+ int iterations = 0;
+ model->getSamples(iterations, samples);
+ EXPECT_EQ (samples.size(), 2);
+
+ pcl::Indices forcedSamples = {0, 1};
+ Eigen::VectorXf modelCoefficients;
+ EXPECT_TRUE (model->computeModelCoefficients (forcedSamples, modelCoefficients));
+}
+
+TEST (SampleConsensusModelLine, SampleValidationNotEnoughSamples)
+{
+ PointCloud<PointXYZ> cloud;
+ cloud.resize (1);
+
+ cloud[0].getVector3fMap () << 0.1f, 0.0f, 0.0f;
+
+ // Create a shared line model pointer directly
+ SampleConsensusModelLinePtr model (new SampleConsensusModelLine<PointXYZ> (cloud.makeShared ()));
+
+ // Algorithm tests
+ pcl::Indices samples;
+ int iterations = 0;
+ model->getSamples(iterations, samples);
+ EXPECT_EQ (samples.size(), 0);
+
+ pcl::Indices forcedSamples = {0,};
+ Eigen::VectorXf modelCoefficients;
+ EXPECT_FALSE (model->computeModelCoefficients (forcedSamples, modelCoefficients));
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (SampleConsensusModelParallelLine, RANSAC)
{
ASSERT_EQ (indices_.size (), indices->size ());
}
+TEST (SampleConsensusModelPlane, SampleValidationPointsCollinear)
+{
+ PointCloud<PointXYZ> cloud;
+ cloud.resize (4);
+
+ // The "cheat point" makes it possible to find a set of valid samples and
+ // therefore avoids the log message of an unsuccessful sample validation
+ // being printed a 1000 times without any chance of success.
+ // The order is chosen such that with a known, fixed rng-state/-seed all
+ // validation steps are actually exercised.
+ const pcl::index_t firstCollinearPointIndex = 0;
+ const pcl::index_t secondCollinearPointIndex = 1;
+ const pcl::index_t thirdCollinearPointIndex = 2;
+ const pcl::index_t cheatPointIndex = 3;
+
+ cloud[firstCollinearPointIndex].getVector3fMap () << 0.1f, 0.1f, 0.1f;
+ cloud[secondCollinearPointIndex].getVector3fMap () << 0.2f, 0.2f, 0.2f;
+ cloud[thirdCollinearPointIndex].getVector3fMap () << 0.3f, 0.3f, 0.3f;
+ cloud[cheatPointIndex].getVector3fMap () << 0.0f, 0.1f, 0.0f; // <-- cheat point
+
+ // Create a shared line model pointer directly and explicitly disable the
+ // random seed for the reasons mentioned above
+ SampleConsensusModelPlanePtr model (
+ new SampleConsensusModelPlane<PointXYZ> (cloud.makeShared (), /* random = */ false));
+
+ // Algorithm tests
+ pcl::Indices samples;
+ int iterations = 0;
+ model->getSamples(iterations, samples);
+ EXPECT_EQ (samples.size(), 3);
+ // The "cheat point" has to be part of the sample, otherwise something is wrong.
+ // The best option would be to assert on stderr output here, but that doesn't
+ // seem to be that simple.
+ EXPECT_TRUE (std::find(samples.begin (), samples.end (), cheatPointIndex) != samples.end ());
+
+ pcl::Indices forcedSamples = {firstCollinearPointIndex, secondCollinearPointIndex, thirdCollinearPointIndex};
+ Eigen::VectorXf modelCoefficients;
+ EXPECT_FALSE (model->computeModelCoefficients (forcedSamples, modelCoefficients));
+}
+
+TEST (SampleConsensusModelPlane, SampleValidationPointsValid)
+{
+ PointCloud<PointXYZ> cloud;
+ cloud.resize (3);
+
+ cloud[0].getVector3fMap () << 0.1f, 0.0f, 0.0f;
+ cloud[1].getVector3fMap () << 0.0f, 0.1f, 0.0f;
+ cloud[2].getVector3fMap () << 0.0f, 0.0f, 0.1f;
+
+ // Create a shared line model pointer directly
+ SampleConsensusModelPlanePtr model (
+ new SampleConsensusModelPlane<PointXYZ> (cloud.makeShared ()));
+
+ // Algorithm tests
+ pcl::Indices samples;
+ int iterations = 0;
+ model->getSamples(iterations, samples);
+ EXPECT_EQ (samples.size(), 3);
+
+ Eigen::VectorXf modelCoefficients;
+ EXPECT_TRUE (model->computeModelCoefficients (samples, modelCoefficients));
+}
+
+TEST (SampleConsensusModelPlane, SampleValidationNotEnoughSamples)
+{
+ PointCloud<PointXYZ> cloud;
+ cloud.resize (2);
+
+ cloud[0].getVector3fMap () << 0.1f, 0.0f, 0.0f;
+ cloud[1].getVector3fMap () << 0.0f, 0.1f, 0.0f;
+
+ std::vector<pcl::Indices> testIndices = {{}, {0,}, {0, 1}};
+
+ for( const auto& indices : testIndices) {
+ PointCloud<PointXYZ> subCloud {cloud, indices};
+
+ // Create a shared line model pointer directly
+ SampleConsensusModelPlanePtr model (
+ new SampleConsensusModelPlane<PointXYZ> (subCloud.makeShared ()));
+
+ // Algorithm tests
+ pcl::Indices samples;
+ int iterations = 0;
+ model->getSamples(iterations, samples);
+ EXPECT_EQ (samples.size(), 0);
+
+ Eigen::VectorXf modelCoefficients;
+ EXPECT_FALSE (model->computeModelCoefficients (indices, modelCoefficients));
+ }
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (SampleConsensusModelPlane, RANSAC)
{
// test axis slightly in valid range
{
- model->setAxis (Eigen::Vector3f (0, sin (max_angle_rad * (1 - angle_eps)), std::cos (max_angle_rad * (1 - angle_eps))));
+ model->setAxis (Eigen::Vector3f (0, std::sin (max_angle_rad * (1 - angle_eps)), std::cos (max_angle_rad * (1 - angle_eps))));
RandomSampleConsensus<PointXYZ> sac (model, 0.03);
sac.computeModel ();
// test axis slightly out of valid range
{
- model->setAxis (Eigen::Vector3f (0, sin (max_angle_rad * (1 + angle_eps)), std::cos (max_angle_rad * (1 + angle_eps))));
+ model->setAxis (Eigen::Vector3f (0, std::sin (max_angle_rad * (1 + angle_eps)), std::cos (max_angle_rad * (1 + angle_eps))));
RandomSampleConsensus<PointXYZ> sac (model, 0.03);
sac.computeModel ();
#include <pcl/sample_consensus/sac_model_circle.h>
#include <pcl/sample_consensus/sac_model_circle3d.h>
#include <pcl/sample_consensus/sac_model_normal_sphere.h>
+#include <pcl/sample_consensus/sac_model_ellipse3d.h>
using namespace pcl;
using SampleConsensusModelCircle3DPtr = SampleConsensusModelCircle3D<PointXYZ>::Ptr;
using SampleConsensusModelCylinderPtr = SampleConsensusModelCylinder<PointXYZ, Normal>::Ptr;
using SampleConsensusModelNormalSpherePtr = SampleConsensusModelNormalSphere<PointXYZ, Normal>::Ptr;
+using SampleConsensusModelEllipse3DPtr = SampleConsensusModelEllipse3D<PointXYZ>::Ptr;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TEST (SampleConsensusModelSphere, RANSAC)
EXPECT_NEAR ( 1, coeff_refined[2], 1e-3);
}
+///////////////////////////////////////////////////////////////////////////////
+
+TEST (SampleConsensusModelCircle2D, SampleValidationPointsValid)
+{
+ PointCloud<PointXYZ> cloud;
+ cloud.resize (3);
+
+ cloud[0].getVector3fMap () << 1.0f, 2.0f, 0.0f;
+ cloud[1].getVector3fMap () << 0.0f, 1.0f, 0.0f;
+ cloud[2].getVector3fMap () << 1.5f, 0.0f, 0.0f;
+
+ // Create a shared line model pointer directly
+ SampleConsensusModelCircle2DPtr model (
+ new SampleConsensusModelCircle2D<PointXYZ> (cloud.makeShared ()));
+
+ // Algorithm tests
+ pcl::Indices samples;
+ int iterations = 0;
+ model->getSamples(iterations, samples);
+ EXPECT_EQ (samples.size(), 3);
+
+ Eigen::VectorXf modelCoefficients;
+ EXPECT_TRUE (model->computeModelCoefficients (samples, modelCoefficients));
+
+ EXPECT_NEAR (modelCoefficients[0], 1.05f, 1e-3); // center x
+ EXPECT_NEAR (modelCoefficients[1], 0.95f, 1e-3); // center y
+ EXPECT_NEAR (modelCoefficients[2], std::sqrt (1.105f), 1e-3); // radius
+}
+
+using PointVector = std::vector<PointXYZ>;
+class SampleConsensusModelCircle2DCollinearTest
+ : public testing::TestWithParam<PointVector> {
+ protected:
+ void SetUp() override {
+ pointCloud_ = make_shared<PointCloud<PointXYZ>>();
+ for(const auto& point : GetParam()) {
+ pointCloud_->emplace_back(point);
+ }
+ }
+
+ PointCloud<PointXYZ>::Ptr pointCloud_ = nullptr;
+};
+
+// Parametric tests clearly show the input for which they failed and provide
+// clearer feedback if something is changed in the future.
+TEST_P (SampleConsensusModelCircle2DCollinearTest, SampleValidationPointsInvalid)
+{
+ ASSERT_NE (pointCloud_, nullptr);
+
+ SampleConsensusModelCircle2DPtr model (
+ new SampleConsensusModelCircle2D<PointXYZ> (pointCloud_));
+ ASSERT_GE (model->getInputCloud ()->size (), model->getSampleSize ());
+
+ // Algorithm tests
+ // (Maybe) TODO: try to implement the "cheat point" trick from
+ // test_sample_consensus_line_models.cpp and friends here, too.
+ // pcl::Indices samples;
+ // int iterations = 0;
+ // model->getSamples(iterations, samples);
+ // EXPECT_EQ (samples.size(), 0);
+
+ // Explicitly enforce sample order so they can act as designed
+ pcl::Indices forcedSamples = {0, 1, 2};
+ Eigen::VectorXf modelCoefficients;
+ EXPECT_FALSE (model->computeModelCoefficients (forcedSamples, modelCoefficients));
+}
+
+INSTANTIATE_TEST_SUITE_P (CollinearInputs, SampleConsensusModelCircle2DCollinearTest,
+ testing::Values( // Throw in some negative coordinates and "asymmetric" points to cover more cases
+ PointVector {{ 0.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 2.0f, 0.0f, 0.0f}}, // collinear along x-axis
+ PointVector {{-1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 2.0f, 0.0f, 0.0f}},
+ PointVector {{ 0.0f, -1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 2.0f, 0.0f}}, // collinear along y-axis
+ PointVector {{ 0.0f, -1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 2.0f, 0.0f}},
+ PointVector {{ 0.0f, 0.0f, 0.0f}, { 1.0f, 1.0f, 0.0f}, { 2.0f, 2.0f, 0.0f}}, // collinear along diagonal
+ PointVector {{ 0.0f, 0.0f, 0.0f}, {-1.0f, -1.0f, 0.0f}, {-2.0f, -2.0f, 0.0f}},
+ PointVector {{-3.0f, -6.5f, 0.0f}, {-2.0f, -0.5f, 0.0f}, {-1.5f, 2.5f, 0.0f}}, // other collinear input
+ PointVector {{ 2.0f, 2.0f, 0.0f}, { 0.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 0.0f}}, // two points equal
+ PointVector {{ 0.0f, 0.0f, 0.0f}, { 2.0f, 2.0f, 0.0f}, { 0.0f, 0.0f, 0.0f}},
+ PointVector {{ 0.0f, 0.0f, 0.0f}, { 0.0f, 0.0f, 0.0f}, { 2.0f, 2.0f, 0.0f}},
+ PointVector {{ 1.0f, 1.0f, 0.0f}, { 1.0f, 1.0f, 0.0f}, { 1.0f, 1.0f, 0.0f}} // all points equal
+ )
+);
+
//////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT>
class SampleConsensusModelCircle2DTest : private SampleConsensusModelCircle2D<PointT>
EXPECT_NEAR (-3.0, coeff[2], 1e-3);
EXPECT_NEAR ( 0.1, coeff[3], 1e-3);
EXPECT_NEAR ( 0.0, coeff[4], 1e-3);
- EXPECT_NEAR (-1.0, coeff[5], 1e-3);
+ // Use abs in y component because both variants are valid normal vectors
+ EXPECT_NEAR ( 1.0, std::abs (coeff[5]), 1e-3);
EXPECT_NEAR ( 0.0, coeff[6], 1e-3);
Eigen::VectorXf coeff_refined;
EXPECT_NEAR (-3.0, coeff_refined[2], 1e-3);
EXPECT_NEAR ( 0.1, coeff_refined[3], 1e-3);
EXPECT_NEAR ( 0.0, coeff_refined[4], 1e-3);
- EXPECT_NEAR (-1.0, coeff_refined[5], 1e-3);
+ EXPECT_NEAR ( 1.0, std::abs (coeff_refined[5]), 1e-3);
EXPECT_NEAR ( 0.0, coeff_refined[6], 1e-3);
}
-TEST (SampleConsensusModelCylinder, projectPoints)
+TEST (SampleConsensusModelSphere, projectPoints)
{
- Eigen::VectorXf model_coefficients(7);
- model_coefficients << -0.59, 0.85, -0.80, 0.22, -0.70, 0.68, 0.18;
+ Eigen::VectorXf model_coefficients(4);
+ model_coefficients << -0.32, -0.89, 0.37, 0.12; // center and radius
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.259754, -0.950873, 0.318377); // inlier, dist from center=0.10
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.221871, -0.973718, 0.353817); // inlier, dist from center=0.13
+ input->emplace_back(-0.332269, -0.848851, 0.437499); // inlier, dist from center=0.08
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.327668, -0.800009, 0.290988); // inlier, dist from center=0.12
+ input->emplace_back(-0.173948, -0.883831, 0.403625); // inlier, dist from center=0.15
input->emplace_back(-0.033891, 0.624537, -0.606994); // outlier, not projected
+ pcl::SampleConsensusModelSphere<pcl::PointXYZ> model(input);
+ pcl::Indices inliers = {0, 2, 3, 5, 6};
+
+ pcl::PointCloud<pcl::PointXYZ> projected_truth;
+ projected_truth.emplace_back(-0.247705, -0.963048, 0.308053);
+ projected_truth.emplace_back(-0.229419, -0.967278, 0.355062);
+ projected_truth.emplace_back(-0.338404, -0.828276, 0.471249);
+ projected_truth.emplace_back(-0.327668, -0.800009, 0.290988);
+ projected_truth.emplace_back(-0.203158, -0.885065, 0.396900);
+
+ 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);
+}
+
+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_points;
model.projectPoints(inliers, model_coefficients, projected_points, false);
EXPECT_EQ(projected_points.size(), 5);
- for(int i=0; i<5; ++i)
+ 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;
EXPECT_XYZ_NEAR(projected_points_all[7], (*input)[7], 1e-5);
}
+TEST(SampleConsensusModelEllipse3D, RANSAC)
+{
+ srand(0);
+
+ // Using a custom point cloud on a tilted plane
+ PointCloud<PointXYZ> cloud;
+ cloud.resize(22);
+
+ cloud[ 0].getVector3fMap() << 1.000000, 5.000000, 3.000000;
+ cloud[ 1].getVector3fMap() << 0.690983, 5.000000, 2.902110;
+ cloud[ 2].getVector3fMap() << 0.412215, 5.000000, 2.618030;
+ cloud[ 3].getVector3fMap() << 0.190983, 5.000000, 2.175570;
+ cloud[ 4].getVector3fMap() << 0.048944, 5.000000, 1.618030;
+ cloud[ 5].getVector3fMap() << 0.000000, 5.000000, 1.000000;
+ cloud[ 6].getVector3fMap() << 0.048944, 5.000000, 0.381966;
+ cloud[ 7].getVector3fMap() << 0.190983, 5.000000, -0.175571;
+ cloud[ 8].getVector3fMap() << 0.412215, 5.000000, -0.618034;
+ cloud[ 9].getVector3fMap() << 0.690983, 5.000000, -0.902113;
+ cloud[10].getVector3fMap() << 1.000000, 5.000000, -1.000000;
+ cloud[11].getVector3fMap() << 1.309020, 5.000000, -0.902113;
+ cloud[12].getVector3fMap() << 1.587790, 5.000000, -0.618034;
+ cloud[13].getVector3fMap() << 1.809020, 5.000000, -0.175571;
+ cloud[14].getVector3fMap() << 1.951060, 5.000000, 0.381966;
+ cloud[15].getVector3fMap() << 2.000000, 5.000000, 1.000000;
+ cloud[16].getVector3fMap() << 1.951060, 5.000000, 1.618030;
+ cloud[17].getVector3fMap() << 1.809020, 5.000000, 2.175570;
+ cloud[18].getVector3fMap() << 1.587790, 5.000000, 2.618030;
+ cloud[19].getVector3fMap() << 1.309020, 5.000000, 2.902110;
+
+ cloud[20].getVector3fMap() << 0.85000002f, 4.8499999f, -3.1500001f;
+ cloud[21].getVector3fMap() << 1.15000000f, 5.1500001f, -2.8499999f;
+
+ // Create a shared 3d ellipse model pointer directly
+ SampleConsensusModelEllipse3DPtr model( new SampleConsensusModelEllipse3D<PointXYZ>(cloud.makeShared()));
+
+ // Create the RANSAC object
+ RandomSampleConsensus<PointXYZ> sac(model, 0.0011);
+
+ // Algorithm tests
+ bool result = sac.computeModel();
+ ASSERT_TRUE(result);
+
+ pcl::Indices sample;
+ sac.getModel(sample);
+ EXPECT_EQ(6, sample.size());
+
+ pcl::Indices inliers;
+ sac.getInliers(inliers);
+ EXPECT_EQ(20, inliers.size());
+
+ Eigen::VectorXf coeff;
+ sac.getModelCoefficients(coeff);
+ EXPECT_EQ(11, coeff.size());
+ EXPECT_NEAR(1.0, coeff[0], 1e-3);
+ EXPECT_NEAR(5.0, coeff[1], 1e-3);
+ EXPECT_NEAR(1.0, coeff[2], 1e-3);
+
+ EXPECT_NEAR(2.0, coeff[3], 1e-3);
+ EXPECT_NEAR(1.0, coeff[4], 1e-3);
+
+ EXPECT_NEAR(0.0, coeff[5], 1e-3);
+ // Use abs in y component because both variants are valid normal vectors
+ EXPECT_NEAR(1.0, std::abs(coeff[6]), 1e-3);
+ EXPECT_NEAR(0.0, coeff[7], 1e-3);
+
+ EXPECT_NEAR(0.0, coeff[8], 1e-3);
+ EXPECT_NEAR(0.0, coeff[9], 1e-3);
+ // Use abs in z component because both variants are valid local vectors
+ EXPECT_NEAR(1.0, std::abs(coeff[10]), 1e-3);
+
+ Eigen::VectorXf coeff_refined;
+ model->optimizeModelCoefficients(inliers, coeff, coeff_refined);
+ EXPECT_EQ(11, coeff_refined.size());
+ EXPECT_NEAR(1.0, coeff_refined[0], 1e-3);
+ EXPECT_NEAR(5.0, coeff_refined[1], 1e-3);
+ EXPECT_NEAR(1.0, coeff_refined[2], 1e-3);
+
+ EXPECT_NEAR(2.0, coeff_refined[3], 1e-3);
+ EXPECT_NEAR(1.0, coeff_refined[4], 1e-3);
+
+ EXPECT_NEAR(0.0, coeff_refined[5], 1e-3);
+ // Use abs in y component because both variants are valid normal vectors
+ EXPECT_NEAR(1.0, std::abs(coeff_refined[6]), 1e-3);
+ EXPECT_NEAR(0.0, coeff_refined[7], 1e-3);
+
+ EXPECT_NEAR(0.0, coeff_refined[8], 1e-3);
+ EXPECT_NEAR(0.0, coeff_refined[9], 1e-3);
+ // Use abs in z component because both variants are valid local vectors
+ EXPECT_NEAR(1.0, std::abs(coeff_refined[10]), 1e-3);
+}
+
int
main (int argc, char** argv)
{
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
}
float max_dist = 0.0f;
unsigned int counter = 0;
- for (std::multimap<float, int>::iterator it = sorted_brute_force_result.begin (); it != sorted_brute_force_result.end ()
+ for (auto it = sorted_brute_force_result.begin (); it != sorted_brute_force_result.end ()
&& counter < no_of_neighbors; ++it)
{
max_dist = std::max (max_dist, it->first);
}
float max_dist = 0.0f;
unsigned int counter = 0;
- for (std::multimap<float, int>::iterator it = sorted_brute_force_result.begin (); it != sorted_brute_force_result.end ()
+ for (auto it = sorted_brute_force_result.begin (); it != sorted_brute_force_result.end ()
&& counter < no_of_neighbors; ++it)
{
max_dist = std::max (max_dist, it->first);
{
public:
prioPointQueueEntry ()
- {
- }
+ = default;
prioPointQueueEntry (PointXYZ& point_arg, double pointDistance_arg, int pointIdx_arg)
{
point_ = point_arg;
pointCandidates.pop ();
// copy results into vectors
- unsigned idx = static_cast<unsigned> (pointCandidates.size ());
+ auto idx = static_cast<unsigned> (pointCandidates.size ());
k_indices_bruteforce.resize (idx);
k_sqr_distances_bruteforce.resize (idx);
while (!pointCandidates.empty ())
std::vector<int> cloudSearchBruteforce;
for (std::size_t i = 0; i < cloudIn->size (); i++)
{
- pointDist = sqrt (
+ pointDist = std::sqrt (
((*cloudIn)[i].x - searchPoint.x) * ((*cloudIn)[i].x - searchPoint.x)
+ ((*cloudIn)[i].y - searchPoint.y) * ((*cloudIn)[i].y - searchPoint.y)
+ ((*cloudIn)[i].z - searchPoint.z) * ((*cloudIn)[i].z - searchPoint.z));
// check if result from octree radius search can be also found in bruteforce search
for (const auto& current : cloudNWRSearch)
{
- pointDist = sqrt (
+ pointDist = std::sqrt (
((*cloudIn)[current].x-searchPoint.x) * ((*cloudIn)[current].x-searchPoint.x) +
((*cloudIn)[current].y-searchPoint.y) * ((*cloudIn)[current].y-searchPoint.y) +
((*cloudIn)[current].z-searchPoint.z) * ((*cloudIn)[current].z-searchPoint.z)
{
public:
prioPointQueueEntry ()
- {
- }
+ = default;
prioPointQueueEntry (PointXYZ& point_arg, double pointDistance_arg, int pointIdx_arg)
{
point_ = point_arg;
for (std::size_t i = 0; i < cloudIn->size (); i++)
{
- pointDist = sqrt (
+ pointDist = std::sqrt (
((*cloudIn)[i].x - searchPoint.x) * ((*cloudIn)[i].x - searchPoint.x)
+ ((*cloudIn)[i].y - searchPoint.y) * ((*cloudIn)[i].y - searchPoint.y)
+ ((*cloudIn)[i].z - searchPoint.z) * ((*cloudIn)[i].z - searchPoint.z));
// check if result from organized radius search can be also found in bruteforce search
for (const auto& current : cloudNWRSearch)
{
- pointDist = sqrt (
+ pointDist = std::sqrt (
((*cloudIn)[current].x-searchPoint.x) * ((*cloudIn)[current].x-searchPoint.x) +
((*cloudIn)[current].y-searchPoint.y) * ((*cloudIn)[current].y-searchPoint.y) +
((*cloudIn)[current].z-searchPoint.z) * ((*cloudIn)[current].z-searchPoint.z)
// check if bruteforce result from organized radius search can be also found in bruteforce search
for (const auto& current : cloudSearchBruteforce)
{
- pointDist = sqrt (
+ pointDist = std::sqrt (
((*cloudIn)[current].x-searchPoint.x) * ((*cloudIn)[current].x-searchPoint.x) +
((*cloudIn)[current].y-searchPoint.y) * ((*cloudIn)[current].y-searchPoint.y) +
((*cloudIn)[current].z-searchPoint.z) * ((*cloudIn)[current].z-searchPoint.z)
class prioPointQueueEntry
{
public:
- prioPointQueueEntry ()
- = default;
+ prioPointQueueEntry () = default;
prioPointQueueEntry (PointXYZ& point_arg, double pointDistance_arg, int pointIdx_arg)
{
point_ = point_arg;
// typical focal length from kinect
constexpr double oneOverFocalLength = 0.0018;
- double radiusSearchTime = 0, radiusSearchLPTime = 0;
-
for (unsigned int test_id = 0; test_id < test_runs; test_id++)
{
// generate point cloud
pcl::Indices cloudNWRSearch;
std::vector<float> cloudNWRRadius;
- double check_time = getTime();
organizedNeighborSearch.setInputCloud (cloudIn);
organizedNeighborSearch.radiusSearch ((*cloudIn)[randomIdx], searchRadius, cloudNWRSearch, cloudNWRRadius, std::numeric_limits<unsigned int>::max());
- double check_time2 = getTime();
-
- radiusSearchLPTime += check_time2 - check_time;
-
organizedNeighborSearch.setInputCloud (cloudIn);
organizedNeighborSearch.radiusSearch ((*cloudIn)[randomIdx], searchRadius, cloudNWRSearch, cloudNWRRadius, std::numeric_limits<unsigned int>::max());
-
- radiusSearchTime += getTime() - check_time2;
}
}
// compare results to each other
#pragma omp parallel for \
default(none) \
- shared(distances, indices, passed, search_methods)
+ shared(distances, indices, passed, search_methods, radius)
for (int sIdx = 1; sIdx < static_cast<int> (search_methods.size ()); ++sIdx)
{
- passed [sIdx] = passed [sIdx] && compareResults (indices [0], distances [0], search_methods [0]->getName (),
- indices [sIdx], distances [sIdx], search_methods [sIdx]->getName (), 1e-6f);
+ const bool same_results = compareResults (indices [0], distances [0], search_methods [0]->getName (),
+ indices [sIdx], distances [sIdx], search_methods [sIdx]->getName (), 1e-6f);
+ if (!same_results) {
+ if ((((indices [0 ].size()+1)==indices [sIdx].size()) && std::abs(*distances [sIdx].crbegin()-radius*radius)<1e-6) ||
+ (((indices [sIdx].size()+1)==indices [0 ].size()) && std::abs(*distances [0 ].crbegin()-radius*radius)<1e-6)) {
+ // One result list has one entry more than the other, and this additional entry is very close to the radius boundary.
+ // Because of numerical inaccuracies, points very close to the boundary may be counted as inside or outside depending
+ // on the search method. The two result lists will still be considered the same in this case.
+ } else {
+ passed [sIdx] = false;
+ }
+ }
}
}
}
pcl::io::loadPCDFile (argv [1], *organized_sparse_cloud);
+ const unsigned int seed = time (nullptr);
+ srand (seed);
+
// create unorganized cloud
unorganized_dense_cloud->resize (unorganized_point_count);
unorganized_dense_cloud->height = 1;
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
}
// Load a standard PCD file from disk
- PointCloud<PointXYZ> cloud, cloud_t, another_cloud;
- PointCloud<PointXYZRGB> colored_cloud_1;
- if (loadPCDFile (argv[1], cloud) < 0)
+ cloud_.reset(new PointCloud<PointXYZ>);
+ if (loadPCDFile (argv[1], *cloud_) < 0)
{
std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its path to the test." << std::endl;
return (-1);
}
- if (pcl::io::loadPCDFile (argv[2], another_cloud) < 0)
+ another_cloud_.reset(new PointCloud<PointXYZ>);
+ if (pcl::io::loadPCDFile (argv[2], *another_cloud_) < 0)
{
std::cerr << "Failed to read test file. Please download `car6.pcd` and pass its path to the test." << std::endl;
return (-1);
}
- if (pcl::io::loadPCDFile (argv[3], colored_cloud_1) < 0)
+ colored_cloud.reset(new PointCloud<PointXYZRGB>);
+ if (pcl::io::loadPCDFile (argv[3], *colored_cloud) < 0)
{
std::cerr << "Failed to read test file. Please download `colored_cloud.pcd` and pass its path to the test." << std::endl;
return (-1);
}
- colored_cloud = colored_cloud_1.makeShared();
-
// Tranpose the cloud
- cloud_t = cloud;
- for (auto& point: cloud_t)
+ cloud_t_.reset(new PointCloud<PointXYZ>);
+ *cloud_t_ = *cloud_;
+ for (auto& point: *cloud_t_)
point.x += 0.01f;
- cloud_ = cloud.makeShared ();
- cloud_t_ = cloud_t.makeShared ();
-
- another_cloud_ = another_cloud.makeShared();
- normals_ = (new pcl::PointCloud<pcl::Normal>)->makeShared();
+ normals_.reset (new pcl::PointCloud<pcl::Normal>);
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
normal_estimator.setInputCloud(cloud_);
normal_estimator.setKSearch(30);
normal_estimator.compute(*normals_);
- another_normals_ = (new pcl::PointCloud<pcl::Normal>)->makeShared();
+ another_normals_.reset (new pcl::PointCloud<pcl::Normal>);
normal_estimator.setInputCloud(another_cloud_);
normal_estimator.setKSearch(30);
normal_estimator.compute(*another_normals_);
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT (build AND BUILD_io AND BUILD_features))
return()
#include <pcl/io/vtk_io.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/mls.h>
+#include <pcl/common/common.h> // getMinMax3D
using namespace pcl;
using namespace pcl::io;
// EXPECT_NEAR ((*mls_normals)[10].curvature, 0.019003, 1e-3);
// EXPECT_EQ (mls_normals->size (), 457);
-
+ const float voxel_size = 0.005f;
+ const int num_dilations = 5;
mls_upsampling.setUpsamplingMethod (MovingLeastSquares<PointXYZ, PointNormal>::VOXEL_GRID_DILATION);
- mls_upsampling.setDilationIterations (5);
- mls_upsampling.setDilationVoxelSize (0.005f);
+ mls_upsampling.setDilationIterations (num_dilations);
+ mls_upsampling.setDilationVoxelSize (voxel_size);
mls_normals->clear ();
mls_upsampling.process (*mls_normals);
- EXPECT_NEAR ((*mls_normals)[10].x, -0.070005938410758972, 2e-3);
- EXPECT_NEAR ((*mls_normals)[10].y, 0.028887597844004631, 2e-3);
+ EXPECT_NEAR ((*mls_normals)[10].x, -0.086348414421081543, 2e-3);
+ EXPECT_NEAR ((*mls_normals)[10].y, 0.080920584499835968, 2e-3);
EXPECT_NEAR ((*mls_normals)[10].z, 0.01788550429046154, 2e-3);
EXPECT_NEAR ((*mls_normals)[10].curvature, 0.107273, 1e-1);
- EXPECT_NEAR (double (mls_normals->size ()), 29394, 2);
+ EXPECT_NEAR (double (mls_normals->size ()), 25483, 2);
+
+ // Check the boundary
+ Eigen::Vector4f original_min_pt, original_max_pt, min_pt, max_pt;
+ pcl::getMinMax3D(*cloud, original_min_pt, original_max_pt);
+ pcl::getMinMax3D(*mls_normals, min_pt, max_pt);
+ EXPECT_TRUE(
+ (original_min_pt.array() - (num_dilations + 3) * voxel_size <= min_pt.array())
+ .all());
+ EXPECT_TRUE(
+ (max_pt.array() <= original_max_pt.array() + (num_dilations + 4) * voxel_size)
+ .all());
}
#ifdef _OPENMP
list<ORROctree::Node*> inter_leaves;
// Run through all full leaves
- for ( std::vector<ORROctree::Node*>::const_iterator leaf1 = full_leaves.begin () ; leaf1 != full_leaves.end () ; ++leaf1 )
+ for ( const auto& leaf1 : full_leaves )
{
- const ORROctree::Node::Data* node_data1 = (*leaf1)->getData ();
+ const ORROctree::Node::Data* node_data1 = leaf1->getData ();
// Get all full leaves at the right distance to the current leaf
inter_leaves.clear ();
octree.getFullLeavesIntersectedBySphere (node_data1->getPoint (), pair_width, inter_leaves);
// Ensure that inter_leaves does not contain leaf1
- for ( list<ORROctree::Node*>::iterator leaf2 = inter_leaves.begin () ; leaf2 != inter_leaves.end () ; ++leaf2 )
+ for ( const auto& leaf2 : inter_leaves )
{
- EXPECT_NE(*leaf1, *leaf2);
+ EXPECT_NE(leaf1, leaf2);
}
}
}
set(DEFAULT ON)
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS})
if(NOT build)
return()
given_intrinsics (0, 2) = 320.f;
given_intrinsics (1, 2) = 240.f;
- float M_PIf = static_cast<float> (M_PI);
+ float M_PI_f = static_cast<float> (M_PI);
Eigen::Matrix4f given_extrinsics (Eigen::Matrix4f::Identity ());
- given_extrinsics.block<3, 3> (0, 0) = Eigen::AngleAxisf (30.f * M_PIf / 180.f, Eigen::Vector3f (1.f, 0.f, 0.f)).matrix ();
+ given_extrinsics.block<3, 3> (0, 0) = Eigen::AngleAxisf (30.f * M_PI_f / 180.f, Eigen::Vector3f (1.f, 0.f, 0.f)).matrix ();
given_extrinsics.block<3, 1> (0, 3) = Eigen::Vector3f (10.f, 15.f, 20.f);
visualizer.setCameraParameters (given_intrinsics, given_extrinsics);
Eigen::Vector3f trans (10.f, 2.f, 20.f);
visualizer.setCameraPosition (trans[0], trans[1], trans[2], trans[0] + 1., trans[1], trans[2], 0., 1., 0.);
viewer_pose = visualizer.getViewerPose ().matrix ();
- Eigen::Matrix3f expected_rotation = Eigen::AngleAxisf (M_PIf / 2.0f, Eigen::Vector3f (0.f, 1.f, 0.f)).matrix ();
+ Eigen::Matrix3f expected_rotation = Eigen::AngleAxisf (M_PI_f / 2.0f, Eigen::Vector3f (0.f, 1.f, 0.f)).matrix ();
for (std::size_t i = 0; i < 3; ++i)
for (std::size_t j = 0; j < 3; ++j)
EXPECT_NEAR (viewer_pose (i, j), expected_rotation (i, j), 1e-6);
set(REASON "")
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${SUBSYS_OPT_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} OPT_DEPS ${SUBSYS_OPT_DEPS})
if(NOT build)
return()
if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
target_link_libraries(pcl_obj2pcd VTK::FiltersCore)
+ elseif(${VTK_VERSION} VERSION_GREATER_EQUAL 8.0)
+ target_link_libraries(pcl_obj2pcd vtkFiltersCore)
endif()
PCL_ADD_EXECUTABLE(pcl_obj2ply COMPONENT ${SUBSYS_NAME} SOURCES obj2ply.cpp)
if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
target_link_libraries(pcl_vtk2pcd VTK::FiltersCore)
+ elseif(${VTK_VERSION} VERSION_GREATER_EQUAL 8.0)
+ target_link_libraries(pcl_vtk2pcd vtkFiltersCore)
endif()
if(BUILD_visualization)
+++ /dev/null
-/*
- * Software License Agreement (BSD License)
- *
- * Point Cloud Library (PCL) - www.pointclouds.org
- * Copyright (c) 2010-2011, Willow Garage, Inc.
- * Copyright (c) 2012-, Open Perception, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Willow Garage, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * $Id: io.h 5850 2012-06-06 14:04:59Z stfox88 $
- *
- */
-
-#pragma once
-
-#ifdef __GNUC__
-#pragma GCC system_header
-#endif
-
-#include <boost/date_time/gregorian/gregorian_types.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", cluster_indices.size ()); print_info (" clusters]\n");
output.reserve (cluster_indices.size ());
- for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
+ for (const auto& cluster : cluster_indices)
{
pcl::ExtractIndices<pcl::PCLPointCloud2> extract;
extract.setInputCloud (input);
- extract.setIndices (pcl::make_shared<const pcl::PointIndices> (*it));
+ extract.setIndices (pcl::make_shared<const pcl::PointIndices> (cluster));
pcl::PCLPointCloud2::Ptr out (new pcl::PCLPointCloud2);
extract.filter (*out);
output.push_back (out);
}
void
-compute (Cloud &cloud_a, Cloud &cloud_b)
+compute (const Cloud::ConstPtr &cloud_a, const Cloud::ConstPtr &cloud_b)
{
// Estimate
TicToc tt;
// compare A to B
pcl::search::KdTree<PointType> tree_b;
- tree_b.setInputCloud (cloud_b.makeShared ());
+ tree_b.setInputCloud (cloud_b);
float max_dist_a = -std::numeric_limits<float>::max ();
- for (const auto &point : cloud_a.points)
+ for (const auto &point : (*cloud_a))
{
pcl::Indices indices (1);
std::vector<float> sqr_distances (1);
// compare B to A
pcl::search::KdTree<PointType> tree_a;
- tree_a.setInputCloud (cloud_a.makeShared ());
+ tree_a.setInputCloud (cloud_a);
float max_dist_b = -std::numeric_limits<float>::max ();
- for (const auto &point : cloud_b.points)
+ for (const auto &point : (*cloud_b))
{
pcl::Indices indices (1);
std::vector<float> sqr_distances (1);
return (-1);
// Compute the Hausdorff distance
- compute (*cloud_a, *cloud_b);
+ compute (cloud_a, cloud_b);
}
/** @brief Main function\r
* @return Exit status */\r
int\r
-main (void)\r
+main ()\r
{\r
viewer_ptr.reset (new CloudViewer ("Ensenso 3D cloud viewer"));\r
ensenso_ptr.reset (new pcl::EnsensoGrabber);\r
if (distribution == "uniform")
{
CloudGenerator<pcl::PointXYZ, UniformGenerator<float> > generator;
- std::uint32_t seed = static_cast<std::uint32_t> (time (nullptr));
+ auto seed = static_cast<std::uint32_t> (time (nullptr));
UniformGenerator<float>::Parameters x_params (xmin, xmax, seed++);
generator.setParametersForX (x_params);
UniformGenerator<float>::Parameters y_params (ymin, ymax, seed++);
else if (distribution == "normal")
{
CloudGenerator<pcl::PointXYZ, NormalGenerator<float> > generator;
- std::uint32_t seed = static_cast<std::uint32_t> (time (nullptr));
+ auto seed = static_cast<std::uint32_t> (time (nullptr));
NormalGenerator<float>::Parameters x_params (xmean, xstddev, seed++);
generator.setParametersForX (x_params);
NormalGenerator<float>::Parameters y_params (ymean, ystddev, seed++);
batchProcess (const std::vector<std::string> &pcd_files, std::string &output_dir,
float resolution)
{
- std::vector<std::string> st;
for (const auto &pcd_file : pcd_files)
{
// Load the first file
#include <string>
#include <iostream>
-#include <fstream>
#include <vector>
using PointType = pcl::PointXYZ;
#include <string>
#include <iostream>
-#include <fstream>
#include <vector>
using PointType = pcl::PointXYZ;
void
mouse_callback (const pcl::visualization::MouseEvent& mouse_event, void* cookie)
{
- std::string* message = static_cast<std::string*> (cookie);
+ auto* message = static_cast<std::string*> (cookie);
if (mouse_event.getType() == pcl::visualization::MouseEvent::MouseButtonPress && mouse_event.getButton() == pcl::visualization::MouseEvent::LeftButton)
{
std::cout << (*message) << " :: " << mouse_event.getX () << " , " << mouse_event.getY () << std::endl;
batchProcess (const std::vector<std::string> &pcd_files, std::string &output_dir,
float radius)
{
- std::vector<std::string> st;
for (const auto &pcd_file : pcd_files)
{
// Load the first file
#include <pcl/io/pcd_io.h>
#include <pcl/io/vtk_lib_io.h>
#include <vtkVersion.h>
-#include <vtkPLYReader.h>
#include <vtkOBJReader.h>
#include <vtkTriangle.h>
#include <vtkTriangleFilter.h>
{
float r = static_cast<float> (uniform_deviate (rand ()) * totalArea);
- std::vector<double>::iterator low = std::lower_bound (cumulativeAreas->begin (), cumulativeAreas->end (), r);
+ auto low = std::lower_bound (cumulativeAreas->begin (), cumulativeAreas->end (), r);
vtkIdType el = vtkIdType (low - cumulativeAreas->begin ());
double A[3], B[3], C[3];
}
void
-compute (ConstCloudPtr &input, Cloud &output, float resolution, std::string method)
+compute (ConstCloudPtr &input, Cloud &output, float resolution, const std::string& method)
{
// Estimate
TicToc tt;
batchProcess (const std::vector<std::string> &pcd_files, std::string &output_dir,
float resolution, const std::string &method)
{
- std::vector<std::string> st;
for (const auto &pcd_file : pcd_files)
{
// Load the first file
#include <string>
#include <iostream>
-#include <fstream>
#include <vector>
using PointType = pcl::PointXYZ;
#include <string>
#include <iostream>
-#include <fstream>
#include <vector>
}
std::cout << argv[pcd_indices[i]] << " width: " << data->width << " height: " << data->height << std::endl;
- pcl::NormalDistributionsTransform<PointType, PointType> * ndt = new pcl::NormalDistributionsTransform<PointType, PointType>();
+ auto * ndt = new pcl::NormalDistributionsTransform<PointType, PointType>();
ndt->setMaximumIterations (iter);
ndt->setResolution (ndt_res);
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
+#include <vtkOBJReader.h> // for vtkOBJReader
+#include <vtkPolyDataNormals.h> // vtkPolyDataNormals
+
using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;
#include <pcl/console/parse.h>
#include <pcl/io/vtk_lib_io.h>
+#include <vtkOBJReader.h> // for vtkOBJReader
+#include <vtkPolyDataWriter.h> // for vtkPolyDataWriter
+
using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;
vtkIdType ids[2] = {0, 1};
// Insert the points and compute the lines
- for ( list<ObjRecRANSAC::OrientedPointPair>::const_iterator it = opps.begin () ; it != opps.end () ; ++it )
+ for ( const auto& opp : opps )
{
- vtk_opps_points->SetPoint (ids[0], it->p1_[0], it->p1_[1], it->p1_[2]);
- vtk_opps_points->SetPoint (ids[1], it->p2_[0], it->p2_[1], it->p2_[2]);
+ vtk_opps_points->SetPoint (ids[0], opp.p1_[0], opp.p1_[1], opp.p1_[2]);
+ vtk_opps_points->SetPoint (ids[1], opp.p2_[0], opp.p2_[1], opp.p2_[2]);
vtk_opps_lines->InsertNextCell (2, ids);
- vtk_normals->SetTuple3 (ids[0], it->n1_[0], it->n1_[1], it->n1_[2]);
- vtk_normals->SetTuple3 (ids[1], it->n2_[0], it->n2_[1], it->n2_[2]);
+ vtk_normals->SetTuple3 (ids[0], opp.n1_[0], opp.n1_[1], opp.n1_[2]);
+ vtk_normals->SetTuple3 (ids[1], opp.n2_[0], opp.n2_[1], opp.n2_[2]);
ids[0] += 2;
ids[1] += 2;
std::sort(accepted_hypotheses.begin (), accepted_hypotheses.end (), compareHypotheses);
// Show the hypotheses
- for ( std::vector<Hypothesis>::iterator acc_hypo = accepted_hypotheses.begin () ; i < params->num_hypotheses_to_show_ && acc_hypo != accepted_hypotheses.end () ; ++i, ++acc_hypo )
+ for ( auto acc_hypo = accepted_hypotheses.begin () ; i < params->num_hypotheses_to_show_ && acc_hypo != accepted_hypotheses.end () ; ++i, ++acc_hypo )
{
// Visualize the orientation as a tripod
char frame_name[128];
void
keyboardCB (const pcl::visualization::KeyboardEvent &event, void* params_void)
{
- CallbackParameters* params = static_cast<CallbackParameters*> (params_void);
+ auto* params = static_cast<CallbackParameters*> (params_void);
if (event.getKeyCode () == 13 /*enter*/ && event.keyUp ())
update (params);
// Switch models visibility
params->show_models_ = !params->show_models_;
- for ( std::list<vtkActor*>::iterator it = params->model_actors_.begin () ; it != params->model_actors_.end () ; ++it )
+ for ( auto it = params->model_actors_.begin () ; it != params->model_actors_.end () ; ++it )
(*it)->SetVisibility (static_cast<int> (params->show_models_));
params->viz_.getRenderWindow ()->Render ();
#include <vtkHedgeHog.h>
#include <cstdio>
#include <thread>
-#include <vector>
using namespace std::chrono_literals;
using namespace pcl;
for (int i = 0 ; i < num_cells ; ++i )
{
// Make sure that we get only point pairs belonging to 'model'
- ModelLibrary::HashTableCell::const_iterator res = cells[i].find (model);
+ auto res = cells[i].find (model);
if ( res == cells[i].end () )
continue;
void keyboardCB (const pcl::visualization::KeyboardEvent &event, void* params_void)
{
- CallbackParameters* params = static_cast<CallbackParameters*> (params_void);
+ auto* params = static_cast<CallbackParameters*> (params_void);
if (event.getKeySym () == "Left" && event.keyUp ())
{
octree.build (*points_in, voxel_size);
// Get the first full leaf in the octree (arbitrary order)
- std::vector<ORROctree::Node*>::iterator leaf = octree.getFullLeaves ().begin ();
+ auto leaf = octree.getFullLeaves ().begin ();
// Get the average points in every full octree leaf
octree.getFullLeavesPoints (*points_out);
}
// Just print the leaf size
- std::vector<ORROctree::Node*>::iterator first_leaf = octree->getFullLeaves ().begin ();
+ auto first_leaf = octree->getFullLeaves ().begin ();
if ( first_leaf != octree->getFullLeaves ().end () )
printf("leaf size = %f\n", (*first_leaf)->getBounds ()[1] - (*first_leaf)->getBounds ()[0]);
#include <vtkCubeSource.h>
#include <vtkPointData.h>
#include <vector>
-#include <list>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vtkRenderWindow.h>
#include <vtkTransform.h>
#include <cstdio>
-#include <vector>
#include <list>
#include <thread>
int i = 0;
// Show the hypotheses
- for ( std::list<ObjRecRANSAC::Output>::iterator it = rec_output.begin () ; it != rec_output.end () ; ++it, ++i )
+ for ( auto it = rec_output.begin () ; it != rec_output.end () ; ++it, ++i )
{
std::cout << it->object_name_ << " has a confidence value of " << it->match_confidence_ << std::endl;
// If the asked depth is the depth of the octree, retrieve the centroid at this LeafNode
if (octree.getTreeDepth () == (unsigned int) depth)
{
- pcl::octree::OctreePointCloudVoxelCentroid<pcl::PointXYZ>::LeafNode* container = static_cast<pcl::octree::OctreePointCloudVoxelCentroid<pcl::PointXYZ>::LeafNode*> (tree_it.getCurrentOctreeNode ());
+ auto* container = dynamic_cast<pcl::octree::OctreePointCloudVoxelCentroid<pcl::PointXYZ>::LeafNode*> (tree_it.getCurrentOctreeNode ());
container->getContainer ().getCentroid (pt_centroid);
}
// Retrieve every centroid under the current BranchNode
pcl::octree::OctreeKey dummy_key;
pcl::PointCloud<pcl::PointXYZ>::VectorType voxelCentroids;
- octree.getVoxelCentroidsRecursive (static_cast<pcl::octree::OctreePointCloudVoxelCentroid<pcl::PointXYZ>::BranchNode*> (*tree_it), dummy_key, voxelCentroids);
+ octree.getVoxelCentroidsRecursive (dynamic_cast<pcl::octree::OctreePointCloudVoxelCentroid<pcl::PointXYZ>::BranchNode*> (*tree_it), dummy_key, voxelCentroids);
// Iterate over the leafs to compute the centroid of all of them
pcl::CentroidPoint<pcl::PointXYZ> centroid;
#include <pcl/point_types.h>
#include <pcl/io/oni_grabber.h>
#include <pcl/io/pcd_io.h>
-#include <vector>
using namespace pcl;
using namespace pcl::console;
return (-1);
}
- pcl::ONIGrabber* grabber = new pcl::ONIGrabber (argv[1], false, false);
+ auto* grabber = new pcl::ONIGrabber (argv[1], false, false);
std::function<void (const CloudConstPtr&) > f = [] (const CloudConstPtr& cloud) { cloud_cb (cloud); };
boost::signals2::connection c = grabber->registerCallback (f);
}
if (image->getEncoding () == pcl::io::openni2::Image::RGB)
- image_viewer_->addRGBImage ( (const unsigned char*)image->getData (), image->getWidth (), image->getHeight ());
+ image_viewer_->addRGBImage ( reinterpret_cast<const unsigned char*>(image->getData ()), image->getWidth (), image->getHeight ());
else
image_viewer_->addRGBImage (rgb_data_, image->getWidth (), image->getHeight ());
image_viewer_->spinOnce ();
class Buffer
{
public:
- Buffer () {}
+ Buffer () = default;
+ Buffer (const Buffer&) = delete; // Disabled copy constructor
+ Buffer& operator =(const Buffer&) = delete; // Disabled assignment operator
bool
pushBack (Frame::ConstPtr frame)
}
private:
- Buffer (const Buffer&) = delete; // Disabled copy constructor
- Buffer& operator =(const Buffer&) = delete; // Disabled assignment operator
-
std::mutex bmutex_;
std::condition_variable buff_empty_;
boost::circular_buffer<Frame::ConstPtr> buffer_;
&rgb_data[0]);
}
else
- memcpy (&rgb_data[0],
- frame->image->getMetaData ().Data (),
+ memcpy (&rgb_data[0],
+ frame->image->getMetaData ().Data (),
rgb_data.size ());
image_viewer_->addRGBImage (reinterpret_cast<unsigned char*> (&rgb_data[0]),
{
std::cout << std::endl << "Supported image modes for device: " << device->getVendorName () << " , " << device->getProductName () << std::endl;
modes = grabber.getAvailableImageModes ();
- for (std::vector<std::pair<int, XnMapOutputMode> >::const_iterator it = modes.begin (); it != modes.end (); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
if (device->hasDepthStream ())
{
std::cout << std::endl << "Supported depth modes for device: " << device->getVendorName () << " , " << device->getProductName () << std::endl;
modes = grabber.getAvailableDepthModes ();
- for (std::vector<std::pair<int, XnMapOutputMode> >::const_iterator it = modes.begin (); it != modes.end (); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
}
}
{
std::cout << std::endl << "Supported image modes for device: " << device->getVendorName () << " , " << device->getProductName () << std::endl;
modes = grabber.getAvailableImageModes ();
- for (std::vector<std::pair<int, XnMapOutputMode> >::const_iterator it = modes.begin (); it != modes.end (); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
}
}
auto device = grabber.getDevice();
std::cout << "Supported depth modes for device: " << device->getVendorName() << " , " << device->getProductName() << std::endl;
std::vector<std::pair<int, XnMapOutputMode > > modes = grabber.getAvailableDepthModes();
- for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin(); it != modes.end(); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
if (device->hasImageStream ())
{
std::cout << std::endl << "Supported image modes for device: " << device->getVendorName() << " , " << device->getProductName() << std::endl;
modes = grabber.getAvailableImageModes();
- for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin(); it != modes.end(); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
}
}
auto device = grabber.getDevice();
std::cout << "Supported depth modes for device: " << device->getVendorName() << " , " << device->getProductName() << std::endl;
std::vector<std::pair<int, XnMapOutputMode > > modes = grabber.getAvailableDepthModes();
- for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin(); it != modes.end(); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
if (device->hasImageStream ())
{
std::cout << std::endl << "Supported image modes for device: " << device->getVendorName() << " , " << device->getProductName() << std::endl;
modes = grabber.getAvailableImageModes();
- for (std::vector<std::pair<int, XnMapOutputMode > >::const_iterator it = modes.begin(); it != modes.end(); ++it)
+ for (const auto& mode : modes)
{
- std::cout << it->first << " = " << it->second.nXRes << " x " << it->second.nYRes << " @ " << it->second.nFPS << std::endl;
+ std::cout << mode.first << " = " << mode.second.nXRes << " x " << mode.second.nYRes << " @ " << mode.second.nFPS << std::endl;
}
}
}
void
compute (const pcl::PCLPointCloud2::ConstPtr &input, pcl::PCLPointCloud2 &output,
- std::string method,
+ const std::string& method,
int min_pts, double radius,
int mean_k, double std_dev_mul, bool negative, bool keep_organized)
{
batchProcess (const std::vector<std::string> &pcd_files, std::string &output_dir,
const std::string &field_name, float min, float max, bool inside, bool keep_organized)
{
- std::vector<std::string> st;
for (const auto &pcd_file : pcd_files)
{
// Load the first file
void
mouse_callback (const pcl::visualization::MouseEvent& mouse_event, void* cookie)
{
- std::string* message = static_cast<std::string*> (cookie);
+ auto* message = static_cast<std::string*> (cookie);
if (mouse_event.getType() == pcl::visualization::MouseEvent::MouseButtonPress && mouse_event.getButton() == pcl::visualization::MouseEvent::LeftButton)
{
std::cout << (*message) << " :: " << mouse_event.getX () << " , " << mouse_event.getY () << std::endl;
// PCL
#include <pcl/common/common.h>
#include <pcl/io/pcd_io.h>
-#include <cfloat>
+#include <limits>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/image_viewer.h>
#include <pcl/visualization/histogram_visualizer.h>
bool
isMultiDimensionalFeatureField (const pcl::PCLPointField &field)
{
- if (field.count > 1)
- return (true);
- return (false);
+ return (field.count > 1 && field.name != "_"); // check for padding fields "_"
}
bool
print_info ("\n");
print_info (" -use_point_picking = enable the usage of picking points on screen (default "); print_value ("disabled"); print_info (")\n");
print_info ("\n");
+ print_info (" -use_area_picking = enable the usage of area picking points on screen (default "); print_value("disabled"); print_info(")\n");
+ print_info ("\n");
print_info (" -optimal_label_colors = maps existing labels to the optimal sequential glasbey colors, label_ids will not be mapped to fixed colors (default "); print_value ("disabled"); print_info (")\n");
print_info ("\n");
+ print_info (" -edl = Enable Eye-Dome Lighting rendering, to improve depth perception. (default: "); print_value ("disabled"); print_info (")\n");
+ print_info ("\n");
print_info ("\n(Note: for multiple .pcd files, provide multiple -{fc,ps,opaque,position,orientation} parameters; they will be automatically assigned to the right file)\n");
}
pcl::PCLPointCloud2::Ptr cloud;
pcl::PointCloud<pcl::PointXYZ>::Ptr xyzcloud;
+void
+area_callback(const pcl::visualization::AreaPickingEvent& event, void* /*cookie*/)
+{
+ const auto names = event.getCloudNames();
+
+ for (const std::string& name : names) {
+ const pcl::Indices indices = event.getPointsIndices(name);
+
+ PCL_INFO("Picked %d points from %s \n", indices.size(), name.c_str());
+ }
+}
+
void
pp_callback (const pcl::visualization::PointPickingEvent& event, void* cookie)
{
if (use_vbos)
print_highlight ("Vertex Buffer Object (VBO) visualization enabled.\n");
+ bool useEDLRendering = false;
+ pcl::console::parse_argument(argc, argv, "-edl", useEDLRendering);
+ if (useEDLRendering)
+ print_highlight("EDL visualization enabled.\n");
+
bool use_pp = pcl::console::find_switch (argc, argv, "-use_point_picking");
if (use_pp)
print_highlight ("Point picking enabled.\n");
+ bool use_ap = pcl::console::find_switch(argc, argv, "-use_area_picking");
+ if (use_ap)
+ print_highlight("Area picking enabled. \n");
+
bool use_optimal_l_colors = pcl::console::find_switch (argc, argv, "-optimal_label_colors");
if (use_optimal_l_colors)
print_highlight ("Optimal glasbey colors are being assigned to existing labels.\nNote: No static mapping between label ids and colors\n");
{
print_highlight ("Multi-viewport rendering enabled.\n");
- int y_s = static_cast<int>(std::floor (sqrt (static_cast<float>(p_file_indices.size () + vtk_file_indices.size ()))));
+ int y_s = static_cast<int>(std::floor (std::sqrt (static_cast<float>(p_file_indices.size () + vtk_file_indices.size ()))));
x_s = y_s + static_cast<int>(std::ceil (double (p_file_indices.size () + vtk_file_indices.size ()) / double (y_s) - y_s));
if (!p_file_indices.empty ())
// Create the PCLPlotter object
pcl::visualization::PCLPlotter::Ptr ph;
// Using min_p, max_p to set the global Y min/max range for the histogram
- float min_p = FLT_MAX; float max_p = -FLT_MAX;
+ float min_p = std::numeric_limits<float>::max();
+ float max_p = std::numeric_limits<float>::lowest();
int k = 0, l = 0, viewport = 0;
// Load the data files
if (!p)
p.reset (new pcl::visualization::PCLVisualizer (argc, argv, "PCD viewer"));
+ if (useEDLRendering)
+ p->enableEDLRendering();
+
// Multiview enabled?
if (mview)
{
if (use_pp) // Only enable the point picking callback if the command line parameter is enabled
p->registerPointPickingCallback (&pp_callback, static_cast<void*> (&cloud));
+ if (use_ap)
+ p->registerAreaPickingCallback(&area_callback);
+
+ if (useEDLRendering)
+ p->enableEDLRendering();
+
// Set whether or not we should be using the vtkVertexBufferObjectMapper
p->setUseVbos (use_vbos);
boost::uuids::random_generator gen;
boost::uuids::uuid uuid = gen();
std::vector<char> uuid_data(uuid.size());
- std::copy(uuid.begin(), uuid.end(), uuid_data.begin());
+ std::copy(uuid.cbegin(), uuid.cend(), uuid_data.begin());
segment.info.uid(uuid_data);
// The filename can be nice to know.
segment.info.filename(filename_);
#include <pcl/console/parse.h>
#include <pcl/io/vtk_lib_io.h>
+#include <vtkPLYReader.h> // for vtkPLYReader
+#include <vtkPolyDataWriter.h> // for vtkPolyDataWriter
+
using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;
}
// Retrieve the entries from the image data and copy them into the output RGB cloud
- double* pixel = new double [4];
- memset (pixel, 0, sizeof (double) * 4);
+ double* pixel = new double [4]{0.0};
float depth;
std::string intensity_type;
int
batchProcess (const std::vector<std::string> &pcd_files, std::string &output_dir, int max_window_size, float slope, float max_distance, float initial_distance, float cell_size, float base, bool exponential, bool approximate)
{
- std::vector<std::string> st;
for (const auto &pcd_file : pcd_files)
{
// Load the first file
batchProcess (const std::vector<std::string> &pcd_files, std::string &output_dir,
float radius, bool inside, bool keep_organized)
{
- std::vector<std::string> st;
for (const auto &pcd_file : pcd_files)
{
// Load the first file
// /////////////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////////////////////////////
- pcl::PointCloud<pcl::PointXYZ> inputCloud;
- pcl::PointCloud<pcl::PointXYZ> targetCloud;
+ pcl::PointCloud<pcl::PointXYZ>::Ptr inputCloud(new pcl::PointCloud<pcl::PointXYZ>);
+ pcl::PointCloud<pcl::PointXYZ>::Ptr targetCloud(new pcl::PointCloud<pcl::PointXYZ>);
- if (pcl::io::loadPCDFile<pcl::PointXYZ> (argv[1], inputCloud) == -1) //* load the file
+ if (pcl::io::loadPCDFile<pcl::PointXYZ> (argv[1], *inputCloud) == -1) //* load the file
{
PCL_ERROR ("Couldn't read the first .pcd file \n");
return (-1);
}
- if (pcl::io::loadPCDFile<pcl::PointXYZ> (argv[2], targetCloud) == -1) //* load the file
+ if (pcl::io::loadPCDFile<pcl::PointXYZ> (argv[2], *targetCloud) == -1) //* load the file
{
PCL_ERROR ("Couldn't read the second .pcd file \n");
return (-1);
// sor.setLeafSize (0.4, 0.4, 0.4);
// sor.setLeafSize (0.5, 0.5, 0.5);
- sor.setInputCloud (inputCloud.makeShared());
- std::cout<<"\n inputCloud.size()="<<inputCloud.size()<<std::endl;
+ sor.setInputCloud (inputCloud);
+ std::cout<<"\n inputCloud->size()="<<inputCloud->size()<<std::endl;
sor.filter (inputCloudFiltered);
std::cout<<"\n inputCloudFiltered.size()="<<inputCloudFiltered.size()<<std::endl;
- sor.setInputCloud (targetCloud.makeShared());
- std::cout<<"\n targetCloud.size()="<<targetCloud.size()<<std::endl;
+ sor.setInputCloud (targetCloud);
+ std::cout<<"\n targetCloud->size()="<<targetCloud->size()<<std::endl;
sor.filter (targetCloudFiltered);
std::cout<<"\n targetCloudFiltered.size()="<<targetCloudFiltered.size()<<std::endl;
// /////////////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////////////////////////////////////////////////////////////////////////////////////////
pcl::RegistrationVisualizer<pcl::PointXYZ, pcl::PointXYZ> registrationVisualizer;
- registrationVisualizer.startDisplay();
-
registrationVisualizer.setMaximumDisplayedCorrespondences (100);
// /////////////////////////////////////////////////////////////////////////////////////////////////////
// Register the registration algorithm to the RegistrationVisualizer
registrationVisualizer.setRegistration (icp);
+ registrationVisualizer.startDisplay();
+
// Start registration process
icp.align (source_aligned);
std::cout << "has converged:" << icp.hasConverged () << " score: " << icp.getFitnessScore () << std::endl;
std::cout << icp.getFinalTransformation () << std::endl;
+
+ registrationVisualizer.stopDisplay();
// ///////////////////////////////////////////////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////////////////////////////////////////////////
//
// ///////////////////////////////////////////////////////////////////////////////////////////////////
+ return 0;
}
int
batchProcess (const std::vector<std::string> &pcd_files, std::string &output_dir, int max_it, double thresh, bool negative)
{
- std::vector<std::string> st;
for (const auto &pcd_file : pcd_files)
{
// Load the first file
val = static_cast<T> (val * static_cast<T> (multiplier));
memcpy (&cloud.data[field_offset], &val, sizeof (T));
}
+template <> void
+multiply<bool> (pcl::PCLPointCloud2 &cloud, int field_offset, double multiplier)
+{
+ if (multiplier != static_cast<bool>(multiplier)) {
+ PCL_WARN("Invalid value for scaling a boolean: %f. Only 0 or 1 is valid", multiplier);
+ return;
+ }
+
+ bool val;
+ memcpy (&val, &cloud.data[field_offset], sizeof (bool));
+ val = val && static_cast<bool> (multiplier);
+ memcpy (&cloud.data[field_offset], &val, sizeof (bool));
+}
void
scaleInPlace (pcl::PCLPointCloud2 &cloud, double* multiplier)
int y_idx = pcl::getFieldIndex (cloud, "y");
int z_idx = pcl::getFieldIndex (cloud, "z");
Eigen::Array3i xyz_offset (cloud.fields[x_idx].offset, cloud.fields[y_idx].offset, cloud.fields[z_idx].offset);
-
+
+ if (cloud.fields[x_idx].datatype == pcl::PCLPointField::BOOL) {
+ PCL_WARN("Datatype of point was deduced as boolean. Please check, there might be "
+ "an error somewhere");
+ }
+
for (uindex_t cp = 0; cp < cloud.width * cloud.height; ++cp)
{
// Assume all 3 fields are the same (XYZ)
assert ((cloud.fields[x_idx].datatype == cloud.fields[y_idx].datatype));
assert ((cloud.fields[x_idx].datatype == cloud.fields[z_idx].datatype));
+#define MULTIPLY(CASE_LABEL) \
+ case CASE_LABEL: { \
+ for (int i = 0; i < 3; ++i) \
+ multiply<pcl::traits::asType_t<CASE_LABEL>>( \
+ cloud, xyz_offset[i], multiplier[i]); \
+ break; \
+ }
switch (cloud.fields[x_idx].datatype)
{
- case pcl::PCLPointField::INT8:
- for (int i = 0; i < 3; ++i) multiply<std::int8_t> (cloud, xyz_offset[i], multiplier[i]);
- break;
- case pcl::PCLPointField::UINT8:
- for (int i = 0; i < 3; ++i) multiply<std::uint8_t> (cloud, xyz_offset[i], multiplier[i]);
- break;
- case pcl::PCLPointField::INT16:
- for (int i = 0; i < 3; ++i) multiply<std::int16_t> (cloud, xyz_offset[i], multiplier[i]);
- break;
- case pcl::PCLPointField::UINT16:
- for (int i = 0; i < 3; ++i) multiply<std::uint16_t> (cloud, xyz_offset[i], multiplier[i]);
- break;
- case pcl::PCLPointField::INT32:
- for (int i = 0; i < 3; ++i) multiply<std::int32_t> (cloud, xyz_offset[i], multiplier[i]);
- break;
- case pcl::PCLPointField::UINT32:
- for (int i = 0; i < 3; ++i) multiply<std::uint32_t> (cloud, xyz_offset[i], multiplier[i]);
- break;
- case pcl::PCLPointField::FLOAT32:
- for (int i = 0; i < 3; ++i) multiply<float> (cloud, xyz_offset[i], multiplier[i]);
- break;
- case pcl::PCLPointField::FLOAT64:
- for (int i = 0; i < 3; ++i) multiply<double> (cloud, xyz_offset[i], multiplier[i]);
- break;
+ MULTIPLY(pcl::PCLPointField::BOOL)
+ MULTIPLY(pcl::PCLPointField::INT8)
+ MULTIPLY(pcl::PCLPointField::UINT8)
+ MULTIPLY(pcl::PCLPointField::INT16)
+ MULTIPLY(pcl::PCLPointField::UINT16)
+ MULTIPLY(pcl::PCLPointField::INT32)
+ MULTIPLY(pcl::PCLPointField::UINT32)
+ MULTIPLY(pcl::PCLPointField::INT64)
+ MULTIPLY(pcl::PCLPointField::UINT64)
+ MULTIPLY(pcl::PCLPointField::FLOAT32)
+ MULTIPLY(pcl::PCLPointField::FLOAT64)
}
+#undef MULTIPLY
xyz_offset += cloud.point_step;
}
}
#include <vtkGeneralTransform.h>
#include <vtkPlatonicSolidSource.h>
+#include <vtkPolyDataReader.h> // for vtkPolyDataReader
+#include <vtkPLYReader.h> // for vtkPLYReader
#include <vtkLoopSubdivisionFilter.h>
#include <vtkCellLocator.h>
#include <vtkMath.h>
VLPGrabber grabber (pcapFile);
- PointCloudColorHandlerGenericField<PointXYZI> *color_handler = new PointCloudColorHandlerGenericField<PointXYZI> ("intensity");
+ auto *color_handler = new PointCloudColorHandlerGenericField<PointXYZI> ("intensity");
SimpleVLPViewer<PointXYZI> v (grabber, color_handler);
v.run ();
#include <pcl/console/parse.h>
#include <pcl/console/time.h>
+#include <vtkPolyDataNormals.h> // for vtkPolyDataNormals
+#include <vtkPolyDataReader.h> // for vtkPolyDataReader
+
using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;
#include <pcl/console/parse.h>
#include <pcl/io/vtk_lib_io.h>
+#include <vtkPolyDataReader.h> // for vtkPolyDataReader
+#include <vtkPLYWriter.h> // for vtkPLYWriter
+
using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;
set(build TRUE)
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON)
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS})
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS})
PCL_ADD_DOC("${SUBSYS_NAME}")
public:
/** \brief empty constructor */
- PointCoherence() {}
+ PointCoherence() = default;
/** \brief empty distructor */
- virtual ~PointCoherence() {}
+ virtual ~PointCoherence() = default;
/** \brief compute coherence from the source point to the target point.
* \param source instance of source point.
PointCloudCoherence() : target_input_(), point_coherences_() {}
/** \brief Destructor. */
- virtual ~PointCloudCoherence() {}
+ virtual ~PointCloudCoherence() = default;
/** \brief compute coherence between two pointclouds. */
inline void
Eigen::Vector4f n = source.getNormalVector4fMap();
Eigen::Vector4f n_dash = target.getNormalVector4fMap();
if (n.norm() <= 1e-5 || n_dash.norm() <= 1e-5) {
- PCL_ERROR("norm might be ZERO!\n");
- std::cout << "source: " << source << std::endl;
- std::cout << "target: " << target << std::endl;
- exit(1);
+ PCL_ERROR_STREAM("[NormalCoherence::computeCoherence] normal of source and/or "
+ "target is zero! source: "
+ << source << "target: " << target << std::endl);
return 0.0;
}
n.normalize();
{
/* generate an alias table, a and q */
std::vector<int> HL(particles->size());
- std::vector<int>::iterator H = HL.begin();
- std::vector<int>::iterator L = HL.end() - 1;
+ auto H = HL.begin();
+ auto L = HL.end() - 1;
const auto num = particles->size();
for (std::size_t i = 0; i < num; i++)
q[i] = (*particles)[i].weight * static_cast<float>(num);
const float* srow0 = src_ptr + (y > 0 ? y - 1 : height > 1 ? 1 : 0) * width;
const float* srow1 = src_ptr + y * width;
const float* srow2 =
- src_ptr + (y < height - 1 ? y + 1 : height > 1 ? height - 2 : 0) * width;
+ src_ptr + (y < height - 1 ? y + 1 : (height > 1 ? height - 2 : 0)) * width;
float* grad_x_row = &(grad_x[y * width]);
float* grad_y_row = &(grad_y[y * width]);
/** \brief resampling phase of particle filter method. sampling the particles
* according to the weights calculated in weight method. in particular, "sample with
- * replacement" is archieved by walker's alias method.
+ * replacement" is achieved by walker's alias method.
*/
void
resample() override;
}
/** Destructor */
- ~PyramidalKLTTracker() {}
+ ~PyramidalKLTTracker() override = default;
/** \brief Set the number of pyramid levels
* \param levels desired number of pyramid levels
endif()
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}")
-PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} EXT_DEPS vtk OPT_DEPS openni openni2 ensenso davidSDK dssdk rssdk)
+PCL_SUBSYS_DEPEND(build NAME ${SUBSYS_NAME} DEPS ${SUBSYS_DEPS} EXT_DEPS vtk OPT_DEPS openni openni2 ensenso davidSDK dssdk rssdk)
if(ANDROID)
set(build FALSE)
src/pcl_plotter.cpp
)
-if(VTK_RENDERING_BACKEND_OPENGL_VERSION VERSION_LESS 2)
- list(APPEND srcs
- "src/vtk/vtkVertexBufferObject.cxx"
- "src/vtk/vtkVertexBufferObjectMapper.cxx"
- )
-
- # Code in this module may use deprecated declarations when using OpenGLv1
- # Add the GCC exclusive rules for -Werror only for OpenGLv1 compile to avoid build interruption
- if(CMAKE_COMPILER_IS_GNUCXX)
- add_compile_options("-Wno-error=deprecated-declarations")
- endif()
+if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0 AND UNIX AND NOT ANDROID AND NOT APPLE AND NOT APPLE_IOS)
+ list(APPEND srcs "src/vtk/vtkFixedXRenderWindowInteractor.cxx")
endif()
if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
"include/pcl/${SUBSYS_NAME}/vtk/pcl_vtk_compatibility.h"
)
-if(VTK_RENDERING_BACKEND_OPENGL_VERSION VERSION_LESS 2)
- list(APPEND vtk_incs
- "include/pcl/${SUBSYS_NAME}/vtk/vtkVertexBufferObject.h"
- "include/pcl/${SUBSYS_NAME}/vtk/vtkVertexBufferObjectMapper.h"
- )
+if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0 AND UNIX AND NOT ANDROID AND NOT APPLE AND NOT APPLE_IOS)
+ list(APPEND vtk_incs "include/pcl/${SUBSYS_NAME}/vtk/vtkFixedXRenderWindowInteractor.h")
endif()
if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0)
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()
+ if(${VTK_VERSION} VERSION_GREATER_EQUAL 8.0)
+ target_link_libraries("${LIB_NAME}" vtkCommonColor vtkCommonComputationalGeometry)
+ 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.
#TODO: Update when CMAKE 3.10 is available
if(NOT (${VTK_VERSION} VERSION_LESS 9.0))
vtk_module_autoinit(TARGETS "${LIB_NAME}"
- MODULES VTK::RenderingOpenGL2
+ MODULES VTK::RenderingContextOpenGL2
+ VTK::RenderingOpenGL2
VTK::RenderingFreeType)
endif()
#include <pcl/pcl_macros.h>
+#include <map>
+
namespace pcl
{
namespace visualization
class PCL_EXPORTS AreaPickingEvent
{
public:
- AreaPickingEvent (int nb_points, const pcl::Indices& indices)
- : nb_points_ (nb_points)
- , indices_ (indices)
+ AreaPickingEvent (std::map<std::string, pcl::Indices> cloud_indices)
+ : cloud_indices_ (std::move(cloud_indices))
{}
- /** \brief For situations where a whole are is selected, return the points indices.
+ PCL_DEPRECATED(1,16,"This constructor is deprecated!")
+ AreaPickingEvent(int /*nb_points*/, const pcl::Indices& indices)
+ : AreaPickingEvent ({{"",indices}}) {}
+
+ /** \brief For situations where a whole area is selected, return the points indices.
* \param[out] indices indices of the points under the area selected by user.
* \return true, if the area selected by the user contains points, false otherwise
*/
inline bool
getPointsIndices (pcl::Indices& indices) const
{
- if (nb_points_ <= 0)
+ if (cloud_indices_.empty())
return (false);
- indices = indices_;
+
+ for (const auto& i : cloud_indices_)
+ indices.insert(indices.cend (), i.second.cbegin (), i.second.cend ());
+
return (true);
}
+ /** \brief For situations where a whole area is selected, return the names
+ * of the selected point clouds.
+ * \return The names of selected point clouds
+ */
+ inline std::vector<std::string>
+ getCloudNames () const
+ {
+ std::vector<std::string> names;
+ for (const auto& i : cloud_indices_)
+ names.push_back (i.first);
+ return names;
+ }
+ /** \brief For situations where a whole area is selected, return the points indices
+ * for a given point cloud
+ * \param[in] name of selected clouds.
+ * \return The indices for the selected cloud.
+ */
+ inline Indices
+ getPointsIndices (const std::string& name) const
+ {
+ const auto cloud = cloud_indices_.find (name);
+ if(cloud == cloud_indices_.cend ())
+ return Indices ();
+
+ return cloud->second;
+ }
private:
- int nb_points_;
- pcl::Indices indices_;
+ std::map<std::string, pcl::Indices> cloud_indices_;
};
} //namespace visualization
} //namespace pcl
#if defined __GNUC__
# pragma GCC system_header
#endif
+PCL_DEPRECATED_HEADER(1, 16, "Please include the needed boost headers directly.")
#include <boost/shared_array.hpp>
#define BOOST_PARAMETER_MAX_ARITY 7
#pragma once
#include <pcl/visualization/pcl_visualizer.h> //pcl vis
-#include <boost/scoped_ptr.hpp> // scoped_ptr for pre-C++11
#include <string>
+#include <memory>
namespace pcl
{
private:
/** \brief Private implementation. */
struct CloudViewer_impl;
- boost::scoped_ptr<CloudViewer_impl> impl_;
+ std::unique_ptr<CloudViewer_impl> impl_;
boost::signals2::connection
registerMouseCallback (std::function<void (const pcl::visualization::MouseEvent&)>);
public:
CloudActor () : color_handler_index_ (0), geometry_handler_index_ (0) {}
- virtual ~CloudActor ()
- {
- geometry_handlers.clear ();
- color_handlers.clear ();
- }
+ virtual ~CloudActor () = default;
/** \brief The actor holding the data to render. */
vtkSmartPointer<vtkLODActor> actor;
/** \brief PCL histogram visualizer constructor. */
PCLHistogramVisualizer ();
- virtual ~PCLHistogramVisualizer () {}
+ virtual ~PCLHistogramVisualizer () = default;
/** \brief Spin once method. Calls the interactor and updates the screen once.
* \param[in] time - How long (in ms) should the visualization loop be allowed to run.
*/
/** \brief Internal structure describing a layer. */
struct Layer
{
- Layer () {}
+ Layer () = default;
vtkSmartPointer<vtkContextActor> actor;
std::string layer_name;
};
const pcl::PointCloud<PointT> &cloud, int hsize,
const std::string &id, int win_width, int win_height)
{
- RenWinInteractMap::iterator am_it = wins_.find (id);
+ auto am_it = wins_.find (id);
if (am_it != wins_.end ())
{
PCL_WARN ("[addFeatureHistogram] A window with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
return (false);
}
- RenWinInteractMap::iterator am_it = wins_.find (id);
+ auto am_it = wins_.find (id);
if (am_it != wins_.end ())
{
PCL_WARN ("[addFeatureHistogram] A window with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
const pcl::PointCloud<PointT> &cloud, int hsize,
const std::string &id)
{
- RenWinInteractMap::iterator am_it = wins_.find (id);
+ auto am_it = wins_.find (id);
if (am_it == wins_.end ())
{
PCL_WARN ("[updateFeatureHistogram] A window with id <%s> does not exists!.\n", id.c_str ());
return (false);
}
- RenWinInteractMap::iterator am_it = wins_.find (id);
+ auto am_it = wins_.find (id);
if (am_it == wins_.end ())
{
PCL_WARN ("[updateFeatureHistogram] A window with id <%s> does not exists!.\n", id.c_str ());
return (false);
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addMask] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
return (false);
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addPlanarPolygon] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
return (false);
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
return (false);
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID'=%s' found. Creating new one...\n", layer_id.c_str ());
}
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addCorrespondences] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
}
else
{
- memcpy (&data_[j], 0, source_img.width * 3);
+ std::fill_n(&data_[j], source_img.width * 3, 0);
j += source_img.width * 3;
}
}
else
{
- memcpy (&data_[j], 0, target_img.width * 3);
+ std::fill_n(&data_[j], target_img.width * 3, 0);
j += target_img.width * 3;
}
}
{
double r, g, b;
getRandomColors (r, g, b);
- unsigned char u_r = static_cast<unsigned char> (255.0 * r);
- unsigned char u_g = static_cast<unsigned char> (255.0 * g);
- unsigned char u_b = static_cast<unsigned char> (255.0 * b);
+ auto u_r = static_cast<unsigned char> (255.0 * r);
+ auto u_g = static_cast<unsigned char> (255.0 * g);
+ auto u_b = static_cast<unsigned char> (255.0 * b);
vtkSmartPointer<context_items::Circle> query_circle = vtkSmartPointer<context_items::Circle>::New ();
query_circle->setColors (u_r, u_g, u_b);
vtkSmartPointer<context_items::Circle> match_circle = vtkSmartPointer<context_items::Circle>::New ();
{
// Here we're just pushing the handlers onto the queue. If needed, something fancier could
// be done such as checking if a specific handler already exists, etc.
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
am_it->second.geometry_handlers.push_back (geometry_handler);
return (true);
}
const std::string &id, int viewport)
{
// Check to see if this entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it != cloud_actor_map_->end ())
{
// Here we're just pushing the handlers onto the queue. If needed, something fancier could
const std::string &id, int viewport)
{
// Check to see if this entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it != cloud_actor_map_->end ())
{
// Here we're just pushing the handlers onto the queue. If needed, something fancier could
points->SetNumberOfPoints (nr_points);
// Get a pointer to the beginning of the data array
- float *data = (static_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
+ float *data = (dynamic_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
// Set the points
vtkIdType ptr = 0;
if (cloud->is_dense)
{
- for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
- std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
+ for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
+ std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
+ }
}
else
{
return (false);
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
vtkSmartPointer<vtkAppendPolyData> all_data = vtkSmartPointer<vtkAppendPolyData>::New ();
return (false);
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
vtkSmartPointer<vtkAppendPolyData> all_data = vtkSmartPointer<vtkAppendPolyData>::New ();
actor->GetProperty ()->SetRepresentationToSurface ();
actor->GetProperty ()->SetInterpolationToFlat ();
actor->GetProperty ()->SetColor (r, g, b);
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- actor->GetMapper ()->ImmediateModeRenderingOn ();
-#endif
actor->GetMapper ()->StaticOn ();
actor->GetMapper ()->ScalarVisibilityOff ();
actor->GetMapper ()->Update ();
//////////////////////////////////////////////////////////////////////////
// Get the actor pointer
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
vtkLODActor* actor = vtkLODActor::SafeDownCast (am_it->second);
if (!actor)
return (false);
textActor->SetCamera (renderer->GetActiveCamera ());
renderer->AddActor (textActor);
- renderer->Render ();
-
+
// Save the pointer/ID pair to the global actor map. If we are saving multiple vtkFollowers
// for multiple viewport
const std::string uid = tid + std::string (i, '*');
// If the cloud is organized, then distribute the normal step in both directions
if (cloud->isOrganized () && normals->isOrganized ())
{
- vtkIdType point_step = static_cast<vtkIdType> (sqrt (double (level)));
+ auto point_step = static_cast<vtkIdType> (sqrt (double (level)));
nr_normals = (static_cast<vtkIdType> ((cloud->width - 1)/ point_step) + 1) *
(static_cast<vtkIdType> ((cloud->height - 1) / point_step) + 1);
pts = new float[2 * nr_normals * 3];
vtkSmartPointer<vtkAppendPolyData> alldata = vtkSmartPointer<vtkAppendPolyData>::New ();
alldata->AddInputData (line_1_data);
alldata->AddInputData (line_2_data);
+ alldata->Update ();
// Create an Actor
vtkSmartPointer<vtkLODActor> actor;
}
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end () && !overwrite)
{
PCL_WARN ("[addCorrespondences] A set of correspondences with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
const std::string &id)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
double minmax[2];
minmax[0] = std::numeric_limits<double>::min ();
minmax[1] = std::numeric_limits<double>::max ();
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
-#endif
am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
// Update the mapper
const std::string &id)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
double minmax[2];
minmax[0] = std::numeric_limits<double>::min ();
minmax[1] = std::numeric_limits<double>::max ();
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
-#endif
am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
// Update the mapper
const std::string &id)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
has_colors = true;
}
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- am_it->second.actor->GetMapper ()->ImmediateModeRenderingOff ();
-#endif
-
if (has_colors)
am_it->second.actor->GetMapper ()->SetScalarRange (minmax);
{
if (!isFinite ((*cloud)[i]))
continue;
- const pcl::RGB* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
+ const auto* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
unsigned char color[3];
color[0] = rgb_data->r;
color[1] = rgb_data->g;
vtkSmartPointer<vtkLODActor> actor;
// Get a pointer to the beginning of the data array
- float *data = static_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
+ float *data = dynamic_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
vtkIdType ptr = 0;
std::vector<int> lookup;
// If the dataset is dense (no NaNs)
if (cloud->is_dense)
{
- for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
- std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
+ for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
+ std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
+ }
}
else
{
}
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
// Get the current poly data
- vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
+ vtkSmartPointer<vtkPolyData> polydata = dynamic_cast<vtkPolyData*>(am_it->second.actor->GetMapper ()->GetInput ());
if (!polydata)
return (false);
vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys ();
points->SetNumberOfPoints (nr_points);
// Get a pointer to the beginning of the data array
- float *data = (static_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
+ float *data = (dynamic_cast<vtkFloatArray*> (points->GetData ()))->GetPointer (0);
int ptr = 0;
std::vector<int> lookup;
{
if (!isFinite ((*cloud)[i]))
continue;
- const pcl::RGB* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
+ const auto* const rgb_data = reinterpret_cast<const pcl::RGB*>(reinterpret_cast<const char*> (&(*cloud)[i]) + offset);
unsigned char color[3];
color[0] = rgb_data->r;
color[1] = rgb_data->g;
!std::isfinite ((*cloud_)[cp].y) ||
!std::isfinite ((*cloud_)[cp].z))
continue;
-
memcpy (&rgb, (reinterpret_cast<const char *> (&(*cloud_)[cp])) + rgba_offset, sizeof (pcl::RGB));
colors[j ] = rgb.r;
colors[j + 1] = rgb.g;
namespace pcl
{
-template<typename PointSource, typename PointTarget> void
-RegistrationVisualizer<PointSource, PointTarget>::startDisplay ()
+template<typename PointSource, typename PointTarget, typename Scalar> void
+RegistrationVisualizer<PointSource, PointTarget, Scalar>::startDisplay ()
{
// Create and start the rendering thread. This will open the display window.
- viewer_thread_ = std::thread (&pcl::RegistrationVisualizer<PointSource, PointTarget>::runDisplay, this);
+ viewer_thread_ = std::thread (&pcl::RegistrationVisualizer<PointSource, PointTarget, Scalar>::runDisplay, this);
}
-template<typename PointSource, typename PointTarget> void
-RegistrationVisualizer<PointSource, PointTarget>::stopDisplay ()
+template<typename PointSource, typename PointTarget, typename Scalar> void
+RegistrationVisualizer<PointSource, PointTarget, Scalar>::stopDisplay ()
{
// Stop the rendering thread. This will kill the display window.
+ if(viewer_thread_.joinable())
+ viewer_thread_.join();
viewer_thread_.~thread ();
}
-template<typename PointSource, typename PointTarget> void
-RegistrationVisualizer<PointSource, PointTarget>::runDisplay ()
+template<typename PointSource, typename PointTarget, typename Scalar> void
+RegistrationVisualizer<PointSource, PointTarget, Scalar>::runDisplay ()
{
// Open 3D viewer
viewer_
}
-template<typename PointSource, typename PointTarget> void
-RegistrationVisualizer<PointSource, PointTarget>::updateIntermediateCloud (
+template<typename PointSource, typename PointTarget, typename Scalar> void
+RegistrationVisualizer<PointSource, PointTarget, Scalar>::updateIntermediateCloud (
const pcl::PointCloud<PointSource> &cloud_src,
const pcl::Indices &indices_src,
const pcl::PointCloud<PointTarget> &cloud_tgt,
}
} // namespace pcl
-
{}
/** \brief Empty destructor */
- ~PCLVisualizerInteractorStyle () {}
+ ~PCLVisualizerInteractorStyle () override = default;
// this macro defines Superclass, the isA functionality and the safe downcast method
vtkTypeMacro (PCLVisualizerInteractorStyle, vtkInteractorStyleRubberBandPick);
* \param[in] file the name of the camera parameter file
*/
void
- setCameraFile (const std::string file)
+ setCameraFile (const std::string& file)
{
camera_file_ = file;
}
this->brush_->DeepCopy (b);
this->transform_->SetMatrix (t->GetMatrix());
}
+
+ virtual ~Figure2D()
+ {
+ pen_->Delete();
+ brush_->Delete();
+ transform_->Delete();
+ }
void applyInternals (vtkContext2D *painter) const
{
const std::string &id = "ellipsoid",
int viewport = 0);
+ /**
+ * @brief Eye-Dome Lighting makes dark areas to improve depth perception
+ * See https://www.kitware.com/eye-dome-lighting-a-non-photorealistic-shading-technique/
+ * It is applied to all actors, including texts.
+ * @param viewport
+ */
+ void
+ enableEDLRendering(int viewport = 0);
+
/** \brief Changes the visual representation for all actors to surface representation. */
void
setRepresentationToSurfaceForAllActors ();
static FPSCallback *New () { return (new FPSCallback); }
FPSCallback () : actor (), pcl_visualizer (), decimated (), last_fps(0.0f) {}
- FPSCallback (const FPSCallback& src) : vtkCommand (src), actor (src.actor), pcl_visualizer (src.pcl_visualizer), decimated (src.decimated), last_fps (src.last_fps) {}
+ FPSCallback (const FPSCallback& src) = default;
FPSCallback& operator = (const FPSCallback& src) { actor = src.actor; pcl_visualizer = src.pcl_visualizer; decimated = src.decimated; last_fps = src.last_fps; return (*this); }
void
{}
/** \brief Destructor. */
- virtual ~PointCloudColorHandler () {}
+ virtual ~PointCloudColorHandler() = default;
/** \brief Check if this handler is capable of handling the input data or not. */
inline bool
capable_ = true;
}
- /** \brief Destructor. */
- virtual ~PointCloudColorHandlerCustom () {};
-
/** \brief Abstract getName method. */
virtual std::string
getName () const { return ("PointCloudColorHandlerCustom"); }
setInputCloud (cloud);
}
- /** \brief Destructor. */
- virtual ~PointCloudColorHandlerRGBField () {}
-
/** \brief Get the name of the field used. */
virtual std::string
getFieldName () const { return ("rgb"); }
/** \brief Constructor. */
PointCloudColorHandlerHSVField (const PointCloudConstPtr &cloud);
-
- /** \brief Empty destructor */
- virtual ~PointCloudColorHandlerHSVField () {}
/** \brief Get the name of the field used. */
virtual std::string
setInputCloud (cloud);
}
- /** \brief Destructor. */
- virtual ~PointCloudColorHandlerGenericField () {}
-
/** \brief Get the name of the field used. */
virtual std::string getFieldName () const { return (field_name_); }
setInputCloud (cloud);
}
- /** \brief Destructor. */
- virtual ~PointCloudColorHandlerRGBAField () {}
-
/** \brief Get the name of the field used. */
virtual std::string
getFieldName () const { return ("rgba"); }
static_mapping_ = static_mapping;
}
- /** \brief Destructor. */
- virtual ~PointCloudColorHandlerLabelField () {}
-
/** \brief Get the name of the field used. */
virtual std::string
getFieldName () const { return ("label"); }
{}
/** \brief Destructor. */
- virtual ~PointCloudColorHandler () {}
+ virtual ~PointCloudColorHandler() = default;
/** \brief Return whether this handler is capable of handling the input data or not. */
inline bool
{
capable_ = true;
}
-
- /** \brief Empty destructor */
- virtual ~PointCloudColorHandlerRandom () {}
/** \brief Get the name of the class. */
virtual std::string
{
capable_ = true;
}
-
- /** \brief Empty destructor */
- virtual ~PointCloudColorHandlerCustom () {}
/** \brief Get the name of the class. */
virtual std::string
/** \brief Constructor. */
PointCloudColorHandlerRGBField (const PointCloudConstPtr &cloud);
-
- /** \brief Empty destructor */
- virtual ~PointCloudColorHandlerRGBField () {}
vtkSmartPointer<vtkDataArray>
getColor () const override;
/** \brief Constructor. */
PointCloudColorHandlerHSVField (const PointCloudConstPtr &cloud);
-
- /** \brief Empty destructor */
- virtual ~PointCloudColorHandlerHSVField () {}
vtkSmartPointer<vtkDataArray>
getColor () const override;
/** \brief Constructor. */
PointCloudColorHandlerGenericField (const PointCloudConstPtr &cloud,
const std::string &field_name);
-
- /** \brief Empty destructor */
- virtual ~PointCloudColorHandlerGenericField () {}
vtkSmartPointer<vtkDataArray>
getColor () const override;
/** \brief Constructor. */
PointCloudColorHandlerRGBAField (const PointCloudConstPtr &cloud);
- /** \brief Empty destructor */
- virtual ~PointCloudColorHandlerRGBAField () {}
-
vtkSmartPointer<vtkDataArray>
getColor () const override;
PointCloudColorHandlerLabelField (const PointCloudConstPtr &cloud,
const bool static_mapping = true);
- /** \brief Empty destructor */
- virtual ~PointCloudColorHandlerLabelField () {}
-
vtkSmartPointer<vtkDataArray>
getColor () const override;
{}
/** \brief Destructor. */
- virtual ~PointCloudGeometryHandler () {}
+ virtual ~PointCloudGeometryHandler() = default;
/** \brief Abstract getName method.
* \return the name of the class/object.
/** \brief Constructor. */
PointCloudGeometryHandlerXYZ (const PointCloudConstPtr &cloud);
- /** \brief Destructor. */
- virtual ~PointCloudGeometryHandlerXYZ () {};
-
/** \brief Class getName method. */
virtual std::string
getName () const { return ("PointCloudGeometryHandlerXYZ"); }
}
/** \brief Destructor. */
- virtual ~PointCloudGeometryHandler () {}
+ virtual ~PointCloudGeometryHandler() = default;
/** \brief Abstract getName method. */
virtual std::string
/** \brief Constructor. */
PointCloudGeometryHandlerXYZ (const PointCloudConstPtr &cloud);
- /** \brief Destructor. */
- virtual ~PointCloudGeometryHandlerXYZ () {}
-
/** \brief Class getName method. */
virtual std::string
getName () const { return ("PointCloudGeometryHandlerXYZ"); }
const std::string &y_field_name,
const std::string &z_field_name);
- /** \brief Destructor. */
- virtual ~PointCloudGeometryHandlerCustom () {}
-
/** \brief Class getName method. */
virtual std::string
getName () const { return ("PointCloudGeometryHandlerCustom"); }
#pragma once
+#include <pcl/pcl_base.h>
#include <pcl/pcl_macros.h>
#include <pcl/types.h> // for pcl::Indices
+#include <pcl/visualization/common/actor_map.h>
#include <vtkCommand.h>
+#include <vtkActor.h>
+
+#include <map>
+#include <vector>
+
+
class vtkRenderWindowInteractor;
namespace pcl
{
return (new PointPickingCallback);
}
-
- PointPickingCallback () : x_ (0), y_ (0), z_ (0), idx_ (-1), pick_first_ (false) {}
/** \brief Empty destructor */
- ~PointPickingCallback () {}
+ ~PointPickingCallback () override = default;
void
Execute (vtkObject *caller, unsigned long eventid, void*) override;
- int
+ pcl::index_t
performSinglePick (vtkRenderWindowInteractor *iren);
- int
+ pcl::index_t
performSinglePick (vtkRenderWindowInteractor *iren, float &x, float &y, float &z);
- int
- performAreaPick (vtkRenderWindowInteractor *iren, pcl::Indices &indices) const;
+ pcl::index_t
+ performAreaPick (vtkRenderWindowInteractor *iren,
+ CloudActorMapPtr cam_ptr,
+ std::map<std::string, pcl::Indices>& cloud_indices) const;
+
private:
- float x_, y_, z_;
- int idx_;
- bool pick_first_;
+ float x_{0}, y_{0}, z_{0};
+ pcl::index_t idx_{pcl::UNAVAILABLE};
+ bool pick_first_{false};
+ const vtkActor* actor_{nullptr};
};
/** /brief Class representing 3D point picking events. */
class PCL_EXPORTS PointPickingEvent
{
public:
- PointPickingEvent (int idx) : idx_ (idx), idx2_ (-1), x_ (), y_ (), z_ (), x2_ (), y2_ (), z2_ () {}
- PointPickingEvent (int idx, float x, float y, float z) : idx_ (idx), idx2_ (-1), x_ (x), y_ (y), z_ (z), x2_ (), y2_ (), z2_ () {}
-
- PointPickingEvent (int idx1, int idx2, float x1, float y1, float z1, float x2, float y2, float z2) :
+ PointPickingEvent (pcl::index_t idx) : PointPickingEvent ( idx, -1,-1, -1) {}
+ PointPickingEvent (pcl::index_t idx, float x, float y, float z, const std::string& name = "") : idx_ (idx), idx2_ (-1), x_ (x), y_ (y), z_ (z), x2_ (), y2_ (), z2_ (), name_ (name) {}
+ PointPickingEvent (pcl::index_t idx1, pcl::index_t idx2, float x1, float y1, float z1, float x2, float y2, float z2) :
idx_ (idx1), idx2_ (idx2), x_ (x1), y_ (y1), z_ (z1), x2_ (x2), y2_ (y2), z2_ (z2)
{}
* cloud for the correct index. An example of how to do this can be found in the pp_callback function in
* visualization/tools/pcd_viewer.cpp
*/
- inline int
+ inline pcl::index_t
getPointIndex () const
{
return (idx_);
inline bool
getPoints (float &x1, float &y1, float &z1, float &x2, float &y2, float &z2) const
{
- if (idx2_ == -1)
+ if (idx2_ == pcl::UNAVAILABLE)
return (false);
x1 = x_; y1 = y_; z1 = z_;
x2 = x2_; y2 = y2_; z2 = z2_;
* visualization/tools/pcd_viewer.cpp
*/
inline bool
- getPointIndices (int &index_1, int &index_2) const
+ getPointIndices(pcl::index_t& index_1, pcl::index_t& index_2) const
{
- if (idx2_ == -1)
+ if (idx2_ == pcl::UNAVAILABLE)
return (false);
index_1 = idx_;
index_2 = idx2_;
return (true);
}
+ /** \brief Get name of selected cloud.
+ * \return name of the cloud selected by the user
+ */
+ inline const std::string&
+ getCloudName () const { return name_; }
+
private:
- int idx_, idx2_;
+ pcl::index_t idx_, idx2_;
float x_, y_, z_;
float x2_, y2_, z2_;
+ std::string name_;
};
} //namespace visualization
} //namespace pcl
//! Constructor
RangeImageVisualizer (const std::string& name="Range Image");
//! Destructor
- ~RangeImageVisualizer ();
+ ~RangeImageVisualizer () override;
// =====PUBLIC STATIC METHODS=====
/** Get a widget visualizing the given range image.
* \author Gheorghe Lisca
* \ingroup visualization
*/
- template<typename PointSource, typename PointTarget>
+ template<typename PointSource, typename PointTarget, typename Scalar = float>
class RegistrationVisualizer
{
/** \brief Empty constructor. */
RegistrationVisualizer () :
update_visualizer_ (),
- first_update_flag_ (),
+ first_update_flag_ (false),
cloud_source_ (),
cloud_target_ (),
cloud_intermediate_ (),
maximum_displayed_correspondences_ (0)
{}
+ ~RegistrationVisualizer ()
+ {
+ stopDisplay();
+ }
+
/** \brief Set the registration algorithm whose intermediate steps will be rendered.
* The method creates the local callback function pcl::RegistrationVisualizer::update_visualizer_ and
* binds it to the local buffers update function pcl::RegistrationVisualizer::updateIntermediateCloud().
* \param registration represents the registration method whose intermediate steps will be rendered.
*/
bool
- setRegistration (pcl::Registration<PointSource, PointTarget> ®istration)
+ setRegistration (pcl::Registration<PointSource, PointTarget, Scalar> ®istration)
{
// Update the name of the registration method to be displayed
registration_method_name_ = registration.getClassName();
updateIntermediateCloud (cloud_src, indices_src, cloud_tgt, indices_tgt);
};
- // Register the local callback function to the registration algorithm callback function
- registration.registerVisualizationCallback (this->update_visualizer_);
-
// Flag that no visualizer update was done. It indicates to visualizer update function to copy
// the registration input source and the target point clouds in the next call.
visualizer_updating_mutex_.lock ();
visualizer_updating_mutex_.unlock ();
+ // Register the local callback function to the registration algorithm callback function
+ registration.registerVisualizationCallback (this->update_visualizer_);
+
return true;
}
* All rights reserved
*/
-PCL_DEPRECATED_HEADER(1, 14, "Use required vtk includes instead.")
+PCL_DEPRECATED_HEADER(1, 15, "Use required vtk includes instead.")
#include <pcl/pcl_macros.h>
#include <vtkContextItem.h>
+
+#include <algorithm>
#include <vector>
template <typename T> class vtkSmartPointer;
static PCLContextItem *New();
bool Paint (vtkContext2D *) override { return (false); };
void setColors (unsigned char r, unsigned char g, unsigned char b);
- void setColors (unsigned char rgb[3]) { memcpy (colors, rgb, 3 * sizeof (unsigned char)); }
+ void setColors (unsigned char rgb[3]) { std::copy(rgb, rgb + 3, colors); }
void setOpacity (double opacity) { SetOpacity (opacity); };
unsigned char colors[3];
std::vector<float> params;
--- /dev/null
+/*=========================================================================
+
+ Program: Visualization Toolkit
+ Module: vtkXRenderWindowInteractor.h
+
+ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+ All rights reserved.
+ See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notice for more information.
+
+=========================================================================*/
+/**
+ * @class vtkXRenderWindowInteractor
+ * @brief an X event driven interface for a RenderWindow
+ *
+ * vtkXRenderWindowInteractor is a convenience object that provides event
+ * bindings to common graphics functions. For example, camera and actor
+ * functions such as zoom-in/zoom-out, azimuth, roll, and pan. IT is one of
+ * the window system specific subclasses of vtkRenderWindowInteractor. Please
+ * see vtkRenderWindowInteractor documentation for event bindings.
+ *
+ * @sa
+ * vtkRenderWindowInteractor
+ */
+
+#ifndef vtkXRenderWindowInteractor_h
+#define vtkXRenderWindowInteractor_h
+
+//===========================================================
+// now we define the C++ class
+
+#include "vtkRenderWindowInteractor.h"
+#include "vtkRenderingUIModule.h" // For export macro
+#include <X11/Xlib.h> // Needed for X types in the public interface
+
+namespace pcl {
+class vtkCallbackCommand;
+class vtkXRenderWindowInteractorInternals;
+
+class VTKRENDERINGUI_EXPORT vtkXRenderWindowInteractor : public vtkRenderWindowInteractor
+{
+public:
+ vtkXRenderWindowInteractor(const vtkXRenderWindowInteractor&) = delete;
+ void operator=(const vtkXRenderWindowInteractor&) = delete;
+
+ static vtkXRenderWindowInteractor* New();
+ vtkTypeMacro(vtkXRenderWindowInteractor, vtkRenderWindowInteractor);
+ void PrintSelf(ostream& os, vtkIndent indent) override;
+
+ /**
+ * Initializes the event handlers without an XtAppContext. This is
+ * good for when you don't have a user interface, but you still
+ * want to have mouse interaction.
+ */
+ void Initialize() override;
+
+ /**
+ * Break the event loop on 'q','e' keypress. Want more ???
+ */
+ void TerminateApp() override;
+
+ /**
+ * Run the event loop and return. This is provided so that you can
+ * implement your own event loop but yet use the vtk event handling as
+ * well.
+ */
+ void ProcessEvents() override;
+
+ ///@{
+ /**
+ * Enable/Disable interactions. By default interactors are enabled when
+ * initialized. Initialize() must be called prior to enabling/disabling
+ * interaction. These methods are used when a window/widget is being
+ * shared by multiple renderers and interactors. This allows a "modal"
+ * display where one interactor is active when its data is to be displayed
+ * and all other interactors associated with the widget are disabled
+ * when their data is not displayed.
+ */
+ void Enable() override;
+ void Disable() override;
+ ///@}
+
+ /**
+ * Update the Size data member and set the associated RenderWindow's
+ * size.
+ */
+ void UpdateSize(int, int) override;
+
+ /**
+ * Re-defines virtual function to get mouse position by querying X-server.
+ */
+ void GetMousePosition(int* x, int* y) override;
+
+ void DispatchEvent(XEvent*);
+
+protected:
+ vtkXRenderWindowInteractor();
+ ~vtkXRenderWindowInteractor() override;
+
+ /**
+ * Update the Size data member and set the associated RenderWindow's
+ * size but do not resize the XWindow.
+ */
+ void UpdateSizeNoXResize(int, int);
+
+ // Using static here to avoid destroying context when many apps are open:
+ static int NumAppInitialized;
+
+ Display* DisplayId;
+ bool OwnDisplay = false;
+ Window WindowId;
+ Atom KillAtom;
+ int PositionBeforeStereo[2];
+ vtkXRenderWindowInteractorInternals* Internal;
+
+ // Drag and drop related
+ int XdndSourceVersion;
+ Window XdndSource;
+ Atom XdndFormatAtom;
+ Atom XdndURIListAtom;
+ Atom XdndTypeListAtom;
+ Atom XdndEnterAtom;
+ Atom XdndPositionAtom;
+ Atom XdndDropAtom;
+ Atom XdndActionCopyAtom;
+ Atom XdndStatusAtom;
+ Atom XdndFinishedAtom;
+
+ ///@{
+ /**
+ * X-specific internal timer methods. See the superclass for detailed
+ * documentation.
+ */
+ int InternalCreateTimer(int timerId, int timerType, unsigned long duration) override;
+ int InternalDestroyTimer(int platformTimerId) override;
+ ///@}
+
+ void FireTimers();
+
+ /**
+ * This will start up the X event loop and never return. If you
+ * call this method it will loop processing X events until the
+ * application is exited.
+ */
+ void StartEventLoop() override;
+
+ /**
+ * Deallocate X ressource that may have been allocated
+ * Also calls finalize on the render window if available
+ */
+ void Finalize();
+
+};
+} // namespace pcl
+
+#endif
+++ /dev/null
- /*=========================================================================
-
- Program: Visualization Toolkit
- Module: vtkPixelBufferObject.h
-
- Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
- All rights reserved.
- See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notice for more information.
-
-=========================================================================*/
-// .NAME vtkVertexBufferObject - abstracts an OpenGL vertex buffer object.
-// .SECTION Description
-// Provides low-level access to GPU memory. Used to pass raw data to GPU.
-// The data is uploaded into a vertex buffer.
-// .SECTION See Also
-// OpenGL Vertex Buffer Object Extension Spec (ARB_vertex_buffer_object):
-// http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
-// .SECTION Caveats
-// Since most GPUs don't support double format all double data is converted to
-// float and then uploaded.
-// DON'T PLAY WITH IT YET.
-
-#pragma once
-
-#include "vtkObject.h"
-#include "vtkWeakPointer.h"
-
-#include "vtkgl.h" // Needed for gl data types exposed in API
-#include <pcl/pcl_macros.h>
-
-class vtkCellArray;
-class vtkDataArray;
-class vtkObject;
-class vtkPoints;
-class vtkUnsignedCharArray;
-class vtkOpenGLExtensionManager;
-class vtkRenderWindow;
-
-class PCL_DEPRECATED(1, 13, "The OpenGL backend of VTK is deprecated. Please switch to the OpenGL2 backend.")
-PCL_EXPORTS vtkVertexBufferObject : public vtkObject
-{
-public:
-
- static vtkVertexBufferObject* New();
- vtkTypeMacro(vtkVertexBufferObject, vtkObject);
- void PrintSelf(ostream& os, vtkIndent indent) override;
-
- // Description:
- // Get/Set the context. Context must be a vtkOpenGLRenderWindow.
- // This does not increase the reference count of the
- // context to avoid reference loops.
- // SetContext() may raise an error is the OpenGL context does not support the
- // required OpenGL extensions.
- void SetContext(vtkRenderWindow* context);
- vtkRenderWindow* GetContext();
-
- //BTX
- // Usage values.
- enum
- {
- StreamDraw=0,
- StreamRead,
- StreamCopy,
- StaticDraw,
- StaticRead,
- StaticCopy,
- DynamicDraw,
- DynamicRead,
- DynamicCopy,
- NumberOfUsages
- };
- //ETX
-
- // Description:
- // Usage is a performance hint.
- // Valid values are:
- // - StreamDraw specified once by A, used few times S
- // - StreamRead specified once by R, queried a few times by A
- // - StreamCopy specified once by R, used a few times S
- // - StaticDraw specified once by A, used many times S
- // - StaticRead specified once by R, queried many times by A
- // - StaticCopy specified once by R, used many times S
- // - DynamicDraw respecified repeatedly by A, used many times S
- // - DynamicRead respecified repeatedly by R, queried many times by A
- // - DynamicCopy respecified repeatedly by R, used many times S
- // A: the application
- // S: as the source for GL drawing and image specification commands.
- // R: reading data from the GL
- // Initial value is StaticDraw, as in OpenGL spec.
- vtkGetMacro(Usage, int);
- vtkSetMacro(Usage, int);
-
- int GetAttributeIndex();
- void SetUserDefinedAttribute(int index, bool normalized=false, int stride=0);
- void ResetUserDefinedAttribute();
-
- void SetAttributeNormalized(bool normalized);
-
- // Description:
- // Set point data
- bool Upload(vtkPoints *points);
-
- // Description:
- // Set indice data
- bool Upload(vtkCellArray *verts);
-
- // Description:
- // Set indice data
- bool Upload(unsigned int *indices, unsigned int count);
-
- // Description:
- // Set color data
- bool Upload(vtkUnsignedCharArray *colors);
-
- // Description:
- // Set color data
- bool Upload(vtkDataArray *array);
- bool Upload(vtkDataArray *array, int attributeType, int arrayType);
- bool UploadNormals(vtkDataArray *normals);
- bool UploadColors(vtkDataArray *colors);
-
-
- // Description:
- // Get the size of the data loaded into the GPU. Size is in the number of
- // elements of the uploaded Type.
- vtkGetMacro(Size, unsigned int);
-
- // Description:
- // Get the size of the data loaded into the GPU. Size is in the number of
- // elements of the uploaded Type.
- vtkGetMacro(Count, unsigned int);
-
- // Description:
- // Get the openGL buffer handle.
- vtkGetMacro(Handle, unsigned int);
-
- // Description:
- // Inactivate the buffer.
- void UnBind();
-
- // Description:
- // Make the buffer active.
- void Bind();
-
- // Description:
- // Allocate the memory. size is in number of bytes. type is a VTK type.
-// void Allocate(unsigned int size, int type);
-
-//BTX
-
- // Description:
- // Release the memory allocated without destroying the PBO handle.
- void ReleaseMemory();
-
- // Description:
- // Returns if the context supports the required extensions.
- static bool IsSupported(vtkRenderWindow* renWin);
-
-//ETX
-//BTX
-protected:
- vtkVertexBufferObject();
- ~vtkVertexBufferObject();
-
- // Description:
- // Loads all required OpenGL extensions. Must be called every time a new
- // context is set.
- bool LoadRequiredExtensions(vtkOpenGLExtensionManager* mgr);
-
- // Description:
- // Create the pixel buffer object.
- void CreateBuffer();
-
- // Description:
- // Destroys the pixel buffer object.
- void DestroyBuffer();
-
- // Description:
- // Uploads data to buffer object
- bool Upload(GLvoid* data);
-
- // Description:
- // Get the openGL buffer handle.
- vtkGetMacro(ArrayType, unsigned int);
-
- int Usage;
- unsigned int Size;
- unsigned int Count;
- unsigned int Handle;
- unsigned int ArrayType;
- unsigned int BufferTarget;
-
- int AttributeIndex;
- int AttributeSize;
- int AttributeType;
- int AttributeNormalized;
- int AttributeStride;
-
- vtkWeakPointer<vtkRenderWindow> Context;
-
-
-private:
- vtkVertexBufferObject(const vtkVertexBufferObject&); // Not implemented.
- void operator=(const vtkVertexBufferObject&); // Not implemented.
-
- // Helper to get data type sizes when passing to opengl
- int GetDataTypeSize(int type);
- //ETX
-};
+++ /dev/null
-/*=========================================================================
-
- Program: Visualization Toolkit
- Module: vtkVertexBufferObjectMapper.h
-
- Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
- All rights reserved.
- See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notice for more information.
-
-=========================================================================*/
-// .NAME vtkVertexBufferObjectMapper - map vtkPolyData to graphics primitives
-// .SECTION Description
-// vtkVertexBufferObjectMapper is a class that maps polygonal data (i.e., vtkPolyData)
-// to graphics primitives. vtkVertexBufferObjectMapper serves as a superclass for
-// device-specific poly data mappers, that actually do the mapping to the
-// rendering/graphics hardware/software.
-
-#pragma once
-
-#include <pcl/pcl_exports.h>
-#include <pcl/pcl_macros.h>
-
-#include "vtkMapper.h"
-#include "vtkSmartPointer.h"
-
-class vtkOpenGLRenderWindow;
-class vtkPolyData;
-class vtkRenderer;
-class vtkRenderWindow;
-class vtkShader2;
-class vtkShaderProgram2;
-class vtkVertexBufferObject;
-
-class PCL_DEPRECATED(1, 13, "The OpenGL backend of VTK is deprecated. Please switch to the OpenGL2 backend.")
-PCL_EXPORTS vtkVertexBufferObjectMapper : public vtkMapper
-{
-public:
- static vtkVertexBufferObjectMapper *New();
- vtkTypeMacro(vtkVertexBufferObjectMapper, vtkMapper);
-// void PrintSelf(ostream& os, vtkIndent indent);
-
- // Description:
- // Implemented by sub classes. Actual rendering is done here.
-// virtual void RenderPiece(vtkRenderer *ren, vtkActor *act);
-
- // Description:
- // This calls RenderPiece (in a for loop is streaming is necessary).
- void Render(vtkRenderer *ren, vtkActor *act) override;
-
- // Description:
- // Specify the input data to map.
- //void SetInputData(vtkPolyData *in);
- void SetInput(vtkPolyData *input);
- void SetInput(vtkDataSet *input);
- vtkPolyData *GetInput();
-
- void SetProgram(vtkSmartPointer<vtkShaderProgram2> program)
- {
- this->program = program;
- }
-
- // Description:
- // Update that sets the update piece first.
- void Update() override;
-
- // Description:
- // Return bounding box (array of six doubles) of data expressed as
- // (xmin,xmax, ymin,ymax, zmin,zmax).
- double *GetBounds() override;
- void GetBounds(double bounds[6]) override
- {this->Superclass::GetBounds(bounds);};
-
- // Description:
- // Make a shallow copy of this mapper.
-// void ShallowCopy(vtkAbstractMapper *m);
-
- // Description:
- // Select a data array from the point/cell data
- // and map it to a generic vertex attribute.
- // vertexAttributeName is the name of the vertex attribute.
- // dataArrayName is the name of the data array.
- // fieldAssociation indicates when the data array is a point data array or
- // cell data array (vtkDataObject::FIELD_ASSOCIATION_POINTS or
- // (vtkDataObject::FIELD_ASSOCIATION_CELLS).
- // componentno indicates which component from the data array must be passed as
- // the attribute. If -1, then all components are passed.
-// virtual void MapDataArrayToVertexAttribute(
-// const char* vertexAttributeName,
-// const char* dataArrayName, int fieldAssociation, int componentno=-1);
-//
-// virtual void MapDataArrayToMultiTextureAttribute(
-// int unit,
-// const char* dataArrayName, int fieldAssociation, int componentno=-1);
-
- // Description:
- // Remove a vertex attribute mapping.
-// virtual void RemoveVertexAttributeMapping(const char* vertexAttributeName);
-//
-// // Description:
-// // Remove all vertex attributes.
-// virtual void RemoveAllVertexAttributeMappings();
-
-protected:
- vtkVertexBufferObjectMapper();
- ~vtkVertexBufferObjectMapper() {};
-
- // Description:
- // Called in GetBounds(). When this method is called, the consider the input
- // to be updated depending on whether this->Static is set or not. This method
- // simply obtains the bounds from the data-object and returns it.
- virtual void ComputeBounds();
-
- vtkVertexBufferObject *vertexVbo;
- vtkVertexBufferObject *indiceVbo;
- vtkVertexBufferObject *colorVbo;
- vtkVertexBufferObject *normalVbo;
-// vtkVertexBufferObject *normalIndiceVbo;
-
- vtkSmartPointer<vtkShaderProgram2> program;
-
- int FillInputPortInformation(int, vtkInformation*) override;
-
- void createShaders(vtkOpenGLRenderWindow* win);
- void createVBOs(vtkRenderWindow* win);
-
- bool initialized;
- bool shadersInitialized;
-
-private:
- vtkVertexBufferObjectMapper(const vtkVertexBufferObjectMapper&); // Not implemented.
- void operator=(const vtkVertexBufferObjectMapper&); // Not implemented.
-};
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/memory.h>
-#include <vtkOrientationMarkerWidget.h>
-#include <vtkRenderWindowInteractor.h>
-
#include <mutex>
#include <thread>
}
}
- ~CloudViewer_impl ()
- {
- }
+ ~CloudViewer_impl () = default;
////////////////////////////////////////////////////////////////////////////////////////////
template <typename T> void
//std::cout << "Image is of size "<<width<<"x"<<height<<"\n";
int size = width*height;
int arraySize = 3 * size;
- unsigned char* data = new unsigned char[arraySize];
+ auto* data = new unsigned char[arraySize];
unsigned char* dataPtr = data;
bool recalculateMinValue = std::isinf (min_value),
//std::cout << "Image is of size "<<width<<"x"<<height<<"\n";
int size = width*height;
int arraySize = 3 * size;
- unsigned char* data = new unsigned char[arraySize];
+ auto* data = new unsigned char[arraySize];
unsigned char* dataPtr = data;
float factor = 1.0f / float (max_value - min_value), offset = float (-min_value);
{
int size = width*height;
int arraySize = 3 * size;
- unsigned char* data = new unsigned char[arraySize];
+ auto* data = new unsigned char[arraySize];
unsigned char* dataPtr = data;
for (int i=0; i<size; ++i)
{
int size = width*height;
int arraySize = 3 * size;
- unsigned char* data = new unsigned char[arraySize];
+ auto* data = new unsigned char[arraySize];
unsigned char* dataPtr = data;
for (int i=0; i<size; ++i)
#include <vtkVersion.h>
#include <vtkDoubleArray.h>
#include <vtkTextProperty.h>
-#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkDataObject.h>
#include <vtkProperty2D.h>
return (false);
}
- RenWinInteractMap::iterator am_it = wins_.find (id);
+ auto am_it = wins_.find (id);
if (am_it != wins_.end ())
{
PCL_WARN ("[addFeatureHistogram] A window with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
return (false);
}
- RenWinInteractMap::iterator am_it = wins_.find (id);
+ auto am_it = wins_.find (id);
if (am_it != wins_.end ())
{
PCL_ERROR ("[addFeatureHistogram] A window with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
const pcl::PCLPointCloud2 &cloud, const std::string &field_name,
const std::string &id)
{
- RenWinInteractMap::iterator am_it = wins_.find (id);
+ auto am_it = wins_.find (id);
if (am_it == wins_.end ())
{
PCL_WARN ("[updateFeatureHistogram] A window with id <%s> does not exists!.\n", id.c_str ());
PCL_ERROR ("[updateFeatureHistogram] Invalid point index (%d) given!\n", index);
return (false);
}
- RenWinInteractMap::iterator am_it = wins_.find (id);
+ auto am_it = wins_.find (id);
if (am_it == wins_.end ())
{
PCL_WARN ("[updateFeatureHistogram] A window with id <%s> does not exists!.\n", id.c_str ());
setSize (width, height);
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addRGBImage] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
setSize (width, height);
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::showMonoImage] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
void
pcl::visualization::ImageViewer::MouseCallback (vtkObject*, unsigned long eid, void* clientdata, void*)
{
- ImageViewer* window = reinterpret_cast<ImageViewer*> (clientdata);
+ auto* window = reinterpret_cast<ImageViewer*> (clientdata);
window->emitMouseEvent (eid);
}
void
pcl::visualization::ImageViewer::KeyboardCallback (vtkObject*, unsigned long eid, void* clientdata, void*)
{
- ImageViewer* window = reinterpret_cast<ImageViewer*> (clientdata);
+ auto* window = reinterpret_cast<ImageViewer*> (clientdata);
window->emitKeyboardEvent (eid);
}
const std::string &layer_id, int width, int height, double opacity)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it != layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addLayer] Layer with ID='%s' already exists!\n", layer_id.c_str ());
pcl::visualization::ImageViewer::removeLayer (const std::string &layer_id)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::removeLayer] No layer with ID='%s' found.\n", layer_id.c_str ());
const std::string &layer_id, double opacity)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addCircle] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
double r, double g, double b, const std::string &layer_id, double opacity)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addFilledRectangle] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
double r, double g, double b, const std::string &layer_id, double opacity)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
double r, double g, double b, const std::string &layer_id, double opacity)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addRectangle] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
const std::string &layer_id, double opacity)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addLine] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
const std::string &layer_id, double opacity)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::addText] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
const std::string &layer_id, double opacity)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::markPoint] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
return;
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- LayerMap::iterator am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
+ auto am_it = std::find_if (layer_map_.begin (), layer_map_.end (), LayerComparator (layer_id));
if (am_it == layer_map_.end ())
{
PCL_DEBUG ("[pcl::visualization::ImageViewer::markPoint] No layer with ID='%s' found. Creating new one...\n", layer_id.c_str ());
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
-pcl::visualization::ImageViewerInteractorStyle::ImageViewerInteractorStyle ()
-{
-}
+pcl::visualization::ImageViewerInteractorStyle::ImageViewerInteractorStyle () = default;
//////////////////////////////////////////////////////////////////////////////////////////
void
#include <vtkLODActor.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
+#include <vtkDataSetMapper.h>
#include <vtkCellArray.h>
#include <vtkTextProperty.h>
#include <vtkAbstractPropPicker.h>
#include <boost/algorithm/string/split.hpp> // for split
#include <boost/filesystem.hpp> // for exists
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
-#include <pcl/visualization/vtk/vtkVertexBufferObjectMapper.h>
-#endif
-
#define ORIENT_MODE 0
#define SELECT_MODE 1
data->SetPoints (points);
data->SetVerts (vertices);
// Modify the mapper
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- if (use_vbos_)
- {
- vtkVertexBufferObjectMapper* mapper = static_cast<vtkVertexBufferObjectMapper*>(act.actor->GetMapper ());
- mapper->SetInput (data);
- // Modify the actor
- act.actor->SetMapper (mapper);
- }
- else
-#endif
- {
- vtkPolyDataMapper* mapper = static_cast<vtkPolyDataMapper*>(act.actor->GetMapper ());
- mapper->SetInputData (data);
- // Modify the actor
- act.actor->SetMapper (mapper);
- }
+ auto* mapper = dynamic_cast<vtkDataSetMapper*>(act.actor->GetMapper ());
+ mapper->SetInputData (data);
+ // Modify the actor
+ act.actor->SetMapper (mapper);
+
act.actor->Modified ();
}
}
double minmax[2];
scalars->GetRange (minmax);
// Update the data
- vtkPolyData *data = static_cast<vtkPolyData*>(act.actor->GetMapper ()->GetInput ());
+ auto *data = dynamic_cast<vtkPolyData*>(act.actor->GetMapper ()->GetInput ());
data->GetPointData ()->SetScalars (scalars);
// Modify the mapper
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- if (use_vbos_)
- {
- vtkVertexBufferObjectMapper* mapper = static_cast<vtkVertexBufferObjectMapper*>(act.actor->GetMapper ());
- mapper->SetScalarRange (minmax);
- mapper->SetScalarModeToUsePointData ();
- mapper->SetInput (data);
- // Modify the actor
- act.actor->SetMapper (mapper);
- }
- else
-#endif
- {
- vtkPolyDataMapper* mapper = static_cast<vtkPolyDataMapper*>(act.actor->GetMapper ());
- mapper->SetScalarRange (minmax);
- mapper->SetScalarModeToUsePointData ();
- mapper->SetInputData (data);
- // Modify the actor
- act.actor->SetMapper (mapper);
- }
+ auto* mapper = dynamic_cast<vtkDataSetMapper*>(act.actor->GetMapper ());
+ mapper->SetScalarRange (minmax);
+ mapper->SetScalarModeToUsePointData ();
+ mapper->SetInputData (data);
+ // Modify the actor
+ act.actor->SetMapper (mapper);
+
act.actor->Modified ();
}
}
+ KeyboardEvent event (true, Interactor->GetKeySym (), Interactor->GetKeyCode (), Interactor->GetAltKey (), Interactor->GetControlKey (), Interactor->GetShiftKey ());
+ keyboard_signal_ (event);
Interactor->Render ();
return;
}
else if (key.find ("XF86ZoomOut") != std::string::npos)
zoomOut ();
- switch (Interactor->GetKeyCode ())
+ char KeyCodeChar = Interactor->GetKeyCode ();
+ if (KeyCodeChar == 0)
+ {
+ std::string KeyString(Interactor->GetKeySym());
+ if (KeyString == "KP_Add")
+ KeyCodeChar = '+';
+ else if (KeyString == "KP_Subtract")
+ KeyCodeChar = '-';
+ }
+
+ switch (KeyCodeChar)
{
case 'h': case 'H':
{
case 'j': case 'J':
{
char cam_fn[80], snapshot_fn[80];
- unsigned t = static_cast<unsigned> (time (nullptr));
- sprintf (snapshot_fn, "screenshot-%d.png" , t);
+ auto t = static_cast<unsigned> (time (nullptr));
+ sprintf (snapshot_fn, "screenshot-%u.png" , t);
saveScreenshot (snapshot_fn);
- sprintf (cam_fn, "screenshot-%d.cam", t);
+ sprintf (cam_fn, "screenshot-%u.cam", t);
saveCameraParameters (cam_fn);
pcl::console::print_info ("Screenshot (%s) and camera information (%s) successfully captured.\n", snapshot_fn, cam_fn);
{
for (actor->InitPathTraversal (); vtkAssemblyPath* path = actor->GetNextPath (); )
{
- vtkSmartPointer<vtkActor> apart = static_cast<vtkActor*> (path->GetLastNode ()->GetViewProp ());
+ vtkSmartPointer<vtkActor> apart = dynamic_cast<vtkActor*> (path->GetLastNode ()->GetViewProp ());
float psize = apart->GetProperty ()->GetPointSize ();
if (psize > 1.0f)
apart->GetProperty ()->SetPointSize (psize - 1.0f);
{
FindPokedRenderer(Interactor->GetEventPosition ()[0], Interactor->GetEventPosition ()[1]);
if(CurrentRenderer)
+ {
CurrentRenderer->ResetCamera ();
+ CurrentRenderer->Render ();
+ }
else
+ {
PCL_WARN ("no current renderer on the interactor style.\n");
-
- CurrentRenderer->Render ();
+ }
break;
}
vtkSmartPointer<vtkCamera> cam = CurrentRenderer->GetActiveCamera ();
- static CloudActorMap::iterator it = cloud_actors_->begin ();
+ static auto it = cloud_actors_->begin ();
// it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault.
bool found_transformation = false;
for (unsigned idx = 0; idx < cloud_actors_->size (); ++idx, ++it)
if (CurrentMode == SELECT_MODE)
{
// Save the point picker
- point_picker_ = static_cast<vtkPointPicker*> (Interactor->GetPicker ());
+ point_picker_ = dynamic_cast<vtkPointPicker*> (Interactor->GetPicker ());
// Switch for an area picker
vtkSmartPointer<vtkAreaPicker> area_picker = vtkSmartPointer<vtkAreaPicker>::New ();
Interactor->SetPicker (area_picker);
line[2] = x2;
line[3] = y2;
- FPolyLine2D *pline = new FPolyLine2D(line, current_pen_, current_brush_, current_transform_);
+ auto *pline = new FPolyLine2D(line, current_pen_, current_brush_, current_transform_);
figures_.push_back (pline);
}
#include <vtkPlot.h>
#include <vtkTable.h>
+#include <algorithm>
#include <fstream>
+#include <limits>
#include <pcl/visualization/pcl_plotter.h>
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-pcl::visualization::PCLPlotter::~PCLPlotter() {}
+pcl::visualization::PCLPlotter::~PCLPlotter() = default;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
//creating a permanent copy of the arrays
double *permanent_X = new double[size];
double *permanent_Y = new double[size];
- memcpy(permanent_X, array_X, size*sizeof(double));
- memcpy(permanent_Y, array_Y, size*sizeof(double));
-
+ std::copy(array_X, array_X + size, permanent_X);
+ std::copy(array_Y, array_Y + size, permanent_Y);
+
//transforming data to be fed to the vtkChartXY
VTK_CREATE (vtkTable, table);
array_y[i] = plot_data[i].second;
}
this->addPlotData (array_x, array_y, static_cast<unsigned long> (plot_data.size ()), name, type, (color.empty ()) ? nullptr : &color[0]);
+ delete[] array_x;
+ delete[] array_y;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{
double xval = i*incr + x_min;
double yval = compute(r_function, xval);
- //if (yval == DBL_MAX) continue; //handling dived by zero
+ //if (yval == std::numeric_limits<double>::max()) continue; //handling dived by zero
array_x[i] = xval;
array_y[i] = yval;
{
if (std::isfinite (value))
{
- unsigned int index = (unsigned int) (std::floor ((value - min) / size));
+ auto index = (unsigned int) (std::floor ((value - min) / size));
if (index == (unsigned int) nbins) index = nbins - 1; //including right boundary
histogram[index].second++;
}
PolynomialFunction numerator = r_function.first, denominator = r_function.second;
double dres = this->compute (denominator,val);
- //if (dres == 0) return DBL_MAX; //return the max possible double value to represent infinity
+ //if (dres == 0) return std::numeric_limits<double>::max(); //return the max possible double value to represent infinity
double nres = this->compute (numerator,val);
return (nres/dres);
}
#include <vtkCellArray.h>
#include <vtkHardwareSelector.h>
#include <vtkSelectionNode.h>
-
#include <vtkSelection.h>
#include <vtkPointPicker.h>
#include <pcl/visualization/vtk/vtkRenderWindowInteractorFix.h>
#include <pcl/visualization/vtk/pcl_vtk_compatibility.h>
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
-#include <pcl/visualization/vtk/vtkVertexBufferObjectMapper.h>
-#endif
-
#include <vtkPolyLine.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#if VTK_MAJOR_VERSION > 7
#include <vtkTexture.h>
+#include <vtkRenderStepsPass.h>
+#include <vtkEDLShading.h>
#endif
#include <pcl/visualization/common/shapes.h>
#include <pcl/common/utils.h> // pcl::utils::ignore
#include <pcl/console/parse.h>
+#include <thread>
+
// Support for VTK 7.1 upwards
#ifdef vtkGenericDataArray_h
#define SetTupleValue SetTypedTuple
if (!win_)
PCL_ERROR ("Pointer to render window is null\n");
- // This is temporary measures for disable display of deprecated warnings
- #if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- win_->GlobalWarningDisplayOff();
- #endif
-
win_->SetWindowName (name.c_str ());
// By default, don't use vertex buffer objects
if (force_redraw)
interactor_->Render ();
- DO_EVERY (1.0 / interactor_->GetDesiredUpdateRate (),
- exit_main_loop_timer_callback_->right_timer_id = interactor_->CreateRepeatingTimer (time);
- interactor_->Start ();
- interactor_->DestroyTimer (exit_main_loop_timer_callback_->right_timer_id);
- );
+#if VTK_MAJOR_VERSION >= 9 && (VTK_MINOR_VERSION != 0 || VTK_BUILD_VERSION != 0) && (VTK_MINOR_VERSION != 0 || VTK_BUILD_VERSION != 1)
+// All VTK 9 versions, except 9.0.0 and 9.0.1
+ if(interactor_->IsA("vtkXRenderWindowInteractor")) {
+ DO_EVERY (1.0 / interactor_->GetDesiredUpdateRate (),
+ interactor_->ProcessEvents ();
+ std::this_thread::sleep_for (std::chrono::milliseconds (time));
+ );
+ }
+ else
+#endif
+ {
+ DO_EVERY (1.0 / interactor_->GetDesiredUpdateRate (),
+ exit_main_loop_timer_callback_->right_timer_id = interactor_->CreateRepeatingTimer (time);
+ interactor_->Start ();
+ interactor_->DestroyTimer (exit_main_loop_timer_callback_->right_timer_id);
+ );
+ }
}
/////////////////////////////////////////////////////////////////////////////////////////////
pcl::visualization::PCLVisualizer::removeCoordinateSystem (const std::string& id, int viewport)
{
// Check to see if the given ID entry exists
- CoordinateActorMap::iterator am_it = coordinate_actor_map_->find (id);
+ auto am_it = coordinate_actor_map_->find (id);
if (am_it == coordinate_actor_map_->end ())
return (false);
pcl::visualization::PCLVisualizer::removePointCloud (const std::string &id, int viewport)
{
// Check to see if the given ID entry exists
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
pcl::visualization::PCLVisualizer::removeShape (const std::string &id, int viewport)
{
// Check to see if the given ID entry exists
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
// Extra step: check if there is a cloud with the same ID
- CloudActorMap::iterator ca_it = cloud_actor_map_->find (id);
+ auto ca_it = cloud_actor_map_->find (id);
bool shape = true;
// Try to find a shape first
for (std::size_t i = viewport; rens_->GetNextItem (); ++i)
{
const std::string uid = id + std::string (i, '*');
- ShapeActorMap::iterator am_it = shape_actor_map_->find (uid);
+ auto am_it = shape_actor_map_->find (uid);
// was it found
if (am_it == shape_actor_map_->end ())
pcl::visualization::PCLVisualizer::removeAllPointClouds (int viewport)
{
// Check to see if the given ID entry exists
- CloudActorMap::iterator am_it = cloud_actor_map_->begin ();
+ auto am_it = cloud_actor_map_->begin ();
while (am_it != cloud_actor_map_->end () )
{
if (removePointCloud (am_it->first, viewport))
style_->lut_enabled_ = false; // Temporally disable LUT to fasten shape removal
// Check to see if the given ID entry exists
- ShapeActorMap::iterator am_it = shape_actor_map_->begin ();
+ auto am_it = shape_actor_map_->begin ();
while (am_it != shape_actor_map_->end ())
{
if (removeShape (am_it->first, viewport))
pcl::visualization::PCLVisualizer::removeAllCoordinateSystems (int viewport)
{
// Check to see if the given ID entry exists
- CoordinateActorMap::iterator am_it = coordinate_actor_map_->begin ();
+ auto am_it = coordinate_actor_map_->begin ();
while (am_it != coordinate_actor_map_->end () )
{
if (removeCoordinateSystem (am_it->first, viewport))
if (!actor)
actor = vtkSmartPointer<vtkLODActor>::New ();
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- if (use_vbos_)
- {
- vtkSmartPointer<vtkVertexBufferObjectMapper> mapper = vtkSmartPointer<vtkVertexBufferObjectMapper>::New ();
-
- mapper->SetInput (data);
-
- if (use_scalars)
- {
- vtkSmartPointer<vtkDataArray> scalars = data->GetPointData ()->GetScalars ();
- if (scalars)
- {
- double minmax[2];
- scalars->GetRange (minmax);
- mapper->SetScalarRange (minmax);
+ vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
+ mapper->SetInputData (data);
- mapper->SetScalarModeToUsePointData ();
- mapper->SetInterpolateScalarsBeforeMapping (getDefaultScalarInterpolationForDataSet (data));
- mapper->ScalarVisibilityOn ();
- }
- }
-
- actor->SetNumberOfCloudPoints (int (std::max<vtkIdType> (1, data->GetNumberOfPoints () / 10)));
- actor->GetProperty ()->SetInterpolationToFlat ();
-
- /// FIXME disabling backface culling due to known VTK bug: vtkTextActors are not
- /// shown when there is a vtkActor with backface culling on present in the scene
- /// Please see VTK bug tracker for more details: http://www.vtk.org/Bug/view.php?id=12588
- // actor->GetProperty ()->BackfaceCullingOn ();
-
- actor->SetMapper (mapper);
- }
- else
-#endif
+ if (use_scalars)
{
- vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
- mapper->SetInputData (data);
-
- if (use_scalars)
+ vtkSmartPointer<vtkDataArray> scalars = data->GetPointData ()->GetScalars ();
+ if (scalars)
{
- vtkSmartPointer<vtkDataArray> scalars = data->GetPointData ()->GetScalars ();
- if (scalars)
- {
- double minmax[2];
- scalars->GetRange (minmax);
- mapper->SetScalarRange (minmax);
+ double minmax[2];
+ scalars->GetRange (minmax);
+ mapper->SetScalarRange (minmax);
- mapper->SetScalarModeToUsePointData ();
- mapper->SetInterpolateScalarsBeforeMapping (getDefaultScalarInterpolationForDataSet (data));
- mapper->ScalarVisibilityOn ();
- }
+ mapper->SetScalarModeToUsePointData ();
+ mapper->SetInterpolateScalarsBeforeMapping (getDefaultScalarInterpolationForDataSet (data));
+ mapper->ScalarVisibilityOn ();
}
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- mapper->ImmediateModeRenderingOff ();
-#endif
+ }
- actor->SetNumberOfCloudPoints (int (std::max<vtkIdType> (1, data->GetNumberOfPoints () / 10)));
- actor->GetProperty ()->SetInterpolationToFlat ();
+ actor->SetNumberOfCloudPoints (int (std::max<vtkIdType> (1, data->GetNumberOfPoints () / 10)));
+ actor->GetProperty ()->SetInterpolationToFlat ();
- /// FIXME disabling backface culling due to known VTK bug: vtkTextActors are not
- /// shown when there is a vtkActor with backface culling on present in the scene
- /// Please see VTK bug tracker for more details: http://www.vtk.org/Bug/view.php?id=12588
- // actor->GetProperty ()->BackfaceCullingOn ();
+ /// FIXME disabling backface culling due to known VTK bug: vtkTextActors are not
+ /// shown when there is a vtkActor with backface culling on present in the scene
+ /// Please see VTK bug tracker for more details: http://www.vtk.org/Bug/view.php?id=12588
+ // actor->GetProperty ()->BackfaceCullingOn ();
- actor->SetMapper (mapper);
- }
+ actor->SetMapper (mapper);
}
/////////////////////////////////////////////////////////////////////////////////////////////
if (!actor)
actor = vtkSmartPointer<vtkActor>::New ();
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- if (use_vbos_)
- {
- vtkSmartPointer<vtkVertexBufferObjectMapper> mapper = vtkSmartPointer<vtkVertexBufferObjectMapper>::New ();
-
- mapper->SetInput (data);
-
- if (use_scalars)
- {
- vtkSmartPointer<vtkDataArray> scalars = data->GetPointData ()->GetScalars ();
- if (scalars)
- {
- double minmax[2];
- scalars->GetRange (minmax);
- mapper->SetScalarRange (minmax);
-
- mapper->SetScalarModeToUsePointData ();
- mapper->SetInterpolateScalarsBeforeMapping (getDefaultScalarInterpolationForDataSet (data));
- mapper->ScalarVisibilityOn ();
- }
- }
-
- //actor->SetNumberOfCloudPoints (int (std::max<vtkIdType> (1, data->GetNumberOfPoints () / 10)));
- actor->GetProperty ()->SetInterpolationToFlat ();
-
- /// FIXME disabling backface culling due to known VTK bug: vtkTextActors are not
- /// shown when there is a vtkActor with backface culling on present in the scene
- /// Please see VTK bug tracker for more details: http://www.vtk.org/Bug/view.php?id=12588
- // actor->GetProperty ()->BackfaceCullingOn ();
+ vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
+ mapper->SetInputData (data);
- actor->SetMapper (mapper);
- }
- else
-#endif
+ if (use_scalars)
{
- vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New ();
- mapper->SetInputData (data);
-
- if (use_scalars)
+ vtkSmartPointer<vtkDataArray> scalars = data->GetPointData ()->GetScalars ();
+ if (scalars)
{
- vtkSmartPointer<vtkDataArray> scalars = data->GetPointData ()->GetScalars ();
- if (scalars)
- {
- double minmax[2];
- scalars->GetRange (minmax);
- mapper->SetScalarRange (minmax);
+ double minmax[2];
+ scalars->GetRange (minmax);
+ mapper->SetScalarRange (minmax);
- mapper->SetScalarModeToUsePointData ();
- mapper->SetInterpolateScalarsBeforeMapping (getDefaultScalarInterpolationForDataSet (data));
- mapper->ScalarVisibilityOn ();
- }
+ mapper->SetScalarModeToUsePointData ();
+ mapper->SetInterpolateScalarsBeforeMapping (getDefaultScalarInterpolationForDataSet (data));
+ mapper->ScalarVisibilityOn ();
}
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- mapper->ImmediateModeRenderingOff ();
-#endif
+ }
//actor->SetNumberOfCloudPoints (int (std::max<vtkIdType> (1, data->GetNumberOfPoints () / 10)));
- actor->GetProperty ()->SetInterpolationToFlat ();
+ actor->GetProperty ()->SetInterpolationToFlat ();
- /// FIXME disabling backface culling due to known VTK bug: vtkTextActors are not
- /// shown when there is a vtkActor with backface culling on present in the scene
- /// Please see VTK bug tracker for more details: http://www.vtk.org/Bug/view.php?id=12588
- // actor->GetProperty ()->BackfaceCullingOn ();
+ /// FIXME disabling backface culling due to known VTK bug: vtkTextActors are not
+ /// shown when there is a vtkActor with backface culling on present in the scene
+ /// Please see VTK bug tracker for more details: http://www.vtk.org/Bug/view.php?id=12588
+ // actor->GetProperty ()->BackfaceCullingOn ();
- actor->SetMapper (mapper);
- }
+ actor->SetMapper (mapper);
//actor->SetNumberOfCloudPoints (std::max<vtkIdType> (1, data->GetNumberOfPoints () / 10));
actor->GetProperty ()->SetInterpolationToFlat ();
int property, double val1, double val2, double val3, const std::string &id, int)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
{
int property, double val1, double val2, const std::string &id, int)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
{
pcl::visualization::PCLVisualizer::getPointCloudRenderingProperties (int property, double &value, const std::string &id)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
const std::string &id)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
int property, double value, const std::string &id, int)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
{
// using immediate more rendering.
case PCL_VISUALIZER_IMMEDIATE_RENDERING:
{
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- actor->GetMapper ()->SetImmediateModeRendering (int (value));
-#endif
actor->Modified ();
break;
}
pcl::visualization::PCLVisualizer::setPointCloudSelected (const bool selected, const std::string &id)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
{
int property, double val1, double val2, double val3, const std::string &id, int)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it == shape_actor_map_->end ())
{
int property, double val1, double val2, const std::string &id, int)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it == shape_actor_map_->end ())
{
int property, double value, const std::string &id, int)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it == shape_actor_map_->end ())
{
bool
pcl::visualization::PCLVisualizer::updateShapePose (const std::string &id, const Eigen::Affine3f& pose)
{
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
vtkLODActor* actor;
bool
pcl::visualization::PCLVisualizer::updateCoordinateSystemPose (const std::string &id, const Eigen::Affine3f& pose)
{
- ShapeActorMap::iterator am_it = coordinate_actor_map_->find (id);
+ auto am_it = coordinate_actor_map_->find (id);
vtkLODActor* actor;
pcl::visualization::PCLVisualizer::updatePointCloudPose (const std::string &id, const Eigen::Affine3f& pose)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
pcl::visualization::PCLVisualizer::resetCameraViewpoint (const std::string &id)
{
vtkSmartPointer<vtkMatrix4x4> camera_pose;
- static CloudActorMap::iterator it = cloud_actor_map_->find (id);
+ const CloudActorMap::iterator it = cloud_actor_map_->find(id);
if (it != cloud_actor_map_->end ())
camera_pose = it->second.viewpoint_transformation_;
else
const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addCylinder] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addCube] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addCube] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addCube] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addEllipsoid] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addSphere] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
pcl::visualization::PCLVisualizer::addModelFromPolyData (
vtkSmartPointer<vtkPolyData> polydata, const std::string & id, int viewport)
{
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr,
pcl::visualization::PCLVisualizer::addModelFromPolyData (
vtkSmartPointer<vtkPolyData> polydata, vtkSmartPointer<vtkTransform> transform, const std::string & id, int viewport)
{
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr,
pcl::visualization::PCLVisualizer::addModelFromPLYFile (const std::string &filename,
const std::string &id, int viewport)
{
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr,
vtkSmartPointer<vtkTransform> transform, const std::string &id,
int viewport)
{
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr,
pcl::visualization::PCLVisualizer::addLine (const pcl::ModelCoefficients &coefficients, const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addLine] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
pcl::visualization::PCLVisualizer::addPlane (const pcl::ModelCoefficients &coefficients, const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addPlane] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
pcl::visualization::PCLVisualizer::addPlane (const pcl::ModelCoefficients &coefficients, double x, double y, double z, const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addPlane] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
pcl::visualization::PCLVisualizer::addCircle (const pcl::ModelCoefficients &coefficients, const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addCircle] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
pcl::visualization::PCLVisualizer::addCone (const pcl::ModelCoefficients &coefficients, const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addCone] A shape with id <%s> already exists! Please choose a different id and retry.\n", id.c_str ());
tid = id;
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
+ auto am_it = shape_actor_map_->find (tid);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addText] A text with id <%s> already exists! Please choose a different id and retry.\n", tid.c_str ());
tid = id;
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
+ auto am_it = shape_actor_map_->find (tid);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addText] A text with id <%s> already exists! Please choose a different id and retry.\n", tid.c_str ());
tid = id;
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
+ auto am_it = shape_actor_map_->find (tid);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[addText] A text with id <%s> already exists! Please choose a different id and retry.\n", tid.c_str ());
tid = id;
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
+ auto am_it = shape_actor_map_->find (tid);
if (am_it == shape_actor_map_->end ())
return (false);
tid = id;
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
+ auto am_it = shape_actor_map_->find (tid);
if (am_it == shape_actor_map_->end ())
return (false);
tid = id;
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- ShapeActorMap::iterator am_it = shape_actor_map_->find (tid);
+ auto am_it = shape_actor_map_->find (tid);
if (am_it == shape_actor_map_->end ())
return (false);
bool
pcl::visualization::PCLVisualizer::updateColorHandlerIndex (const std::string &id, int index)
{
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
{
pcl::console::print_warn (stderr, "[updateColorHandlerIndex] PointCloud with id <%s> doesn't exist!\n", id.c_str ());
double minmax[2];
scalars->GetRange (minmax);
// Update the data
- vtkPolyData *data = static_cast<vtkPolyData*>(am_it->second.actor->GetMapper ()->GetInput ());
+ auto *data = dynamic_cast<vtkPolyData*>(am_it->second.actor->GetMapper ()->GetInput ());
data->GetPointData ()->SetScalars (scalars);
// Modify the mapper
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- if (use_vbos_)
- {
- vtkVertexBufferObjectMapper* mapper = static_cast<vtkVertexBufferObjectMapper*>(am_it->second.actor->GetMapper ());
- mapper->SetScalarRange (minmax);
- mapper->SetScalarModeToUsePointData ();
- mapper->SetInput (data);
- // Modify the actor
- am_it->second.actor->SetMapper (mapper);
- am_it->second.actor->Modified ();
- am_it->second.color_handler_index_ = index;
-
- //style_->setCloudActorMap (cloud_actor_map_);
- }
- else
-#endif
- {
- vtkPolyDataMapper* mapper = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ());
- mapper->SetScalarRange (minmax);
- mapper->SetScalarModeToUsePointData ();
- mapper->SetInputData (data);
- // Modify the actor
- am_it->second.actor->SetMapper (mapper);
- am_it->second.actor->Modified ();
- am_it->second.color_handler_index_ = index;
+ auto* mapper = dynamic_cast<vtkDataSetMapper*>(am_it->second.actor->GetMapper ());
+ mapper->SetScalarRange (minmax);
+ mapper->SetScalarModeToUsePointData ();
+ mapper->SetInputData (data);
+ // Modify the actor
+ am_it->second.actor->SetMapper (mapper);
+ am_it->second.actor->Modified ();
+ am_it->second.color_handler_index_ = index;
- //style_->setCloudActorMap (cloud_actor_map_);
- }
+ //style_->setCloudActorMap (cloud_actor_map_);
return (true);
}
const std::string &id,
int viewport)
{
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it != cloud_actor_map_->end ())
{
pcl::console::print_warn (stderr,
}
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it == cloud_actor_map_->end ())
return (false);
std::vector<pcl::Vertices> verts (poly_mesh.polygons); // copy vector
// Get the current poly data
- vtkSmartPointer<vtkPolyData> polydata = static_cast<vtkPolyDataMapper*>(am_it->second.actor->GetMapper ())->GetInput ();
+ vtkSmartPointer<vtkPolyData> polydata = dynamic_cast<vtkPolyData*>(am_it->second.actor->GetMapper ()->GetInput ());
if (!polydata)
return (false);
vtkSmartPointer<vtkCellArray> cells = polydata->GetStrips ();
points->SetNumberOfPoints (nr_points);
// Get a pointer to the beginning of the data array
- float *data = static_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
+ float *data = dynamic_cast<vtkFloatArray*> (points->GetData ())->GetPointer (0);
int ptr = 0;
std::vector<int> lookup;
// If the dataset is dense (no NaNs)
if (cloud->is_dense)
{
- for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3)
- std::copy (&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
+ for (vtkIdType i = 0; i < nr_points; ++i, ptr += 3) {
+ std::copy(&(*cloud)[i].x, &(*cloud)[i].x + 3, &data[ptr]);
+ }
}
else
{
pcl::visualization::PCLVisualizer::addPolylineFromPolygonMesh (
const pcl::PolygonMesh &polymesh, const std::string &id, int viewport)
{
- ShapeActorMap::iterator am_it = shape_actor_map_->find (id);
+ auto am_it = shape_actor_map_->find (id);
if (am_it != shape_actor_map_->end ())
{
pcl::console::print_warn (stderr,
const std::string &id,
int viewport)
{
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it != cloud_actor_map_->end ())
{
PCL_ERROR ("[PCLVisualizer::addTextureMesh] A shape with id <%s> already exists!"
return (true);
}
+void
+pcl::visualization::PCLVisualizer::enableEDLRendering(int viewport)
+{
+#if VTK_MAJOR_VERSION > 7
+ auto* basicPass = vtkRenderStepsPass::New();
+
+ auto* edl = vtkEDLShading::New();
+ edl->SetDelegatePass(basicPass);
+
+ // Add it to all renderers
+ rens_->InitTraversal();
+ vtkRenderer* renderer = nullptr;
+ int i = 0;
+ while ((renderer = rens_->GetNextItem())) {
+ if (i == 0) {
+ renderer->SetPass(edl);
+ }
+ else if (i == viewport) {
+ renderer->SetPass(edl);
+ }
+ i++;
+ }
+#else
+ PCL_WARN("EDL requires VTK version 8 or newer.");
+ utils::ignore(viewport);
+#endif
+}
+
///////////////////////////////////////////////////////////////////////////////////
void
pcl::visualization::PCLVisualizer::setRepresentationToSurfaceForAllActors ()
{
- ShapeActorMap::iterator am_it;
rens_->InitTraversal ();
vtkRenderer* renderer = nullptr;
while ((renderer = rens_->GetNextItem ()))
void
pcl::visualization::PCLVisualizer::setRepresentationToPointsForAllActors ()
{
- ShapeActorMap::iterator am_it;
rens_->InitTraversal ();
vtkRenderer* renderer = nullptr;
while ((renderer = rens_->GetNextItem ()))
void
pcl::visualization::PCLVisualizer::setRepresentationToWireframeForAllActors ()
{
- ShapeActorMap::iterator am_it;
rens_->InitTraversal ();
vtkRenderer* renderer = nullptr;
while ((renderer = rens_->GetNextItem ()))
mapper->SetInputConnection (trans_filter_scale->GetOutputPort ());
mapper->Update ();
- //////////////////////////////
- // * Compute area of the mesh
- //////////////////////////////
- vtkSmartPointer<vtkCellArray> cells = mapper->GetInput ()->GetPolys ();
- vtkIdType npts = 0;
- vtkCellPtsPtr ptIds = nullptr;
-
- double p1[3], p2[3], p3[3], totalArea = 0;
- for (cells->InitTraversal (); cells->GetNextCell(npts, ptIds);)
- {
- polydata->GetPoint (ptIds[0], p1);
- polydata->GetPoint (ptIds[1], p2);
- polydata->GetPoint (ptIds[2], p3);
- totalArea += vtkTriangle::TriangleArea (p1, p2, p3);
- }
-
//create icosahedron
vtkSmartPointer<vtkPlatonicSolidSource> ico = vtkSmartPointer<vtkPlatonicSolidSource>::New ();
ico->SetSolidTypeToIcosahedron ();
{
int id_mesh = static_cast<int> (ids->GetValue (sel_id));
vtkCell * cell = polydata->GetCell (id_mesh);
- vtkTriangle* triangle = dynamic_cast<vtkTriangle*> (cell);
+ auto* triangle = dynamic_cast<vtkTriangle*> (cell);
if (!triangle)
{
PCL_WARN ("[renderViewTesselatedSphere] Invalid triangle %d, skipping!\n", id_mesh);
const std::string &id, int viewport)
{
// Check to see if this entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it != cloud_actor_map_->end ())
{
// Here we're just pushing the handlers onto the queue. If needed, something fancier could
const std::string &id, int viewport)
{
// Check to see if this ID entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it != cloud_actor_map_->end ())
{
const std::string &id, int viewport)
{
// Check to see if this entry already exists (has it been already added to the visualizer?)
- CloudActorMap::iterator am_it = cloud_actor_map_->find (id);
+ auto am_it = cloud_actor_map_->find (id);
if (am_it != cloud_actor_map_->end ())
{
// Here we're just pushing the handlers onto the queue. If needed, something fancier could
int
pcl::visualization::PCLVisualizer::getColorHandlerIndex (const std::string &id)
{
- CloudActorMap::iterator am_it = style_->getCloudActorMap ()->find (id);
+ auto am_it = style_->getCloudActorMap ()->find (id);
if (am_it == cloud_actor_map_->end ())
return (-1);
int
pcl::visualization::PCLVisualizer::getGeometryHandlerIndex (const std::string &id)
{
- CloudActorMap::iterator am_it = style_->getCloudActorMap ()->find (id);
+ auto am_it = style_->getCloudActorMap ()->find (id);
if (am_it != cloud_actor_map_->end ())
return (-1);
void
pcl::visualization::PCLVisualizer::setUseVbos (bool use_vbos)
{
-#if VTK_RENDERING_BACKEND_OPENGL_VERSION < 2
- use_vbos_ = use_vbos;
- style_->setUseVbos (use_vbos_);
-#else
PCL_WARN ("[PCLVisualizer::setUseVbos] Has no effect when OpenGL version is ≥ 2\n");
pcl::utils::ignore(use_vbos);
-#endif
}
//////////////////////////////////////////////////////////////////////////////////////////////
pcl::visualization::PCLVisualizer::FPSCallback::Execute (
vtkObject* caller, unsigned long, void*)
{
- vtkRenderer *ren = reinterpret_cast<vtkRenderer *> (caller);
+ auto *ren = reinterpret_cast<vtkRenderer *> (caller);
last_fps = 1.0f / static_cast<float> (ren->GetLastRenderTimeInSeconds ());
char buf[128];
sprintf (buf, "%.1f FPS", last_fps);
boost::filesystem::directory_iterator (),
back_inserter (paths));
- for (paths_vector::const_iterator it = paths.begin (); it != paths.end (); ++it)
+ for (const auto& path : paths)
{
- if (boost::filesystem::is_regular_file (*it))
+ if (boost::filesystem::is_regular_file (path))
{
- std::string name = it->string ();
+ std::string name = path.string ();
boost::to_upper (name);
if (name == upper_filename)
{
- real_name = it->string ();
+ real_name = path.string ();
break;
}
}
if (boost::filesystem::exists (path))
{
path = boost::filesystem::canonical (path);
- const char *str = path.string ().c_str ();
- sha1.process_bytes (str, std::strlen (str));
+ const auto pathStr = path.string ();
+ sha1.process_bytes (pathStr.c_str(), pathStr.size());
valid = true;
}
}
scalars->SetNumberOfTuples (nr_points);
// Get a random color
- unsigned char* colors = new unsigned char[nr_points * 3];
+ auto* colors = new unsigned char[nr_points * 3];
// Color every point
for (vtkIdType cp = 0; cp < nr_points; ++cp)
scalars->SetNumberOfTuples (nr_points);
// Get a random color
- unsigned char* colors = new unsigned char[nr_points * 3];
+ auto* colors = new unsigned char[nr_points * 3];
double r, g, b;
pcl::visualization::getRandomColors (r, g, b);
vtkIdType nr_points = cloud_->width * cloud_->height;
scalars->SetNumberOfTuples (nr_points);
// Allocate enough memory to hold all colors
- unsigned char* colors = new unsigned char[nr_points * 3];
+ auto* colors = new unsigned char[nr_points * 3];
pcl::RGB rgb_data;
std::size_t point_offset = cloud_->fields[field_idx_].offset;
// Allocate enough memory to hold all colors
// colors is taken over by SetArray (line 419)
- unsigned char* colors = new unsigned char[nr_points * 3];
+ auto* colors = new unsigned char[nr_points * 3];
float h_data, v_data, s_data;
int point_offset = cloud_->fields[field_idx_].offset;
vtkIdType nr_points = cloud_->width * cloud_->height;
scalars->SetNumberOfTuples (nr_points);
// Allocate enough memory to hold all colors
- unsigned char* colors = new unsigned char[nr_points * 4];
+ auto* colors = new unsigned char[nr_points * 4];
pcl::RGB rgba_data;
int point_offset = cloud_->fields[field_idx_].offset;
vtkIdType nr_points = cloud_->width * cloud_->height;
scalars->SetNumberOfTuples (nr_points);
// Allocate enough memory to hold all colors
- unsigned char* colors = new unsigned char[nr_points * 3];
+ auto* colors = new unsigned char[nr_points * 3];
int j = 0;
int point_offset = cloud_->fields[field_idx_].offset;
// Assign Glasbey colors in ascending order of labels
std::size_t color = 0;
- for (std::set<std::uint32_t>::iterator iter = labels.begin (); iter != labels.end (); ++iter, ++color)
- colormap[*iter] = GlasbeyLUT::at (color % GlasbeyLUT::size ());
+ for (const auto& label : labels)
+ {
+ colormap[label] = GlasbeyLUT::at(color % GlasbeyLUT::size());
+ ++color;
+ }
}
// If XYZ present, check if the points are invalid
int x_idx = pcl::getFieldIndex (*cloud_, "x");
#include <vtkPlanes.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
+#include <vtkMapper.h>
+#include <vtkProp3DCollection.h>
/////////////////////////////////////////////////////////////////////////////////////////////
void
pcl::visualization::PointPickingCallback::Execute (vtkObject *caller, unsigned long eventid, void*)
{
- PCLVisualizerInteractorStyle *style = reinterpret_cast<PCLVisualizerInteractorStyle*>(caller);
+ auto *style = reinterpret_cast<PCLVisualizerInteractorStyle*>(caller);
vtkRenderWindowInteractor* iren = reinterpret_cast<pcl::visualization::PCLVisualizerInteractorStyle*>(caller)->GetInteractor ();
+
if (style->CurrentMode == 0)
{
if ((eventid == vtkCommand::LeftButtonPressEvent) && (iren->GetShiftKey () > 0))
float x = 0, y = 0, z = 0;
int idx = performSinglePick (iren, x, y, z);
// Create a PointPickingEvent if a point was selected
- if (idx != -1)
+ if (idx != pcl::UNAVAILABLE)
{
- PointPickingEvent event (idx, x, y, z);
- style->point_picking_signal_ (event);
+ CloudActorMapPtr cam_ptr = style->getCloudActorMap();
+ const auto actor = std::find_if(cam_ptr->cbegin(), cam_ptr->cend(), [this](const auto& cloud_actor) { return cloud_actor.second.actor.GetPointer() == actor_; });
+ const std::string name = (actor != cam_ptr->cend()) ? actor->first : "";
+ style->point_picking_signal_ (PointPickingEvent (idx, x, y, z, name));
}
}
else if ((eventid == vtkCommand::LeftButtonPressEvent) && (iren->GetAltKey () == 1))
{
pick_first_ = !pick_first_;
float x = 0, y = 0, z = 0;
- int idx = -1;
+ index_t idx = pcl::UNAVAILABLE;
if (pick_first_)
idx_ = performSinglePick (iren, x_, y_, z_);
else
else if (eventid == vtkCommand::LeftButtonReleaseEvent)
{
style->OnLeftButtonUp ();
- pcl::Indices indices;
- int nb_points = performAreaPick (iren, indices);
- AreaPickingEvent event (nb_points, indices);
- style->area_picking_signal_ (event);
+ std::map<std::string, Indices> cloud_indices;
+ performAreaPick (iren, style->getCloudActorMap(), cloud_indices);
+ style->area_picking_signal_ (AreaPickingEvent (std::move(cloud_indices)));
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
-int
+pcl::index_t
pcl::visualization::PointPickingCallback::performSinglePick (vtkRenderWindowInteractor *iren)
{
vtkPointPicker* point_picker = vtkPointPicker::SafeDownCast (iren->GetPicker ());
vtkRenderer *ren = iren->FindPokedRenderer (mouse_x, mouse_y);
point_picker->Pick (mouse_x, mouse_y, 0.0, ren);
- return (static_cast<int> (point_picker->GetPointId ()));
+ return (static_cast<pcl::index_t>(point_picker->GetPointId()));
}
/////////////////////////////////////////////////////////////////////////////////////////////
-int
+pcl::index_t
pcl::visualization::PointPickingCallback::performSinglePick (
vtkRenderWindowInteractor *iren,
float &x, float &y, float &z)
vtkRenderer *ren = iren->FindPokedRenderer (mouse_x, mouse_y);
point_picker->Pick (mouse_x, mouse_y, 0.0, ren);
- int idx = static_cast<int> (point_picker->GetPointId ());
+ auto idx = static_cast<index_t>(point_picker->GetPointId());
if (point_picker->GetDataSet ())
{
double p[3];
point_picker->GetDataSet ()->GetPoint (idx, p);
x = float (p[0]); y = float (p[1]); z = float (p[2]);
+ actor_ = point_picker->GetActor();
}
return (idx);
}
/////////////////////////////////////////////////////////////////////////////////////////////
-int
-pcl::visualization::PointPickingCallback::performAreaPick (vtkRenderWindowInteractor *iren,
- pcl::Indices &indices) const
+pcl::index_t
+pcl::visualization::PointPickingCallback::performAreaPick (vtkRenderWindowInteractor *iren,pcl::visualization::CloudActorMapPtr cam_ptr,
+ std::map<std::string, pcl::Indices>& cloud_indices) const
{
- vtkAreaPicker *picker = static_cast<vtkAreaPicker*> (iren->GetPicker ());
+ auto *picker = dynamic_cast<vtkAreaPicker*> (iren->GetPicker ());
vtkRenderer *ren = iren->FindPokedRenderer (iren->GetEventPosition ()[0], iren->GetEventPosition ()[1]);
picker->AreaPick (x_, y_, iren->GetEventPosition ()[0], iren->GetEventPosition ()[1], ren);
- if (picker->GetDataSet ())
- {
- vtkPolyData* points = reinterpret_cast<vtkPolyData*> (picker->GetDataSet ());
-
- // This is a naive solution till we fugure out where to add the GlobalIds at an earlier stage
- if (!points->GetPointData ()->GetGlobalIds () ||
- points->GetPointData ()->GetGlobalIds ()->GetNumberOfTuples () == 0)
- {
- vtkSmartPointer<vtkIdTypeArray> global_ids = vtkIdTypeArray::New ();
- global_ids->SetNumberOfValues (picker->GetDataSet ()->GetNumberOfPoints ());
- for (vtkIdType i = 0; i < picker->GetDataSet ()->GetNumberOfPoints (); ++i)
- global_ids->SetValue (i,i);
- points->GetPointData ()->SetGlobalIds (global_ids);
- }
+ vtkProp3DCollection* props = picker->GetProp3Ds ();
+ if (!props)
+ return -1;
- vtkPlanes* frustum = picker->GetFrustum ();
+ index_t pt_numb = 0;
+ vtkCollectionSimpleIterator pit;
+ vtkProp3D* prop;
+ for (props->InitTraversal (pit); (prop = props->GetNextProp3D (pit));)
+ {
+ vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast (prop);
+ if (!actor)
+ continue;
- vtkSmartPointer<vtkExtractGeometry> extract_geometry = vtkSmartPointer<vtkExtractGeometry>::New ();
- extract_geometry->SetImplicitFunction (frustum);
+ vtkPolyData* pd = vtkPolyData::SafeDownCast (actor->GetMapper ()->GetInput ());
+ if(pd->GetPointData ()->HasArray ("Indices"))
+ pd->GetPointData ()->RemoveArray ("Indices");
- extract_geometry->SetInputData (picker->GetDataSet ());
+ vtkSmartPointer<vtkIdTypeArray> ids = vtkSmartPointer<vtkIdTypeArray>::New ();
+ ids->SetNumberOfComponents (1);
+ ids->SetName ("Indices");
+ for(vtkIdType i = 0; i < pd->GetNumberOfPoints (); i++)
+ ids->InsertNextValue (i);
+ pd->GetPointData ()->AddArray (ids);
+ vtkSmartPointer<vtkExtractGeometry> extract_geometry = vtkSmartPointer<vtkExtractGeometry>::New ();
+ extract_geometry->SetImplicitFunction (picker->GetFrustum ());
+ extract_geometry->SetInputData (pd);
extract_geometry->Update ();
vtkSmartPointer<vtkVertexGlyphFilter> glyph_filter = vtkSmartPointer<vtkVertexGlyphFilter>::New ();
glyph_filter->Update ();
vtkPolyData* selected = glyph_filter->GetOutput ();
- vtkIdTypeArray* ids = vtkIdTypeArray::SafeDownCast(selected->GetPointData ()->GetGlobalIds ());
- assert (ids);
- indices.reserve (ids->GetNumberOfTuples ());
+ vtkIdTypeArray* global_ids = vtkIdTypeArray::SafeDownCast (selected->GetPointData ()->GetArray ("Indices"));
+
+ if (!global_ids->GetSize () || !selected->GetNumberOfPoints ())
+ continue;
+
+ Indices actor_indices;
+ actor_indices.reserve (selected->GetNumberOfPoints ());
+ for (vtkIdType i = 0; i < selected->GetNumberOfPoints (); i++)
+ actor_indices.push_back (static_cast<index_t> (global_ids->GetValue (i)));
- for(vtkIdType i = 0; i < ids->GetNumberOfTuples (); i++)
- indices.push_back (static_cast<index_t> (ids->GetValue (i)));
+ pt_numb += selected->GetNumberOfPoints ();
- return (static_cast<int> (selected->GetNumberOfPoints ()));
+ const auto selected_actor = std::find_if (cam_ptr->cbegin (), cam_ptr->cend (), [&actor] (const auto& cloud_actor) { return cloud_actor.second.actor == actor; });
+ const std::string name = (selected_actor!= cam_ptr->cend ()) ? selected_actor->first : "";
+ cloud_indices.emplace (name, std::move(actor_indices));
}
- return (-1);
+ return pt_numb;
}
{
}
-pcl::visualization::RangeImageVisualizer::~RangeImageVisualizer ()
-{
-}
+pcl::visualization::RangeImageVisualizer::~RangeImageVisualizer () = default;
// void
// pcl::visualization::RangeImageVisualizer::setRangeImage (const pcl::RangeImage& range_image, float min_value, float max_value, bool grayscale)
pcl::visualization::RangeImageVisualizer::getRangeImageWidget (
const pcl::RangeImage& range_image, float min_value, float max_value, bool grayscale, const std::string& name)
{
- RangeImageVisualizer* range_image_widget = new RangeImageVisualizer (name);
+ auto* range_image_widget = new RangeImageVisualizer (name);
range_image_widget->showRangeImage (range_image, min_value, max_value, grayscale);
return range_image_widget;
}
const pcl::PointCloud<pcl::BorderDescription>& border_descriptions, const std::string& name)
{
//std::cout << PVARN(range_image)<<PVARN(min_value)<<PVARN(max_value)<<PVARN(grayscale);
- RangeImageVisualizer* range_image_widget = new RangeImageVisualizer;
+ auto* range_image_widget = new RangeImageVisualizer;
range_image_widget->visualizeBorders (range_image, min_value, max_value, grayscale,
border_descriptions);
range_image_widget->setWindowTitle (name);
pcl::visualization::RangeImageVisualizer::getAnglesWidget (const pcl::RangeImage& range_image, float* angles_image,
const std::string& name)
{
- RangeImageVisualizer* widget = new RangeImageVisualizer;
+ auto* widget = new RangeImageVisualizer;
widget->showAngleImage(angles_image, range_image.width, range_image.height);
widget->setWindowTitle (name);
return widget;
pcl::visualization::RangeImageVisualizer::getHalfAnglesWidget (const pcl::RangeImage& range_image,
float* angles_image, const std::string& name)
{
- RangeImageVisualizer* widget = new RangeImageVisualizer;
+ auto* widget = new RangeImageVisualizer;
widget->showHalfAngleImage(angles_image, range_image.width, range_image.height);
widget->setWindowTitle (name);
return widget;
const pcl::RangeImage& range_image, const float* interest_image, float min_value, float max_value,
const pcl::PointCloud<pcl::InterestPoint>& interest_points, const std::string& name)
{
- RangeImageVisualizer* widget = new RangeImageVisualizer;
+ auto* widget = new RangeImageVisualizer;
widget->showFloatImage (interest_image, range_image.width, range_image.height, min_value, max_value);
widget->setWindowTitle (name);
for (const auto &interest_point : interest_points.points)
void
pcl::visualization::context_items::Markers::setPointColors (unsigned char rgb[3])
{
- memcpy (point_colors, rgb, 3 * sizeof (unsigned char));
+ std::copy(rgb, rgb + 3, point_colors);
}
///////////////////////////////////////////////////////////////////////////////////////////
--- /dev/null
+/*=========================================================================
+
+ Program: Visualization Toolkit
+ Module: vtkXRenderWindowInteractor.cxx
+
+ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+ All rights reserved.
+ See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notice for more information.
+
+=========================================================================*/
+
+// Must be included first to avoid conflicts with X11's `Status` define.
+#include <vtksys/SystemTools.hxx>
+
+#include "pcl/visualization/vtk/vtkFixedXRenderWindowInteractor.h"
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <sys/time.h>
+
+#include "vtkActor.h"
+#include "vtkCallbackCommand.h"
+#include "vtkCommand.h"
+#include "vtkInteractorStyle.h"
+#include "vtkObjectFactory.h"
+#include "vtkRenderWindow.h"
+#include "vtkStringArray.h"
+
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+
+#include <climits>
+#include <cmath>
+#include <map>
+#include <set>
+#include <sstream>
+
+namespace pcl {
+vtkStandardNewMacro(vtkXRenderWindowInteractor);
+
+template <int EventType>
+int XEventTypeEquals(Display*, XEvent* event, XPointer)
+{
+ return event->type == EventType;
+}
+
+struct vtkXRenderWindowInteractorTimer
+{
+ unsigned long duration;
+ timeval lastFire;
+};
+
+constexpr unsigned char XDND_VERSION = 5;
+
+// Map between the X native id to our own integer count id. Note this
+// is separate from the TimerMap in the vtkRenderWindowInteractor
+// superclass. This is used to avoid passing 64-bit values back
+// through the "int" return type of InternalCreateTimer.
+class vtkXRenderWindowInteractorInternals
+{
+public:
+ vtkXRenderWindowInteractorInternals() { this->TimerIdCount = 1; }
+ ~vtkXRenderWindowInteractorInternals() = default;
+
+ // duration is in milliseconds
+ int CreateLocalTimer(unsigned long duration)
+ {
+ int id = this->TimerIdCount++;
+ this->LocalToTimer[id].duration = duration;
+ gettimeofday(&this->LocalToTimer[id].lastFire, nullptr);
+ return id;
+ }
+
+ void DestroyLocalTimer(int id) { this->LocalToTimer.erase(id); }
+
+ void GetTimeToNextTimer(timeval& tv)
+ {
+ uint64_t lowestDelta = 1000000;
+ if (!this->LocalToTimer.empty())
+ {
+ timeval ctv;
+ gettimeofday(&ctv, nullptr);
+ for (auto& timer : this->LocalToTimer)
+ {
+ uint64_t delta = (ctv.tv_sec - timer.second.lastFire.tv_sec) * 1000000 + ctv.tv_usec -
+ timer.second.lastFire.tv_usec;
+ if (delta < lowestDelta)
+ {
+ lowestDelta = delta;
+ }
+ }
+ }
+ tv.tv_sec = lowestDelta / 1000000;
+ tv.tv_usec = lowestDelta % 1000000;
+ }
+
+ void FireTimers(vtkXRenderWindowInteractor* rwi)
+ {
+ if (!this->LocalToTimer.empty())
+ {
+ timeval ctv;
+ gettimeofday(&ctv, nullptr);
+ std::vector<unsigned long> expired;
+ for (auto& timer : this->LocalToTimer)
+ {
+ int64_t delta = (ctv.tv_sec - timer.second.lastFire.tv_sec) * 1000000 + ctv.tv_usec -
+ timer.second.lastFire.tv_usec;
+ if (delta / 1000 >= static_cast<int64_t>(timer.second.duration))
+ {
+ int timerId = rwi->GetVTKTimerId(timer.first);
+ rwi->InvokeEvent(vtkCommand::TimerEvent, &timerId);
+ if (rwi->IsOneShotTimer(timerId))
+ {
+ expired.push_back(timer.first);
+ }
+ else
+ {
+ timer.second.lastFire.tv_sec = ctv.tv_sec;
+ timer.second.lastFire.tv_usec = ctv.tv_usec;
+ }
+ }
+ }
+ for (auto exp : expired)
+ {
+ this->DestroyLocalTimer(exp);
+ }
+ }
+ }
+
+ static std::set<vtkXRenderWindowInteractor*> Instances;
+
+private:
+ int TimerIdCount;
+ std::map<int, vtkXRenderWindowInteractorTimer> LocalToTimer;
+};
+
+std::set<vtkXRenderWindowInteractor*> vtkXRenderWindowInteractorInternals::Instances;
+
+// for some reason the X11 def of KeySym is getting messed up
+using vtkKeySym = XID;
+
+//------------------------------------------------------------------------------
+vtkXRenderWindowInteractor::vtkXRenderWindowInteractor()
+{
+ this->Internal = new vtkXRenderWindowInteractorInternals;
+ this->DisplayId = nullptr;
+ this->WindowId = 0;
+ this->KillAtom = 0;
+ this->XdndSource = 0;
+ this->XdndFormatAtom = 0;
+ this->XdndURIListAtom = 0;
+ this->XdndTypeListAtom = 0;
+ this->XdndEnterAtom = 0;
+ this->XdndPositionAtom = 0;
+ this->XdndDropAtom = 0;
+ this->XdndActionCopyAtom = 0;
+ this->XdndStatusAtom = 0;
+ this->XdndFinishedAtom = 0;
+}
+
+//------------------------------------------------------------------------------
+vtkXRenderWindowInteractor::~vtkXRenderWindowInteractor()
+{
+ this->Disable();
+
+ delete this->Internal;
+}
+
+//------------------------------------------------------------------------------
+// TerminateApp() notifies the event loop to exit.
+// The event loop is started by Start() or by one own's method.
+// This results in Start() returning to its caller.
+void vtkXRenderWindowInteractor::TerminateApp()
+{
+ if (this->Done)
+ {
+ return;
+ }
+
+ this->Done = true;
+
+ // Send a VTK_BreakXtLoop ClientMessage event to be sure we pop out of the
+ // event loop. This "wakes up" the event loop. Otherwise, it might sit idle
+ // waiting for an event before realizing an exit was requested.
+ XClientMessageEvent client;
+ memset(&client, 0, sizeof(client));
+
+ client.type = ClientMessage;
+ // client.serial; //leave zeroed
+ // client.send_event; //leave zeroed
+ client.display = this->DisplayId;
+ client.window = this->WindowId;
+ client.message_type = XInternAtom(this->DisplayId, "VTK_BreakXtLoop", False);
+ client.format = 32; // indicates size of data chunks: 8, 16 or 32 bits...
+ // client.data; //leave zeroed
+
+ XSendEvent(client.display, client.window, True, NoEventMask, reinterpret_cast<XEvent*>(&client));
+ XFlush(client.display);
+}
+
+void vtkXRenderWindowInteractor::ProcessEvents()
+{
+ std::vector<int> rwiFileDescriptors;
+ fd_set in_fds;
+ struct timeval tv;
+ struct timeval minTv;
+
+ bool wait = true;
+ bool done = true;
+ minTv.tv_sec = 1000;
+ minTv.tv_usec = 1000;
+ XEvent event;
+
+ rwiFileDescriptors.reserve(vtkXRenderWindowInteractorInternals::Instances.size());
+ for (auto rwi : vtkXRenderWindowInteractorInternals::Instances)
+ {
+ rwiFileDescriptors.push_back(ConnectionNumber(rwi->DisplayId));
+ }
+
+ for (auto rwi = vtkXRenderWindowInteractorInternals::Instances.begin();
+ rwi != vtkXRenderWindowInteractorInternals::Instances.end();)
+ {
+
+ if (XPending((*rwi)->DisplayId) == 0)
+ {
+ // get how long to wait for the next timer
+ (*rwi)->Internal->GetTimeToNextTimer(tv);
+ minTv.tv_sec = std::min(tv.tv_sec, minTv.tv_sec);
+ minTv.tv_usec = std::min(tv.tv_usec, minTv.tv_usec);
+ }
+ else
+ {
+ // If events are pending, dispatch them to the right RenderWindowInteractor
+ XNextEvent((*rwi)->DisplayId, &event);
+ (*rwi)->DispatchEvent(&event);
+ wait = false;
+ }
+ (*rwi)->FireTimers();
+
+ // Check if all RenderWindowInteractors have been terminated
+ done = done && (*rwi)->Done;
+
+ // If current RenderWindowInteractor have been terminated, handle its last event,
+ // then remove it from the Instance vector
+ if ((*rwi)->Done)
+ {
+ // Empty the event list
+ while (XPending((*rwi)->DisplayId) != 0)
+ {
+ XNextEvent((*rwi)->DisplayId, &event);
+ (*rwi)->DispatchEvent(&event);
+ }
+
+ // Finalize the rwi
+ (*rwi)->Finalize();
+
+ // Adjust the file descriptors vector
+ int rwiPosition = std::distance(vtkXRenderWindowInteractorInternals::Instances.begin(), rwi);
+ rwi = vtkXRenderWindowInteractorInternals::Instances.erase(rwi);
+ rwiFileDescriptors.erase(rwiFileDescriptors.begin() + rwiPosition);
+ }
+ else
+ {
+ ++rwi;
+ }
+ }
+
+ if (wait && !done)
+ {
+ // select will wait until 'tv' elapses or something else wakes us
+ FD_ZERO(&in_fds);
+ for (auto rwiFileDescriptor : rwiFileDescriptors)
+ {
+ FD_SET(rwiFileDescriptor, &in_fds);
+ }
+ int maxFileDescriptor = *std::max_element(rwiFileDescriptors.begin(), rwiFileDescriptors.end());
+ select(maxFileDescriptor + 1, &in_fds, nullptr, nullptr, &minTv);
+ }
+
+ this->Done = done;
+}
+
+//------------------------------------------------------------------------------
+// This will start up the X event loop. If you
+// call this method it will loop processing X events until the
+// loop is exited.
+void vtkXRenderWindowInteractor::StartEventLoop()
+{
+ for (auto rwi : vtkXRenderWindowInteractorInternals::Instances)
+ {
+ rwi->Done = false;
+ }
+ do
+ {
+ this->ProcessEvents();
+ } while (!this->Done);
+}
+
+//------------------------------------------------------------------------------
+// Initializes the event handlers without an XtAppContext. This is
+// good for when you don't have a user interface, but you still
+// want to have mouse interaction.
+void vtkXRenderWindowInteractor::Initialize()
+{
+ if (this->Initialized)
+ {
+ return;
+ }
+
+ vtkRenderWindow* ren;
+ int* size;
+
+ // make sure we have a RenderWindow and camera
+ if (!this->RenderWindow)
+ {
+ vtkErrorMacro(<< "No renderer defined!");
+ return;
+ }
+
+ this->Initialized = 1;
+ ren = this->RenderWindow;
+
+ this->DisplayId = static_cast<Display*>(ren->GetGenericDisplayId());
+ if (!this->DisplayId)
+ {
+ vtkDebugMacro("opening display");
+ this->DisplayId = XOpenDisplay(nullptr);
+ this->OwnDisplay = true;
+ vtkDebugMacro("opened display");
+ ren->SetDisplayId(this->DisplayId);
+ }
+
+ vtkXRenderWindowInteractorInternals::Instances.insert(this);
+
+ size = ren->GetActualSize();
+ size[0] = ((size[0] > 0) ? size[0] : 300);
+ size[1] = ((size[1] > 0) ? size[1] : 300);
+ XSync(this->DisplayId, False);
+
+ ren->Start();
+ ren->End();
+
+ this->WindowId = reinterpret_cast<Window>(ren->GetGenericWindowId());
+
+ XWindowAttributes attribs;
+ // Find the current window size
+ XGetWindowAttributes(this->DisplayId, this->WindowId, &attribs);
+
+ size[0] = attribs.width;
+ size[1] = attribs.height;
+ ren->SetSize(size[0], size[1]);
+
+ this->Enable();
+ this->Size[0] = size[0];
+ this->Size[1] = size[1];
+}
+
+void vtkXRenderWindowInteractor::Finalize()
+{
+ if (this->RenderWindow)
+ {
+ // Finalize the window
+ this->RenderWindow->Finalize();
+ }
+
+ // if we create the display, we'll delete it
+ if (this->OwnDisplay && this->DisplayId)
+ {
+ XCloseDisplay(this->DisplayId);
+ this->DisplayId = nullptr;
+ this->OwnDisplay = false;
+ }
+}
+
+//------------------------------------------------------------------------------
+void vtkXRenderWindowInteractor::Enable()
+{
+ // avoid cycles of calling Initialize() and Enable()
+ if (this->Enabled)
+ {
+ return;
+ }
+
+ // Add the event handler to the system.
+ // If we change the types of events processed by this handler, then
+ // we need to change the Disable() routine to match. In order for Disable()
+ // to work properly, both the callback function AND the client data
+ // passed to XtAddEventHandler and XtRemoveEventHandler must MATCH
+ // PERFECTLY
+ XSelectInput(this->DisplayId, this->WindowId,
+ KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask |
+ StructureNotifyMask | EnterWindowMask | LeaveWindowMask | PointerMotionHintMask |
+ PointerMotionMask);
+
+ // Setup for capturing the window deletion
+ this->KillAtom = XInternAtom(this->DisplayId, "WM_DELETE_WINDOW", False);
+ XSetWMProtocols(this->DisplayId, this->WindowId, &this->KillAtom, 1);
+
+ // Enable drag and drop
+ Atom xdndAwareAtom = XInternAtom(this->DisplayId, "XdndAware", False);
+ XChangeProperty(
+ this->DisplayId, this->WindowId, xdndAwareAtom, XA_ATOM, 32, PropModeReplace, &XDND_VERSION, 1);
+ this->XdndURIListAtom = XInternAtom(this->DisplayId, "text/uri-list", False);
+ this->XdndTypeListAtom = XInternAtom(this->DisplayId, "XdndTypeList", False);
+ this->XdndEnterAtom = XInternAtom(this->DisplayId, "XdndEnter", False);
+ this->XdndPositionAtom = XInternAtom(this->DisplayId, "XdndPosition", False);
+ this->XdndDropAtom = XInternAtom(this->DisplayId, "XdndDrop", False);
+ this->XdndActionCopyAtom = XInternAtom(this->DisplayId, "XdndActionCopy", False);
+ this->XdndStatusAtom = XInternAtom(this->DisplayId, "XdndStatus", False);
+ this->XdndFinishedAtom = XInternAtom(this->DisplayId, "XdndFinished", False);
+
+ this->Enabled = 1;
+
+ this->Modified();
+}
+
+//------------------------------------------------------------------------------
+void vtkXRenderWindowInteractor::Disable()
+{
+ if (!this->Enabled)
+ {
+ return;
+ }
+
+ this->Enabled = 0;
+
+ this->Modified();
+}
+
+//------------------------------------------------------------------------------
+void vtkXRenderWindowInteractor::PrintSelf(ostream& os, vtkIndent indent)
+{
+ this->Superclass::PrintSelf(os, indent);
+}
+
+//------------------------------------------------------------------------------
+void vtkXRenderWindowInteractor::UpdateSize(int x, int y)
+{
+ // if the size changed send this on to the RenderWindow
+ if ((x != this->Size[0]) || (y != this->Size[1]))
+ {
+ this->Size[0] = x;
+ this->Size[1] = y;
+ this->RenderWindow->SetSize(x, y);
+ }
+}
+
+//------------------------------------------------------------------------------
+void vtkXRenderWindowInteractor::UpdateSizeNoXResize(int x, int y)
+{
+ // if the size changed send this on to the RenderWindow
+ if ((x != this->Size[0]) || (y != this->Size[1]))
+ {
+ this->Size[0] = x;
+ this->Size[1] = y;
+ // static_cast<vtkXOpenGLRenderWindow*>(this->RenderWindow)->SetSizeNoXResize(x, y);
+ this->RenderWindow->SetSize(x, y);
+ }
+}
+
+//------------------------------------------------------------------------------
+void vtkXRenderWindowInteractor::FireTimers()
+{
+ if (this->GetEnabled())
+ {
+ this->Internal->FireTimers(this);
+ }
+}
+
+//------------------------------------------------------------------------------
+// X always creates one shot timers
+int vtkXRenderWindowInteractor::InternalCreateTimer(
+ int vtkNotUsed(timerId), int vtkNotUsed(timerType), unsigned long duration)
+{
+ duration = (duration > 0 ? duration : this->TimerDuration);
+ int platformTimerId = this->Internal->CreateLocalTimer(duration);
+ return platformTimerId;
+}
+
+//------------------------------------------------------------------------------
+int vtkXRenderWindowInteractor::InternalDestroyTimer(int platformTimerId)
+{
+ this->Internal->DestroyLocalTimer(platformTimerId);
+ return 1;
+}
+
+//------------------------------------------------------------------------------
+void vtkXRenderWindowInteractor::DispatchEvent(XEvent* event)
+{
+ int xp, yp;
+
+ switch (event->type)
+ {
+ case Expose:
+ {
+ if (!this->Enabled)
+ {
+ return;
+ }
+ XEvent result;
+ while (XCheckTypedWindowEvent(this->DisplayId, this->WindowId, Expose, &result))
+ {
+ // just getting the expose configure event
+ event = &result;
+ }
+ auto* exposeEvent = reinterpret_cast<XExposeEvent*>(event);
+ this->SetEventSize(exposeEvent->width, exposeEvent->height);
+ xp = exposeEvent->x;
+ yp = exposeEvent->y;
+ yp = this->Size[1] - yp - 1;
+ this->SetEventPosition(xp, yp);
+
+ // only render if we are currently accepting events
+ if (this->Enabled)
+ {
+ this->InvokeEvent(vtkCommand::ExposeEvent, nullptr);
+ this->Render();
+ }
+ }
+ break;
+
+ case MapNotify:
+ {
+ // only render if we are currently accepting events
+ if (this->Enabled && this->GetRenderWindow()->GetNeverRendered())
+ {
+ this->Render();
+ }
+ }
+ break;
+
+ case ConfigureNotify:
+ {
+ XEvent result;
+ while (XCheckTypedWindowEvent(this->DisplayId, this->WindowId, ConfigureNotify, &result))
+ {
+ // just getting the last configure event
+ event = &result;
+ }
+ int width = (reinterpret_cast<XConfigureEvent*>(event))->width;
+ int height = (reinterpret_cast<XConfigureEvent*>(event))->height;
+ if (width != this->Size[0] || height != this->Size[1])
+ {
+ bool resizeSmaller = width <= this->Size[0] && height <= this->Size[1];
+ this->UpdateSizeNoXResize(width, height);
+ xp = (reinterpret_cast<XButtonEvent*>(event))->x;
+ yp = (reinterpret_cast<XButtonEvent*>(event))->y;
+ this->SetEventPosition(xp, this->Size[1] - yp - 1);
+ // only render if we are currently accepting events
+ if (this->Enabled)
+ {
+ this->InvokeEvent(vtkCommand::ConfigureEvent, nullptr);
+ if (resizeSmaller)
+ {
+ // Don't call Render when the window is resized to be larger:
+ //
+ // - if the window is resized to be larger, an Expose event will
+ // be triggered by the X server which will trigger a call to
+ // Render().
+ // - if the window is resized to be smaller, no Expose event will
+ // be triggered by the X server, as no new area become visible.
+ // only in this case, we need to explicitly call Render()
+ // in ConfigureNotify.
+ this->Render();
+ }
+ }
+ }
+ }
+ break;
+
+ case ButtonPress:
+ {
+ if (!this->Enabled)
+ {
+ return;
+ }
+ int ctrl = ((reinterpret_cast<XButtonEvent*>(event))->state & ControlMask) ? 1 : 0;
+ int shift = ((reinterpret_cast<XButtonEvent*>(event))->state & ShiftMask) ? 1 : 0;
+ int alt = ((reinterpret_cast<XButtonEvent*>(event))->state & Mod1Mask) ? 1 : 0;
+ xp = (reinterpret_cast<XButtonEvent*>(event))->x;
+ yp = (reinterpret_cast<XButtonEvent*>(event))->y;
+
+ // check for double click
+ static int MousePressTime = 0;
+ int repeat = 0;
+ // 400 ms threshold by default is probably good to start
+ int eventTime = static_cast<int>(reinterpret_cast<XButtonEvent*>(event)->time);
+ if ((eventTime - MousePressTime) < 400)
+ {
+ MousePressTime -= 2000; // no double click next time
+ repeat = 1;
+ }
+ else
+ {
+ MousePressTime = eventTime;
+ }
+
+ this->SetEventInformationFlipY(xp, yp, ctrl, shift, 0, repeat);
+ this->SetAltKey(alt);
+ switch ((reinterpret_cast<XButtonEvent*>(event))->button)
+ {
+ case Button1:
+ this->InvokeEvent(vtkCommand::LeftButtonPressEvent, nullptr);
+ break;
+ case Button2:
+ this->InvokeEvent(vtkCommand::MiddleButtonPressEvent, nullptr);
+ break;
+ case Button3:
+ this->InvokeEvent(vtkCommand::RightButtonPressEvent, nullptr);
+ break;
+ case Button4:
+ this->InvokeEvent(vtkCommand::MouseWheelForwardEvent, nullptr);
+ break;
+ case Button5:
+ this->InvokeEvent(vtkCommand::MouseWheelBackwardEvent, nullptr);
+ break;
+ }
+ }
+ break;
+
+ case ButtonRelease:
+ {
+ if (!this->Enabled)
+ {
+ return;
+ }
+ int ctrl = ((reinterpret_cast<XButtonEvent*>(event))->state & ControlMask) ? 1 : 0;
+ int shift = ((reinterpret_cast<XButtonEvent*>(event))->state & ShiftMask) ? 1 : 0;
+ int alt = ((reinterpret_cast<XButtonEvent*>(event))->state & Mod1Mask) ? 1 : 0;
+ xp = (reinterpret_cast<XButtonEvent*>(event))->x;
+ yp = (reinterpret_cast<XButtonEvent*>(event))->y;
+ this->SetEventInformationFlipY(xp, yp, ctrl, shift);
+ this->SetAltKey(alt);
+ switch ((reinterpret_cast<XButtonEvent*>(event))->button)
+ {
+ case Button1:
+ this->InvokeEvent(vtkCommand::LeftButtonReleaseEvent, nullptr);
+ break;
+ case Button2:
+ this->InvokeEvent(vtkCommand::MiddleButtonReleaseEvent, nullptr);
+ break;
+ case Button3:
+ this->InvokeEvent(vtkCommand::RightButtonReleaseEvent, nullptr);
+ break;
+ }
+ }
+ break;
+
+ case EnterNotify:
+ {
+ // Force the keyboard focus to be this render window
+ XSetInputFocus(this->DisplayId, this->WindowId, RevertToPointerRoot, CurrentTime);
+ if (this->Enabled)
+ {
+ auto* e = reinterpret_cast<XEnterWindowEvent*>(event);
+ this->SetEventInformationFlipY(
+ e->x, e->y, (e->state & ControlMask) != 0, (e->state & ShiftMask) != 0);
+ this->SetAltKey(((reinterpret_cast<XButtonEvent*>(event))->state & Mod1Mask) ? 1 : 0);
+ this->InvokeEvent(vtkCommand::EnterEvent, nullptr);
+ }
+ }
+ break;
+
+ case LeaveNotify:
+ {
+ if (this->Enabled)
+ {
+ auto* e = reinterpret_cast<XLeaveWindowEvent*>(event);
+ this->SetEventInformationFlipY(
+ e->x, e->y, (e->state & ControlMask) != 0, (e->state & ShiftMask) != 0);
+ this->SetAltKey(((reinterpret_cast<XButtonEvent*>(event))->state & Mod1Mask) ? 1 : 0);
+ this->InvokeEvent(vtkCommand::LeaveEvent, nullptr);
+ }
+ }
+ break;
+
+ case KeyPress:
+ {
+ if (!this->Enabled)
+ {
+ return;
+ }
+ int ctrl = ((reinterpret_cast<XButtonEvent*>(event))->state & ControlMask) ? 1 : 0;
+ int shift = ((reinterpret_cast<XButtonEvent*>(event))->state & ShiftMask) ? 1 : 0;
+ int alt = ((reinterpret_cast<XButtonEvent*>(event))->state & Mod1Mask) ? 1 : 0;
+ vtkKeySym keySym = XLookupKeysym(reinterpret_cast<XKeyEvent*>(event), 0);
+ char keyCode = keySym < 128 ? static_cast<char>(keySym) : 0;
+ xp = (reinterpret_cast<XKeyEvent*>(event))->x;
+ yp = (reinterpret_cast<XKeyEvent*>(event))->y;
+ this->SetEventInformationFlipY(xp, yp, ctrl, shift, keyCode, 1, XKeysymToString(keySym));
+ this->SetAltKey(alt);
+ this->InvokeEvent(vtkCommand::KeyPressEvent, nullptr);
+ this->InvokeEvent(vtkCommand::CharEvent, nullptr);
+ }
+ break;
+
+ case KeyRelease:
+ {
+ if (!this->Enabled)
+ {
+ return;
+ }
+ int ctrl = ((reinterpret_cast<XButtonEvent*>(event))->state & ControlMask) ? 1 : 0;
+ int shift = ((reinterpret_cast<XButtonEvent*>(event))->state & ShiftMask) ? 1 : 0;
+ int alt = ((reinterpret_cast<XButtonEvent*>(event))->state & Mod1Mask) ? 1 : 0;
+ vtkKeySym keySym = XLookupKeysym(reinterpret_cast<XKeyEvent*>(event), 0);
+ char keyCode = keySym < 128 ? static_cast<char>(keySym) : 0;
+ xp = (reinterpret_cast<XKeyEvent*>(event))->x;
+ yp = (reinterpret_cast<XKeyEvent*>(event))->y;
+ this->SetEventInformationFlipY(xp, yp, ctrl, shift, keyCode, 1, XKeysymToString(keySym));
+ this->SetAltKey(alt);
+ this->InvokeEvent(vtkCommand::KeyReleaseEvent, nullptr);
+ }
+ break;
+
+ case MotionNotify:
+ {
+ if (!this->Enabled)
+ {
+ return;
+ }
+ int ctrl = ((reinterpret_cast<XButtonEvent*>(event))->state & ControlMask) ? 1 : 0;
+ int shift = ((reinterpret_cast<XButtonEvent*>(event))->state & ShiftMask) ? 1 : 0;
+ int alt = ((reinterpret_cast<XButtonEvent*>(event))->state & Mod1Mask) ? 1 : 0;
+
+ // Note that even though the (x,y) location of the pointer is event structure,
+ // we must call XQueryPointer for the hints (motion event compression) to
+ // work properly.
+ this->GetMousePosition(&xp, &yp);
+ this->SetEventInformation(xp, yp, ctrl, shift);
+ this->SetAltKey(alt);
+ this->InvokeEvent(vtkCommand::MouseMoveEvent, nullptr);
+ }
+ break;
+
+ // Selection request for drag and drop has been delivered
+ case SelectionNotify:
+ {
+ // Sanity checks
+ if (!event->xselection.property || !this->XdndSource)
+ {
+ return;
+ }
+
+ // Recover the dropped file
+ char* data = nullptr;
+ Atom actualType;
+ int actualFormat;
+ unsigned long itemCount, bytesAfter;
+ XGetWindowProperty(this->DisplayId, event->xselection.requestor, event->xselection.property,
+ 0, LONG_MAX, False, event->xselection.target, &actualType, &actualFormat, &itemCount,
+ &bytesAfter, reinterpret_cast<unsigned char**>(&data));
+
+ // Conversion checks
+ if ((event->xselection.target != AnyPropertyType && actualType != event->xselection.target) ||
+ itemCount == 0)
+ {
+ return;
+ }
+
+ // Recover filepaths from uris and invoke DropFilesEvent
+ std::stringstream uris(data);
+ std::string uri, protocol, hostname, filePath;
+ std::string unused0, unused1, unused2, unused3;
+ vtkNew<vtkStringArray> filePaths;
+ while (std::getline(uris, uri, '\n'))
+ {
+ if (vtksys::SystemTools::ParseURL(
+ uri, protocol, unused0, unused1, hostname, unused3, filePath, true))
+ {
+ if (protocol == "file" && (hostname.empty() || hostname == "localhost"))
+ {
+ // The uris can be crlf delimited, remove ending \r if any
+ if (filePath.back() == '\r')
+ {
+ filePath.pop_back();
+ }
+
+ // The extracted filepath miss the first slash
+ filePath.insert(0, "/");
+
+ filePaths->InsertNextValue(filePath);
+ }
+ }
+ }
+ this->InvokeEvent(vtkCommand::DropFilesEvent, filePaths);
+ XFree(data);
+
+ // Inform the source the the drag and drop operation was sucessfull
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.type = ClientMessage;
+ reply.xclient.window = this->XdndSource;
+ reply.xclient.message_type = this->XdndFinishedAtom;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = this->WindowId;
+ reply.xclient.data.l[1] = 1;
+
+ if (this->XdndSourceVersion >= 2)
+ {
+ reply.xclient.data.l[2] = this->XdndActionCopyAtom;
+ }
+
+ XSendEvent(this->DisplayId, this->XdndSource, False, NoEventMask, &reply);
+ XFlush(this->DisplayId);
+ this->XdndSource = 0;
+ }
+ break;
+
+ case ClientMessage:
+ {
+ if (event->xclient.message_type == this->XdndEnterAtom)
+ {
+ // Drag and drop event enter the window
+ this->XdndSource = event->xclient.data.l[0];
+
+ // Check version
+ this->XdndSourceVersion = event->xclient.data.l[1] >> 24;
+ if (this->XdndSourceVersion > XDND_VERSION)
+ {
+ return;
+ }
+
+ // Recover the formats provided by the dnd source
+ Atom* formats = nullptr;
+ unsigned long count;
+ bool list = event->xclient.data.l[1] & 1;
+ if (list)
+ {
+ Atom actualType;
+ int actualFormat;
+ unsigned long bytesAfter;
+ XGetWindowProperty(this->DisplayId, this->XdndSource, this->XdndTypeListAtom, 0, LONG_MAX,
+ False, XA_ATOM, &actualType, &actualFormat, &count, &bytesAfter,
+ reinterpret_cast<unsigned char**>(&formats));
+ }
+ else
+ {
+ count = 3;
+ formats = reinterpret_cast<Atom*>(event->xclient.data.l + 2);
+ }
+
+ // Check one of these format is an URI list
+ // Which is the only supported format
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (formats[i] == this->XdndURIListAtom)
+ {
+ this->XdndFormatAtom = XdndURIListAtom;
+ break;
+ }
+ }
+
+ // Free the allocated formats
+ if (list && formats)
+ {
+ XFree(formats);
+ }
+ }
+ if (event->xclient.message_type == this->XdndPositionAtom)
+ {
+ // Drag and drop event inside the window
+ if (this->XdndSource != static_cast<Window>(event->xclient.data.l[0]))
+ {
+ vtkWarningMacro("Only one dnd action at a time is supported");
+ return;
+ }
+
+ // Recover the position
+ int xWindow, yWindow;
+ int xRoot = event->xclient.data.l[2] >> 16;
+ int yRoot = event->xclient.data.l[2] & 0xffff;
+ Window root = DefaultRootWindow(this->DisplayId);
+ Window child;
+ XTranslateCoordinates(
+ this->DisplayId, root, this->WindowId, xRoot, yRoot, &xWindow, &yWindow, &child);
+
+ // Convert it to VTK compatible location
+ double location[2];
+ location[0] = static_cast<double>(xWindow);
+ location[1] = static_cast<double>(this->Size[1] - yWindow - 1);
+ this->InvokeEvent(vtkCommand::UpdateDropLocationEvent, location);
+
+ // Reply that we are ready to copy the dragged data
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.type = ClientMessage;
+ reply.xclient.window = this->XdndSource;
+ reply.xclient.message_type = this->XdndStatusAtom;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = this->WindowId;
+ reply.xclient.data.l[1] = 1; // Always accept the dnd with no rectangle
+ reply.xclient.data.l[2] = 0; // Specify an empty rectangle
+ reply.xclient.data.l[3] = 0;
+ reply.xclient.data.l[4] = this->XdndActionCopyAtom;
+
+ XSendEvent(this->DisplayId, this->XdndSource, False, NoEventMask, &reply);
+ XFlush(this->DisplayId);
+ }
+ else if (event->xclient.message_type == this->XdndDropAtom)
+ {
+ // Item dropped in the window
+ if (this->XdndSource != static_cast<Window>(event->xclient.data.l[0]))
+ {
+ vtkWarningMacro("Only one dnd action at a time is supported");
+ return;
+ }
+
+ if (this->XdndFormatAtom)
+ {
+ // Ask for a conversion of the selection. This will trigger a SelectionNotify event later.
+ Atom xdndSelectionAtom = XInternAtom(this->DisplayId, "XdndSelection", False);
+ XConvertSelection(this->DisplayId, xdndSelectionAtom, this->XdndFormatAtom,
+ xdndSelectionAtom, this->WindowId, CurrentTime);
+ }
+ else if (this->XdndSourceVersion >= 2)
+ {
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.type = ClientMessage;
+ reply.xclient.window = this->XdndSource;
+ ;
+ reply.xclient.message_type = this->XdndFinishedAtom;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = this->WindowId;
+ reply.xclient.data.l[1] = 0; // The drag was rejected
+ reply.xclient.data.l[2] = None;
+
+ XSendEvent(this->DisplayId, this->XdndSource, False, NoEventMask, &reply);
+ XFlush(this->DisplayId);
+ }
+ }
+ else if (static_cast<Atom>(event->xclient.data.l[0]) == this->KillAtom)
+ {
+ this->ExitCallback();
+ }
+ }
+ break;
+ }
+}
+
+//------------------------------------------------------------------------------
+void vtkXRenderWindowInteractor::GetMousePosition(int* x, int* y)
+{
+ Window root, child;
+ int root_x, root_y;
+ unsigned int keys;
+
+ XQueryPointer(this->DisplayId, this->WindowId, &root, &child, &root_x, &root_y, x, y, &keys);
+
+ *y = this->Size[1] - *y - 1;
+}
+
+//------------------------------------------------------------------------------
+// void vtkXRenderWindowInteractor::Timer(XtPointer client_data, XtIntervalId* id)
+// {
+// vtkXRenderWindowInteractorTimer(client_data, id);
+// }
+
+//------------------------------------------------------------------------------
+// void vtkXRenderWindowInteractor::Callback(
+// Widget w, XtPointer client_data, XEvent* event, Boolean* ctd)
+// {
+// vtkXRenderWindowInteractorCallback(w, client_data, event, ctd);
+// }
+} // namespace pcl
* POSSIBILITY OF SUCH DAMAGE.
*
*/
+#include <pcl/console/print.h> // for PCL_DEBUG
#include <pcl/visualization/vtk/vtkRenderWindowInteractorFix.h>
+#include <vtkVersion.h>
+#if __unix__ && VTK_MAJOR_VERSION == 9 && ((VTK_MINOR_VERSION == 0 && (VTK_BUILD_VERSION == 2 || VTK_BUILD_VERSION == 3)) || (VTK_MINOR_VERSION == 1 && VTK_BUILD_VERSION == 0))
+#include <pcl/visualization/vtk/vtkFixedXRenderWindowInteractor.h>
+#endif
#ifndef __APPLE__
vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew ()
{
+#if __unix__ && VTK_MAJOR_VERSION == 9 && ((VTK_MINOR_VERSION == 0 && (VTK_BUILD_VERSION == 2 || VTK_BUILD_VERSION == 3)) || (VTK_MINOR_VERSION == 1 && VTK_BUILD_VERSION == 0))
+// VTK versions 9.0.2, 9.0.3, 9.1.0
+ vtkRenderWindowInteractor* interactor = vtkRenderWindowInteractor::New ();
+ if(interactor->IsA("vtkXRenderWindowInteractor")) {
+ PCL_DEBUG("Using a fixed version of the vtkXRenderWindowInteractor!\n");
+ interactor->Delete ();
+ interactor = pcl::vtkXRenderWindowInteractor::New ();
+ }
+ return (interactor);
+#else
return (vtkRenderWindowInteractor::New ());
+#endif
}
#endif
+++ /dev/null
-/*=========================================================================
-
- Program: Visualization Toolkit
- Module: vtkVertexBufferObject.cxx
-
- Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
- All rights reserved.
- See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notice for more information.
-
-=========================================================================*/
-#include <pcl/visualization/vtk/vtkVertexBufferObject.h>
-
-#include "vtkCellArray.h"
-#include "vtkDataArray.h"
-#include "vtkObject.h"
-#include "vtkObjectFactory.h"
-#include "vtkOpenGLExtensionManager.h"
-#include "vtkOpenGLRenderWindow.h"
-#include "vtkPoints.h"
-#include "vtkRenderWindow.h"
-#include "vtkUnsignedCharArray.h"
-
-#include "vtkgl.h" // Needed for gl data types exposed in API
-#include "vtkOpenGL.h"
-
-//#define VTK_PBO_DEBUG
-//#define VTK_PBO_TIMING
-
-#ifdef VTK_PBO_TIMING
-#include "vtkTimerLog.h"
-#endif
-
-#define GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX 0x9048
-#define GL_GPU_MEM_INFO_CURRENT_AVAILABLE_MEM_NVX 0x9049
-
-// Mapping from Usage values to OpenGL values.
-
-GLenum OpenGLVertexBufferObjectUsage[9]=
-{
- vtkgl::STREAM_DRAW,
- vtkgl::STREAM_READ,
- vtkgl::STREAM_COPY,
- vtkgl::STATIC_DRAW,
- vtkgl::STATIC_READ,
- vtkgl::STATIC_COPY,
- vtkgl::DYNAMIC_DRAW,
- vtkgl::DYNAMIC_READ,
- vtkgl::DYNAMIC_COPY
-};
-
-const char *VertexBufferObjectUsageAsString[9]=
-{
- "StreamDraw",
- "StreamRead",
- "StreamCopy",
- "StaticDraw",
- "StaticRead",
- "StaticCopy",
- "DynamicDraw",
- "DynamicRead",
- "DynamicCopy"
-};
-
-#ifdef VTK_PBO_DEBUG
-#include <pthread.h> // for debugging with MPI, pthread_self()
-#endif
-
-vtkStandardNewMacro(vtkVertexBufferObject);
-//----------------------------------------------------------------------------
-vtkVertexBufferObject::vtkVertexBufferObject()
-{
- this->Handle = 0;
- this->Context = nullptr;
- this->BufferTarget = 0;
- this->Size=0;
- this->Count=0;
- this->ArrayType = 0;
- this->Usage=StaticDraw;
- this->AttributeIndex = -1;
- this->AttributeSize = 0;
- this->AttributeType = GL_INVALID_ENUM;
- this->AttributeNormalized = GL_FALSE;
- this->AttributeStride = 0;
-}
-
-//----------------------------------------------------------------------------
-vtkVertexBufferObject::~vtkVertexBufferObject()
-{
- this->SetContext(nullptr);
-}
-
-//----------------------------------------------------------------------------
-// Description:
-// Returns if the context supports the required extensions.
-bool vtkVertexBufferObject::IsSupported(vtkRenderWindow* win)
-{
- vtkOpenGLRenderWindow* renWin = vtkOpenGLRenderWindow::SafeDownCast(win);
- if (renWin)
- {
- vtkOpenGLExtensionManager* mgr = renWin->GetExtensionManager();
-
- bool vbo=mgr->ExtensionSupported("GL_VERSION_1_5") ||
- mgr->ExtensionSupported("GL_ARB_vertex_buffer_object");
-
- return vbo;
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::LoadRequiredExtensions(
- vtkOpenGLExtensionManager* mgr)
-{
- bool gl15 = mgr->ExtensionSupported("GL_VERSION_1_5")==1;
-
- bool vbo = gl15 || mgr->ExtensionSupported("GL_ARB_vertex_buffer_object");
-
-// const char *glVendor(reinterpret_cast<const char *>(glGetString(GL_VENDOR)));
-
-// // Get available gpu memory
-// const char *glRenderer(reinterpret_cast<const char *>(glGetString(GL_RENDERER)));
-// const char *glVersion(reinterpret_cast<const char *>(glGetString(GL_VERSION)));
-//
-// if (strncmp(glVendor, "NVIDIA", 6) == 0){
-// if (mgr->ExtensionSupported("GL_NVX_gpu_memory_info")){
-// GLint nTotalMemoryInKB = 0;
-// glGetIntegerv(GL_GPU_MEM_INFO_TOTAL_AVAILABLE_MEM_NVX, &nTotalMemoryInKB);
-// }
-// }
-
- if(vbo)
- {
- if(gl15)
- {
- mgr->LoadExtension("GL_VERSION_1_5");
- }
- else
- {
- mgr->LoadCorePromotedExtension("GL_ARB_vertex_buffer_object");
- }
- }
- return vbo;
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::SetContext(vtkRenderWindow* renWin)
-{
- if (this->Context == renWin)
- {
- return;
- }
-
- this->DestroyBuffer();
-
- vtkOpenGLRenderWindow* openGLRenWin = vtkOpenGLRenderWindow::SafeDownCast(renWin);
- this->Context = openGLRenWin;
- if (openGLRenWin)
- {
- if (!this->LoadRequiredExtensions(openGLRenWin->GetExtensionManager()))
- {
- this->Context = nullptr;
- vtkErrorMacro("Required OpenGL extensions not supported by the context.");
- }
- }
-
- this->Modified();
-}
-
-//----------------------------------------------------------------------------
-vtkRenderWindow* vtkVertexBufferObject::GetContext()
-{
- return this->Context;
-}
-
-//----------------------------------------------------------------------------
-//int vtkVertexBufferObject::GetAttributeIndex(){
-// return this->AttributeIndex;
-//}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::SetUserDefinedAttribute(int index, bool normalized/*=false*/, int stride/*=0*/)
-{
- this->AttributeIndex = index;
- SetAttributeNormalized(normalized);
- this->AttributeStride = stride;
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::ResetUserDefinedAttribute()
-{
- this->AttributeIndex = -1;
-}
-
-void vtkVertexBufferObject::SetAttributeNormalized(bool normalized)
-{
- if (normalized)
- {
- this->AttributeNormalized = GL_TRUE;
- }
- else
- {
- this->AttributeNormalized = GL_FALSE;
- }
-
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::Bind()
-{
- if (!this->Context)
- {
- vtkErrorMacro("No context specified. Cannot Bind.");
- return;
- }
-
- this->CreateBuffer();
-
- vtkgl::BindBuffer(static_cast<GLenum>(this->BufferTarget), this->Handle);
-
- if(this->AttributeIndex >= 0){
- vtkgl::VertexAttribPointer(this->AttributeIndex,
- this->AttributeSize,
- this->AttributeType,
- static_cast<GLboolean> (this->AttributeNormalized),
- this->AttributeStride,
- nullptr);
- vtkgl::EnableVertexAttribArray(this->AttributeIndex);
- } else {
- glEnableClientState(this->ArrayType);
- switch(this->ArrayType){
- case GL_VERTEX_ARRAY:
- glVertexPointer(this->AttributeSize, this->AttributeType, this->AttributeStride, nullptr);
- break;
-
- case GL_INDEX_ARRAY:
- glIndexPointer(this->AttributeType, this->AttributeStride, nullptr);
- break;
-
- case GL_COLOR_ARRAY:
- glColorPointer(this->AttributeSize, this->AttributeType, this->AttributeStride, nullptr);
- break;
-
- case GL_NORMAL_ARRAY:
- glNormalPointer(this->AttributeType, this->AttributeStride, nullptr);
- break;
-
- default:
- vtkErrorMacro("Unsupported Array Type: " << this->ArrayType)
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::UnBind()
-{
- if (this->Context && this->Handle && this->BufferTarget){
- vtkgl::BindBuffer(this->BufferTarget, 0);
-
- if(this->AttributeIndex >= 0){
- vtkgl::DisableVertexAttribArray(this->AttributeIndex);
- } else {
- glDisableClientState(this->ArrayType);
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::CreateBuffer()
-{
- this->Context->MakeCurrent();
- if (!this->Handle)
- {
- GLuint ioBuf;
- vtkgl::GenBuffers(1, &ioBuf);
- this->Handle = ioBuf;
- }
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::DestroyBuffer()
-{
- if (this->Context && this->Handle)
- {
- GLuint ioBuf = static_cast<GLuint>(this->Handle);
- vtkgl::DeleteBuffers(1, &ioBuf);
- }
- this->Handle = 0;
-}
-
-//----------------------------------------------------------------------------
-int vtkVertexBufferObject::GetDataTypeSize(int type)
-{
- switch (type)
- {
- vtkTemplateMacro(
- return sizeof(static_cast<VTK_TT>(0))
- );
-
- case VTK_BIT:
- return 0;
- break;
-
- case VTK_STRING:
- return 0;
- break;
-
- case VTK_UNICODE_STRING:
- return 0;
- break;
-
- default:
- vtkGenericWarningMacro(<<"Unsupported data type!");
- }
-
- return 1;
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::Upload(vtkPoints *points)
-{
- this->Count = static_cast<unsigned int> (points->GetNumberOfPoints());
- this->AttributeSize = points->GetData()->GetNumberOfComponents();
- this->AttributeType = GL_FLOAT;
- this->Size = this->Count * this->AttributeSize * GetDataTypeSize(points->GetDataType());
- this->BufferTarget = vtkgl::ARRAY_BUFFER;
- this->ArrayType = GL_VERTEX_ARRAY;
-
- return this->Upload(points->GetVoidPointer(0));
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::Upload(vtkCellArray *verts)
-{
- vtkIdType npts;
- vtkIdType *pts;
- std::vector<unsigned int> indices;
-
- verts->InitTraversal();
- while(verts->GetNextCell(npts, pts) != 0){
- for (std::size_t i=0; i < static_cast<std::size_t>(npts); i++)
- indices.push_back(static_cast<unsigned int> (pts[i]));
- }
-
- this->Count = static_cast<unsigned int> (indices.size());
- this->AttributeSize = 1;
- this->AttributeType = GL_INT;
- this->Size = static_cast<unsigned int> (this->Count * sizeof(unsigned int));
- this->BufferTarget = vtkgl::ELEMENT_ARRAY_BUFFER;
- this->ArrayType = GL_INDEX_ARRAY;
-
- return this->Upload(&indices[0], static_cast <unsigned int> (indices.size()));
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::Upload(unsigned int *indices, unsigned int count)
-{
- this->Count = count;
- this->AttributeSize = 1;
- this->AttributeType = GL_INT;
- this->Size = static_cast<unsigned int> (this->Count * sizeof(unsigned int));
- this->BufferTarget = vtkgl::ELEMENT_ARRAY_BUFFER;
- this->ArrayType = GL_INDEX_ARRAY;
-
- return this->Upload(reinterpret_cast<GLvoid *>(indices));
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::UploadNormals(vtkDataArray *normals)
-{
- return Upload(normals, GL_FLOAT, GL_NORMAL_ARRAY);
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::UploadColors(vtkDataArray *colors)
-{
- return Upload(colors, GL_UNSIGNED_BYTE, GL_COLOR_ARRAY);
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::Upload(vtkDataArray *array)
-{
-// cout << "vtkDataArray" << endl;
- if (!array)
- return false;
-
- this->Count = static_cast<unsigned int> (array->GetNumberOfTuples());
- this->AttributeSize = 3;
- this->AttributeType = GL_UNSIGNED_BYTE;
- if(array->GetNumberOfComponents() == 1){
-// cout << "in here" << endl;
- this->AttributeType = GL_UNSIGNED_INT;
- }
- this->Size = this->Count * array->GetNumberOfComponents() * GetDataTypeSize(array->GetDataType());
- this->BufferTarget = vtkgl::ARRAY_BUFFER;
- this->ArrayType = GL_COLOR_ARRAY;
-
-// cout << "Count: " << this->Count << endl;
-// cout << "Attribute Size: " << this->AttributeSize << endl;
-// cout << "Size: " << this->Size << endl;
-// cout << "Usage:" << VertexBufferObjectUsageAsString[this->Usage] << endl;
-
- return this->Upload(reinterpret_cast<GLvoid *>(array->GetVoidPointer(0)));
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::Upload(vtkDataArray *array, int attributeType, int arrayType)
-{
-// cout << "vtkDataArray - attributeType/Array" << endl;
- this->Count = static_cast<unsigned int> (array->GetNumberOfTuples());
- this->AttributeSize = array->GetNumberOfComponents();
- this->AttributeType = attributeType;
- this->Size = this->Count * this->AttributeSize * GetDataTypeSize(array->GetDataType());
- this->BufferTarget = vtkgl::ARRAY_BUFFER;
- this->ArrayType = arrayType;
-
- return this->Upload(reinterpret_cast<GLvoid *>(array->GetVoidPointer(0)));
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::Upload(vtkUnsignedCharArray *colors)
-{
-// cout << "vtkUnsignedCharArray" << endl;
- this->Count = static_cast<unsigned int> (colors->GetNumberOfTuples());
- this->AttributeSize = colors->GetNumberOfComponents();
- this->AttributeType = GL_UNSIGNED_BYTE;
- this->Size = this->Count * this->AttributeSize * GetDataTypeSize(colors->GetDataType());
- this->BufferTarget = vtkgl::ARRAY_BUFFER;
- this->ArrayType = GL_COLOR_ARRAY;
-
- return this->Upload(reinterpret_cast<GLvoid *>(colors->GetPointer(0)));
-}
-
-//----------------------------------------------------------------------------
-bool vtkVertexBufferObject::Upload(GLvoid* data)
-{
- if (!this->Context)
- {
- vtkErrorMacro("No context specified. Cannot upload data.");
- return false;
- }
-
- this->CreateBuffer();
-
- GLenum usage = OpenGLVertexBufferObjectUsage[this->Usage];
-
-// std::cout << "Pushing " << (this->Size / 1024 / 1024) << "MB to GPU" << std::endl;
-
- this->Bind();
- vtkgl::BufferData(this->BufferTarget, this->Size, data, usage);
- this->UnBind();
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::ReleaseMemory()
-{
- if (this->Context && this->Handle)
- {
- this->Bind();
- vtkgl::BufferData(this->BufferTarget, 0, nullptr, OpenGLVertexBufferObjectUsage[this->Usage]);
- this->Size = 0;
- this->Count = 0;
- }
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObject::PrintSelf(ostream& os, vtkIndent indent)
-{
- this->Superclass::PrintSelf(os, indent);
- os << indent << "Context: " << this->Context << endl;
- os << indent << "Handle: " << this->Handle << endl;
- os << indent << "Size: " << this->Size << endl;
- os << indent << "Count: " << this->Count << endl;
- os << indent << "Usage:" << VertexBufferObjectUsageAsString[this->Usage] << endl;
-}
+++ /dev/null
-/*=========================================================================
-
- Program: Visualization Toolkit
- Module: vtkVertexBufferObjectMapper.cxx
-
- Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
- All rights reserved.
- See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
-
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notice for more information.
-
-=========================================================================*/
-
-#include <iostream>
-
-#include "pcl/visualization/vtk/vtkVertexBufferObject.h"
-#include "pcl/visualization/vtk/vtkVertexBufferObjectMapper.h"
-
-#include "vtkVersion.h"
-#include "vtkCellData.h"
-#include "vtkExecutive.h"
-#include "vtkInformation.h"
-#include "vtkMath.h"
-#include "vtkgl.h"
-#include "vtkObjectFactory.h"
-#include "vtkOpenGL.h"
-#include "vtkOpenGLRenderWindow.h"
-#include "vtkPainterDeviceAdapter.h"
-#include "vtkPointData.h"
-#include "vtkPolyData.h"
-#include "vtkProperty.h"
-#include "vtkRenderer.h"
-#include "vtkRenderWindow.h"
-#include "vtkShaderProgram2.h"
-#include "vtkShader2.h"
-#include "vtkShader2Collection.h"
-#include "vtkUniformVariables.h"
-
-//----------------------------------------------------------------------------
-vtkStandardNewMacro(vtkVertexBufferObjectMapper);
-
-//----------------------------------------------------------------------------
-vtkVertexBufferObjectMapper::vtkVertexBufferObjectMapper()
-{
- initialized = false;
-// shadersInitialized = false;
-
- program = nullptr;
- vertexVbo = vtkVertexBufferObject::New();
- indiceVbo = vtkVertexBufferObject::New();
- colorVbo = vtkVertexBufferObject::New();
- normalVbo = vtkVertexBufferObject::New();
-// normalIndiceVbo = vtkVertexBufferObject::New();
-
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObjectMapper::Render(vtkRenderer *ren, vtkActor *act)
-{
- ren->GetRenderWindow()->MakeCurrent();
-
- if (this->program)
- this->program->SetContext(vtkOpenGLRenderWindow::SafeDownCast(ren->GetRenderWindow()));
-
-// this->InvokeEvent(vtkCommand::StartEvent,NULL);
-// this->GetInputAlgorithm()->Update();
-// this->InvokeEvent(vtkCommand::EndEvent,NULL);
-
- ren->GetRenderWindow()->MakeCurrent();
- this->SetColorModeToMapScalars();
- this->MapScalars(act->GetProperty()->GetOpacity());
-
- if (!this->initialized)
- {
- createVBOs(ren->GetRenderWindow());
- initialized = true;
- }
-
- // If full transparency
- vtkProperty *prop = act->GetProperty();
- if (prop->GetOpacity() <= 0.0)
- return;
-
- // Set point size
- glPointSize(prop->GetPointSize());
-
- // Use program
- if (this->program)
- this->program->Use();
-
- // Bind vertices and indices
- vertexVbo->Bind();
- indiceVbo->Bind();
-
- // Bind colors if present
- if (this->Colors)
- colorVbo->Bind();
-
- // Bind normals if present
- if (this->GetInput()->GetCellData()->GetNormals())
- normalVbo->Bind();
-
- // Draw
- ren->GetRenderWindow()->GetPainterDeviceAdapter()->DrawElements(VTK_VERTEX, indiceVbo->GetCount(), VTK_UNSIGNED_INT, nullptr);
- //glDrawElements(GL_POINTS, indiceVbo->GetCount(), GL_UNSIGNED_INT, 0);
-
- // Unbind vertices and indices
- vertexVbo->UnBind();
- indiceVbo->UnBind();
-
- // Unbind colors if present
- if (this->Colors)
- colorVbo->UnBind();
-
- // Unbind normals if present
- if (this->GetInput()->GetCellData()->GetNormals())
- normalVbo->UnBind();
-
- if (this->program)
- this->program->Restore();
-
-// //Display Normals (WIP for use with a geometry shader)
-// vtkPolyData *input= this->GetInput();
-// vtkDataArray *normals = input->GetCellData()->GetNormals();
-// if (normals){
-// if (this->program)
-// this->program->Use();
-// vertexVbo->Bind();
-// normalVbo->Bind();
-// normalIndiceVbo->Bind();
-//
-// ren->GetRenderWindow()->GetPainterDeviceAdapter()->DrawElements(VTK_VERTEX, normalIndiceVbo->GetCount(), VTK_UNSIGNED_INT, 0);
-//
-// vertexVbo->UnBind();
-// normalVbo->UnBind();
-// normalIndiceVbo->UnBind();
-// if (this->program)
-// this->program->Restore();
-// }
-}
-
-//----------------------------------------------------------------------------
-void vtkVertexBufferObjectMapper::SetInput(vtkPolyData *input)
-{
-// std::cout << "SetInput" << endl;
- if(input)
- {
- this->SetInputDataObject (0, input);
- }
- else
- {
- // Setting a NULL input removes the connection.
- this->SetInputConnection(0, nullptr);
- }
- initialized = false;
-
-}
-
-void vtkVertexBufferObjectMapper::SetInput(vtkDataSet *input)
-{
-// std::cout << "SetInput" << endl;
- if(input)
- {
- this->SetInputDataObject (0, input);
- }
- else
- {
- // Setting a NULL input removes the connection.
- this->SetInputConnection(0, nullptr);
- }
-}
-
-void vtkVertexBufferObjectMapper::createVBOs(vtkRenderWindow* win)
-{
-
- vtkPolyData *input= this->GetInput();
-
- // Create vertex buffer
- vertexVbo->SetContext(win);
- vertexVbo->Upload(input->GetPoints());
-
- // Create index buffer
- indiceVbo->SetContext(win);
- indiceVbo->SetUsage(vtkVertexBufferObject::DynamicDraw);
- indiceVbo->Upload(input->GetVerts());
-
-// int cellFlag = 0;
-// vtkDataArray *scalars = vtkAbstractMapper::
-// GetScalars(this->GetInput(), this->ScalarMode, this->ArrayAccessMode,
-// this->ArrayId, this->ArrayName, cellFlag);
-
-// cout << "Color Mode" << this->GetColorModeAsString() << endl;
-//
-// cout << "ArrayId " << this->ArrayId << endl;
-// cout << "ArrayName " << this->ArrayName << endl;
-// cout << "ScalarVisibility " << this->ScalarVisibility << endl;
-// cout << "scalars " << scalars << endl;
-// cout << "GetLookupTable " << scalars->GetLookupTable() << endl;
-// cout << "LookupTable " << this->LookupTable << endl;
-// cout << "UseLookupTableScalarRange " << this->UseLookupTableScalarRange << endl;
-// cout << "InterpolateScalarsBeforeMapping " << this->InterpolateScalarsBeforeMapping << endl;
-
-// vtkDataArray *scalars = input->GetPointData()->GetScalars();
-// cout << "Number of tuples:" << scalars->GetNumberOfTuples() << endl;
-// cout << "Number of components:" << scalars->GetNumberOfComponents() << endl;
-// float rgb[3];
-// scalars->GetTuple(0, rgb);
-// cout << "r: " << rgb[0] << "\tg: " << rgb[1] << "\tb: " << rgb[2] << endl;
-
-// if(input->GetPointData()->GetScalars()){
-// colorVbo->SetContext(win);
-//
-// int rgb = scalars->GetTuple1(0);
-// std::uint8_t r = (rgb >> 16) & 0x0000ff;
-// std::uint8_t g = (rgb >> 8) & 0x0000ff;
-// std::uint8_t b = (rgb) & 0x0000ff;
-// cout << "r: " << r << "\tg: " << g<< "\tb: " << b << endl;
-//
-// colorVbo->SetAttributeNormalized(true);
-// colorVbo->UploadColors(input->GetPointData()->GetScalars());
-// colorVbo->Upload(input->GetPointData()->GetScalars());
-// }
-
- // todo: This is VERY BAD! We need to figure out where the scalar data is coming from, ie PointData, CellData etc.
- // Then use this as our color data. In addition, scalars need to be mapped correctly via LUTs. Although,
- // writing a glsl shader for these mappings would probably be faster.
- vtkDataArray *scalars = input->GetCellData()->GetScalars();
- if (scalars)
- {
- colorVbo->SetContext(win);
- colorVbo->Upload(input->GetCellData()->GetScalars());
- }
-
-// // Create color buffer
-// this->Colors = this->MapScalars(1.0);
-// if (this->Colors)
-// {
-//
-// colorVbo->SetContext(win);
-// colorVbo->Upload(this->Colors);
-// colorVbo->SetAttributeNormalized(true);
-// colorVbo->UploadColors(this->Colors);
-//
-// cout << "Number of tuples:" << this->Colors->GetNumberOfTuples() << endl;
-// //for (std::size_t i = 0; i < scalars->GetNumberOfTuples(); i++){
-// double rgb[3];
-// this->Colors->GetTuple(0, rgb);
-// cout << "r: " << rgb[0] << "\tg: " << rgb[1] << "\tb: " << rgb[2] << endl;
-//
-// for (std::size_t i = 0; i < this->Colors->GetNumberOfTuples(); i++){
-// double rgb[3];
-// this->Colors->GetTuple(i, rgb);
-// cout << "r: " << rgb[0] << "\tg: " << rgb[1] << "\tb: " << rgb[2] << endl;
-// }
-// colorVbo->Upload(input->GetCellData()->GetScalars());
-// colorVbo->Upload(input->GetPointData()->GetScalars());
-// }
-
- vtkDataArray *normals = input->GetCellData()->GetNormals();
- if (normals)
- {
- normalVbo->SetContext(win);
- normalVbo->UploadNormals(normals);
-
-// //Create normal IBO
-// normalIndiceVbo->SetContext(win);
-// normalIndiceVbo->SetUsage(vtkVertexBufferObject::DynamicDraw);
-//
-// std::vector<unsigned int> indices;
-// for (std::size_t i=0; i < input->GetPoints()->GetNumberOfPoints(); i+=100){
-// indices.push_back(i);
-// }
-//
-// normalIndiceVbo->Upload(&indices[0], indices.size());
- }
-}
-
-//----------------------------------------------------------------------------
-// Specify the input data or filter.
-vtkPolyData *vtkVertexBufferObjectMapper::GetInput()
-{
- return vtkPolyData::SafeDownCast(
- this->GetExecutive()->GetInputData(0, 0));
-}
-
-void vtkVertexBufferObjectMapper::Update()
-{
- cout << "Update" << endl;
- this->Superclass::Update();
-}
-
-// Get the bounds for the input of this mapper as
-// (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
-double *vtkVertexBufferObjectMapper::GetBounds()
-{
- // do we have an input
- if (!this->GetNumberOfInputConnections(0))
- vtkMath::UninitializeBounds(this->Bounds);
- else
- this->ComputeBounds();
-
- return this->Bounds;
-}
-
-void vtkVertexBufferObjectMapper::ComputeBounds()
-{
- this->GetInput()->GetBounds(this->Bounds);
-}
-
-//void vtkVertexBufferObjectMapper::PrintSelf(ostream& os, vtkIndent indent)
-//{
-// this->Superclass::PrintSelf(os,indent);
-//
-//// os << indent << "Piece : " << this->Piece << endl;
-//// os << indent << "NumberOfPieces : " << this->NumberOfPieces << endl;
-//// os << indent << "GhostLevel: " << this->GhostLevel << endl;
-//// os << indent << "Number of sub pieces: " << this->NumberOfSubPieces
-//// << endl;
-//}
-
-//----------------------------------------------------------------------------
-int vtkVertexBufferObjectMapper::FillInputPortInformation(
- int vtkNotUsed( port ), vtkInformation* info)
-{
- info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");
- return 1;
-}