Merge branch 'PropertyManagerRefactoring' into SmartRanges
# Conflicts: # src/OpenMesh/Core/Mesh/PolyConnectivity.hh
This commit is contained in:
206
.gitlab-ci.yml
206
.gitlab-ci.yml
@@ -1,38 +1,175 @@
|
||||
#############################################################
|
||||
# #
|
||||
# This is an auto generated file. Do not make #
|
||||
# changes to this file. They possible will be overriden. #
|
||||
# #
|
||||
# To make persistent changes changes files in #
|
||||
# ./CI/gitlab-ci/ ... #
|
||||
# and regenerate this file with the configuration tool #
|
||||
# #
|
||||
#############################################################
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
gcc-c++11:
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
|
||||
# -----------------
|
||||
# Linux tasks
|
||||
# -----------------
|
||||
|
||||
cppcheck:
|
||||
stage: build
|
||||
script: "CI/ci-linux.sh gcc C++11"
|
||||
script: "CI/ci-cppcheck.sh"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- cppcheck.log
|
||||
|
||||
gcc-c++11-test-debug:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh gcc C++11 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
|
||||
gcc-c++11-test-release:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh gcc C++11 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
gcc-c++11-build-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh gcc C++11 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-debug-gcc-cpp11-Vector-Checks/
|
||||
|
||||
gcc-c++11-build-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh gcc C++11 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-gcc-cpp11-Vector-Checks/
|
||||
|
||||
clang-c++11-test-debug:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh clang C++11 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
clang-c++11-test-release:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh clang C++11 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
clang-c++11-build-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh clang C++11 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-debug-clang-cpp11-Vector-Checks/
|
||||
|
||||
clang-c++11-build-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh clang C++11 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-clang-cpp11-Vector-Checks/
|
||||
|
||||
gcc-c++14-test-debug:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh gcc C++14 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
gcc-c++14-test-release:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh gcc C++14 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
gcc-c++14-build-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh gcc C++14 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-debug-gcc-cpp14-Vector-Checks/
|
||||
|
||||
gcc-c++14-build-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh gcc C++14 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-gcc-cpp14-Vector-Checks/
|
||||
|
||||
clang-c++14-test-debug:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh clang C++14 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
clang-c++14-test-release:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh clang C++14 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
clang-c++14-build-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh clang C++14 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-debug-clang-cpp14-Vector-Checks/
|
||||
|
||||
clang-c++14-build-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh clang C++14 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-clang-cpp14-Vector-Checks/
|
||||
|
||||
# -----------------
|
||||
# Apple tasks
|
||||
# -----------------
|
||||
|
||||
macos-cpp11-debug:
|
||||
stage: build
|
||||
script: "CI/ci-mac-build.sh C++11 debug ; CI/ci-mac-test.sh C++11 debug"
|
||||
tags:
|
||||
- Linux
|
||||
- stretch
|
||||
- Apple
|
||||
|
||||
clang-c++11:
|
||||
macos-cpp14-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux.sh clang C++11"
|
||||
script: "CI/ci-mac-build.sh C++14 debug ; CI/ci-mac-test.sh C++14 debug"
|
||||
tags:
|
||||
- Linux
|
||||
- stretch
|
||||
- Apple
|
||||
|
||||
gcc-c++14:
|
||||
macos-cpp11-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux.sh gcc C++14"
|
||||
tags:
|
||||
- Linux
|
||||
- stretch
|
||||
|
||||
clang-c++14:
|
||||
stage: build
|
||||
script: "CI/ci-linux.sh clang C++14"
|
||||
tags:
|
||||
- Linux
|
||||
- stretch
|
||||
|
||||
macos-cpp11:
|
||||
stage: build
|
||||
script: "CI/ci-mac.sh C++11"
|
||||
script: "CI/ci-mac-build.sh C++11 release ; CI/ci-mac-test.sh C++11 release"
|
||||
tags:
|
||||
- Apple
|
||||
artifacts:
|
||||
@@ -40,9 +177,9 @@ macos-cpp11:
|
||||
- build-release-cpp11/*.dmg
|
||||
- build-release-cpp11/*.tar.gz
|
||||
|
||||
macos-cpp14:
|
||||
macos-cpp14-release:
|
||||
stage: build
|
||||
script: "CI/ci-mac.sh C++14"
|
||||
script: "CI/ci-mac-build.sh C++14 release ; CI/ci-mac-test.sh C++14 release"
|
||||
tags:
|
||||
- Apple
|
||||
artifacts:
|
||||
@@ -50,16 +187,10 @@ macos-cpp14:
|
||||
- build-release-cpp14/*.dmg
|
||||
- build-release-cpp14/*.tar.gz
|
||||
|
||||
cppcheck:
|
||||
stage: build
|
||||
script: "CI/ci-cppcheck.sh"
|
||||
tags:
|
||||
- Linux
|
||||
- stretch
|
||||
artifacts:
|
||||
paths:
|
||||
- cppcheck.log
|
||||
|
||||
# -----------------
|
||||
# Windows tasks
|
||||
# -----------------
|
||||
|
||||
VS2017-64-bit-shared-apps:
|
||||
stage: build
|
||||
variables:
|
||||
@@ -262,7 +393,7 @@ VS2015-32-bit-static-no-apps:
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
|
||||
Doc-publish:
|
||||
stage: deploy
|
||||
only:
|
||||
@@ -286,3 +417,4 @@ Sources:
|
||||
- OpenMesh*.tar.bz2
|
||||
- OpenMesh*.tar.gz
|
||||
|
||||
|
||||
|
||||
@@ -119,6 +119,8 @@ unittests.exe --gtest_output=xml
|
||||
|
||||
unittests_customvec.exe --gtest_output=xml
|
||||
|
||||
unittests_doublevec.exe --gtest_output=xml
|
||||
|
||||
cd ..
|
||||
|
||||
cd ..
|
||||
@@ -147,6 +149,8 @@ unittests.exe --gtest_output=xml
|
||||
|
||||
unittests_customvec.exe --gtest_output=xml
|
||||
|
||||
unittests_doublevec.exe --gtest_output=xml
|
||||
|
||||
IF %errorlevel% NEQ 0 exit /b %errorlevel%
|
||||
|
||||
cd ..
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# Exit script on any error
|
||||
set -e
|
||||
|
||||
CPU_COUNT=$(grep -c processor /proc/cpuinfo)
|
||||
|
||||
#=====================================
|
||||
# Color Settings:
|
||||
#=====================================
|
||||
|
||||
@@ -11,4 +11,4 @@ cmake -DCMAKE_BUILD_TYPE=Release -DOPENMESH_BUILD_UNIT_TESTS=FALSE ../
|
||||
make doc
|
||||
|
||||
# Copy to webserver
|
||||
scp -r -P 2222 Build/share/OpenMesh/Doc/html/* hudson@web4-info8:OpenMesh-Daily/Doc/
|
||||
scp -r -P 2222 Build/share/OpenMesh/Doc/html/* gitlab@web4-info8:OpenMesh-Daily/Doc/
|
||||
|
||||
37
CI/ci-linux-build.sh
Executable file
37
CI/ci-linux-build.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
source CI/ci-linux-prepare.sh
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Basic configuration details:"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
echo "Compiler: $COMPILER"
|
||||
echo "Options: $OPTIONS"
|
||||
echo "Language: $LANGUAGE"
|
||||
echo "Make Options: $OPTIONS"
|
||||
echo "BuildPath: $BUILDPATH"
|
||||
echo "Path: $PATH"
|
||||
echo "Language: $LANGUAGE"
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Building $BUILD_TYPE version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
if [ ! -d build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks ]; then
|
||||
mkdir build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks
|
||||
fi
|
||||
|
||||
cd build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DOPENMESH_BUILD_UNIT_TESTS=TRUE -DSTL_VECTOR_CHECKS=ON $OPTIONS ../
|
||||
|
||||
#build it
|
||||
make $MAKE_OPTIONS
|
||||
|
||||
cd ..
|
||||
59
CI/ci-linux-prepare.sh
Executable file
59
CI/ci-linux-prepare.sh
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
|
||||
COMPILER=$1
|
||||
LANGUAGE=$2
|
||||
BUILD_TYPE=$3
|
||||
|
||||
# Exit script on any error
|
||||
set -e
|
||||
|
||||
OPTIONS=""
|
||||
MAKE_OPTIONS=""
|
||||
BUILDPATH=""
|
||||
|
||||
# set GTEST path
|
||||
OPTIONS="-DGTEST_ROOT=/usr/src/gtest/"
|
||||
|
||||
if [ "$COMPILER" == "gcc" ]; then
|
||||
echo "Building with GCC";
|
||||
BUILDPATH="gcc"
|
||||
|
||||
# without icecc: no options required
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_COMPILER=/usr/bin/g++ -DCMAKE_C_COMPILER=/usr/bin/gcc"
|
||||
MAKE_OPTIONS="-j16"
|
||||
export ICECC_CXX=/usr/bin/g++ ; export ICECC_CC=/usr/bin/gcc
|
||||
|
||||
elif [ "$COMPILER" == "clang" ]; then
|
||||
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang"
|
||||
echo "Building with CLANG";
|
||||
BUILDPATH="clang"
|
||||
fi
|
||||
|
||||
if [ "$LANGUAGE" == "C++98" ]; then
|
||||
echo "Building with C++98";
|
||||
BUILDPATH="$BUILDPATH-cpp98"
|
||||
elif [ "$LANGUAGE" == "C++11" ]; then
|
||||
echo "Building with C++11";
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_FLAGS='-std=c++11' "
|
||||
BUILDPATH="$BUILDPATH-cpp11"
|
||||
elif [ "$LANGUAGE" == "C++14" ]; then
|
||||
echo "Building with C++14";
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_FLAGS='-std=c++14' "
|
||||
BUILDPATH="$BUILDPATH-cpp14"
|
||||
fi
|
||||
|
||||
#=====================================
|
||||
# Color Settings:
|
||||
#=====================================
|
||||
NC='\033[0m'
|
||||
OUTPUT='\033[0;32m'
|
||||
WARNING='\033[0;93m'
|
||||
|
||||
if [ "$BUILD_TYPE" == "release" ]; then
|
||||
export BUILD_TYPE=Release
|
||||
export BUILD_TYPE_L=release
|
||||
else
|
||||
export BUILD_TYPE=Debug
|
||||
export BUILD_TYPE_L=debug
|
||||
fi
|
||||
67
CI/ci-linux-test.sh
Executable file
67
CI/ci-linux-test.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
source CI/ci-linux-prepare.sh
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Basic configuration details:"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
echo "Compiler: $COMPILER"
|
||||
echo "Options: $OPTIONS"
|
||||
echo "Language: $LANGUAGE"
|
||||
echo "Make Options: $OPTIONS"
|
||||
echo "BuildPath: $BUILDPATH"
|
||||
echo "Path: $PATH"
|
||||
echo "Language: $LANGUAGE"
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Building $BUILD_TYPE version unittests"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
if [ ! -d build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks ]; then
|
||||
mkdir build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks
|
||||
fi
|
||||
|
||||
cd build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks
|
||||
|
||||
#build the unit tests
|
||||
make $MAKE_OPTIONS unittests
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests $BUILD_TYPE version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
cd Unittests
|
||||
|
||||
#execute tests
|
||||
./unittests --gtest_color=yes --gtest_output=xml
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests $BUILD_TYPE version with custom vector type"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
./unittests_customvec --gtest_color=yes --gtest_output=xml
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests $BUILD_TYPE version with double vector type"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
#execute tests
|
||||
./unittests_doublevec --gtest_color=yes --gtest_output=xml
|
||||
|
||||
cd ..
|
||||
cd ..
|
||||
159
CI/ci-linux.sh
159
CI/ci-linux.sh
@@ -1,159 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
COMPILER=$1
|
||||
LANGUAGE=$2
|
||||
|
||||
# Exit script on any error
|
||||
set -e
|
||||
|
||||
OPTIONS=""
|
||||
MAKE_OPTIONS=""
|
||||
BUILDPATH=""
|
||||
|
||||
# set GTEST path
|
||||
OPTIONS="-DGTEST_ROOT=~/sw/gtest-1.8.0/"
|
||||
|
||||
if [ "$COMPILER" == "gcc" ]; then
|
||||
echo "Building with GCC";
|
||||
BUILDPATH="gcc"
|
||||
|
||||
# without icecc: no options required
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_COMPILER=/usr/lib/icecc/bin/g++ -DCMAKE_C_COMPILER=/usr/lib/icecc/bin/gcc"
|
||||
MAKE_OPTIONS="-j16"
|
||||
export ICECC_CXX=/usr/bin/g++ ; export ICECC_CC=/usr/bin/gcc
|
||||
|
||||
elif [ "$COMPILER" == "clang" ]; then
|
||||
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang"
|
||||
echo "Building with CLANG";
|
||||
BUILDPATH="clang"
|
||||
fi
|
||||
|
||||
if [ "$LANGUAGE" == "C++98" ]; then
|
||||
echo "Building with C++98";
|
||||
BUILDPATH="$BUILDPATH-cpp98"
|
||||
elif [ "$LANGUAGE" == "C++11" ]; then
|
||||
echo "Building with C++11";
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_FLAGS='-std=c++11' "
|
||||
BUILDPATH="$BUILDPATH-cpp11"
|
||||
elif [ "$LANGUAGE" == "C++14" ]; then
|
||||
echo "Building with C++14";
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_FLAGS='-std=c++14' "
|
||||
BUILDPATH="$BUILDPATH-cpp14"
|
||||
fi
|
||||
|
||||
#=====================================
|
||||
# Color Settings:
|
||||
#=====================================
|
||||
NC='\033[0m'
|
||||
OUTPUT='\033[0;32m'
|
||||
WARNING='\033[0;93m'
|
||||
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Basic configuration details:"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
echo "Compiler: $COMPILER"
|
||||
echo "Options: $OPTIONS"
|
||||
echo "Language: $LANGUAGE"
|
||||
echo "Make Options: $OPTIONS"
|
||||
echo "BuildPath: $BUILDPATH"
|
||||
echo "Path: $PATH"
|
||||
echo "Language: $LANGUAGE"
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Building Release version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
if [ ! -d build-release-$BUILDPATH-Vector-Checks ]; then
|
||||
mkdir build-release-$BUILDPATH-Vector-Checks
|
||||
fi
|
||||
|
||||
cd build-release-$BUILDPATH-Vector-Checks
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DOPENMESH_BUILD_UNIT_TESTS=TRUE -DSTL_VECTOR_CHECKS=ON $OPTIONS ../
|
||||
|
||||
#build it
|
||||
make $MAKE_OPTIONS
|
||||
|
||||
#build the unit tests
|
||||
make $MAKE_OPTIONS unittests
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests Release version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
cd Unittests
|
||||
|
||||
#execute tests
|
||||
./unittests --gtest_color=yes --gtest_output=xml
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests Release version with custom vector type"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
./unittests_customvec --gtest_color=yes --gtest_output=xml
|
||||
|
||||
cd ..
|
||||
cd ..
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Building Debug version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
if [ ! -d build-debug-$BUILDPATH-Vector-Checks ]; then
|
||||
mkdir build-debug-$BUILDPATH-Vector-Checks
|
||||
fi
|
||||
|
||||
cd build-debug-$BUILDPATH-Vector-Checks
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DOPENMESH_BUILD_UNIT_TESTS=TRUE -DSTL_VECTOR_CHECKS=ON $OPTIONS ../
|
||||
|
||||
#build it
|
||||
make $MAKE_OPTIONS
|
||||
|
||||
#build the unit tests
|
||||
make $MAKE_OPTIONS unittests
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests Debug version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
cd Unittests
|
||||
|
||||
#execute tests
|
||||
./unittests --gtest_color=yes --gtest_output=xml
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests Debug version with custom vector type"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
./unittests_customvec --gtest_color=yes --gtest_output=xml
|
||||
|
||||
cd ..
|
||||
cd ..
|
||||
61
CI/ci-mac-build.sh
Executable file
61
CI/ci-mac-build.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
source CI/ci-mac-prepare.sh
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Basic configuration details:"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
echo "Options: $OPTIONS"
|
||||
echo "BuildPath: $BUILDPATH"
|
||||
echo "Path: $PATH"
|
||||
echo "Language: $LANGUAGE"
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Building $BUILD_TYPE version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
if [ ! -d build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks ]; then
|
||||
mkdir build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks
|
||||
fi
|
||||
|
||||
cd build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DOPENMESH_BUILD_UNIT_TESTS=TRUE -DSTL_VECTOR_CHECKS=ON $OPTIONS ../
|
||||
|
||||
#build it
|
||||
make
|
||||
|
||||
cd ..
|
||||
|
||||
if [ "$BUILD_TYPE_L" == "release" ]; then
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Package creation (DMG and tarball)"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
if [ ! -d build-release-$BUILDPATH ]; then
|
||||
mkdir build-release-$BUILDPATH
|
||||
fi
|
||||
|
||||
cd build-release-$BUILDPATH
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_APPS=OFF -DCPACK_BINARY_DRAGNDROP=ON $OPTIONS ../
|
||||
|
||||
#build it
|
||||
make
|
||||
make package
|
||||
|
||||
cd ..
|
||||
|
||||
fi
|
||||
43
CI/ci-mac-prepare.sh
Executable file
43
CI/ci-mac-prepare.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
#Exit on any error
|
||||
set -e
|
||||
|
||||
LANGUAGE=$1
|
||||
BUILD_TYPE=$2
|
||||
|
||||
PATH=$PATH:/opt/local/bin
|
||||
export PATH
|
||||
|
||||
OPTIONS=""
|
||||
|
||||
# set GTEST path
|
||||
OPTIONS="$OPTIONS -DGTEST_ROOT=~/sw/gtest-1.7.0/"
|
||||
|
||||
if [ "$LANGUAGE" == "C++98" ]; then
|
||||
echo "Building with C++98";
|
||||
BUILDPATH="cpp98"
|
||||
elif [ "$LANGUAGE" == "C++11" ]; then
|
||||
echo "Building with C++11";
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_FLAGS='-std=c++11' "
|
||||
BUILDPATH="cpp11"
|
||||
elif [ "$LANGUAGE" == "C++14" ]; then
|
||||
echo "Building with C++14";
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_FLAGS='-std=c++14' "
|
||||
BUILDPATH="cpp14"
|
||||
fi
|
||||
|
||||
#=====================================
|
||||
# Color Settings:
|
||||
#=====================================
|
||||
NC='\033[0m'
|
||||
OUTPUT='\033[0;32m'
|
||||
WARNING='\033[0;93m'
|
||||
|
||||
if [ "$BUILD_TYPE" == "release" ]; then
|
||||
export BUILD_TYPE=Release
|
||||
export BUILD_TYPE_L=release
|
||||
else
|
||||
export BUILD_TYPE=Debug
|
||||
export BUILD_TYPE_L=debug
|
||||
fi
|
||||
65
CI/ci-mac-test.sh
Executable file
65
CI/ci-mac-test.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
source CI/ci-mac-prepare.sh
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Basic configuration details:"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
echo "Options: $OPTIONS"
|
||||
echo "BuildPath: $BUILDPATH"
|
||||
echo "Path: $PATH"
|
||||
echo "Language: $LANGUAGE"
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Building $BUILD_TYPE version unittests"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
if [ ! -d build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks ]; then
|
||||
mkdir build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks
|
||||
fi
|
||||
|
||||
cd build-$BUILD_TYPE_L-$BUILDPATH-Vector-Checks
|
||||
|
||||
#build the unit tests
|
||||
make unittests
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests $BUILD_TYPE version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
cd Unittests
|
||||
|
||||
#execute tests
|
||||
./unittests --gtest_color=yes --gtest_output=xml
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests $BUILD_TYPE version with minimal vector type"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
./unittests_customvec --gtest_color=yes --gtest_output=xml
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests $BUILD_TYPE version with double vector type"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
#execute tests
|
||||
./unittests_doublevec --gtest_color=yes --gtest_output=xml
|
||||
|
||||
cd ..
|
||||
cd ..
|
||||
161
CI/ci-mac.sh
161
CI/ci-mac.sh
@@ -1,161 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
#Exit on any error
|
||||
set -e
|
||||
|
||||
LANGUAGE=$1
|
||||
|
||||
|
||||
PATH=$PATH:/opt/local/bin
|
||||
export PATH
|
||||
|
||||
OPTIONS=""
|
||||
|
||||
# set GTEST path
|
||||
OPTIONS="$OPTIONS -DGTEST_ROOT=~/sw/gtest-1.7.0/"
|
||||
|
||||
if [ "$LANGUAGE" == "C++98" ]; then
|
||||
echo "Building with C++98";
|
||||
BUILDPATH="cpp98"
|
||||
elif [ "$LANGUAGE" == "C++11" ]; then
|
||||
echo "Building with C++11";
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_FLAGS='-std=c++11' "
|
||||
BUILDPATH="cpp11"
|
||||
elif [ "$LANGUAGE" == "C++14" ]; then
|
||||
echo "Building with C++14";
|
||||
OPTIONS="$OPTIONS -DCMAKE_CXX_FLAGS='-std=c++14' "
|
||||
BUILDPATH="cpp14"
|
||||
fi
|
||||
|
||||
#=====================================
|
||||
# Color Settings:
|
||||
#=====================================
|
||||
NC='\033[0m'
|
||||
OUTPUT='\033[0;32m'
|
||||
WARNING='\033[0;93m'
|
||||
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Basic configuration details:"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
echo "Options: $OPTIONS"
|
||||
echo "BuildPath: $BUILDPATH"
|
||||
echo "Path: $PATH"
|
||||
echo "Language: $LANGUAGE"
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Building Release version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
if [ ! -d build-release-$BUILDPATH-Vector-Checks ]; then
|
||||
mkdir build-release-$BUILDPATH-Vector-Checks
|
||||
fi
|
||||
|
||||
cd build-release-$BUILDPATH-Vector-Checks
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DOPENMESH_BUILD_UNIT_TESTS=TRUE -DSTL_VECTOR_CHECKS=ON $OPTIONS ../
|
||||
|
||||
#build it
|
||||
make
|
||||
|
||||
#build the unit tests
|
||||
make unittests
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests Release version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
cd Unittests
|
||||
|
||||
#execute tests
|
||||
./unittests --gtest_color=yes --gtest_output=xml
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests Release version with minimal vector type"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
./unittests_customvec --gtest_color=yes --gtest_output=xml
|
||||
|
||||
cd ..
|
||||
cd ..
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Building Debug version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
if [ ! -d build-debug-$BUILDPATH-Vector-Checks ]; then
|
||||
mkdir build-debug-$BUILDPATH-Vector-Checks
|
||||
fi
|
||||
|
||||
cd build-debug-$BUILDPATH-Vector-Checks
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DOPENMESH_BUILD_UNIT_TESTS=TRUE -DSTL_VECTOR_CHECKS=ON $OPTIONS ../
|
||||
|
||||
#build it
|
||||
make
|
||||
|
||||
#build the unit tests
|
||||
make unittests
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests Debug version with vectorchecks enabled"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
cd Unittests
|
||||
|
||||
#execute tests
|
||||
./unittests --gtest_color=yes --gtest_output=xml
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Running unittests Debug version with minimal vector type"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
./unittests_customvec --gtest_color=yes --gtest_output=xml
|
||||
|
||||
cd ..
|
||||
cd ..
|
||||
|
||||
echo -e "${OUTPUT}"
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Package creation (DMG and tarball)"
|
||||
echo "======================================================================"
|
||||
echo -e "${NC}"
|
||||
|
||||
|
||||
if [ ! -d build-release-$BUILDPATH ]; then
|
||||
mkdir build-release-$BUILDPATH
|
||||
fi
|
||||
|
||||
cd build-release-$BUILDPATH
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_APPS=OFF -DCPACK_BINARY_DRAGNDROP=ON $OPTIONS ../
|
||||
|
||||
#build it
|
||||
make
|
||||
make package
|
||||
111
CI/gitlab-ci/assemble-gitlab-ci.py
Executable file
111
CI/gitlab-ci/assemble-gitlab-ci.py
Executable file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import sys, os, re
|
||||
|
||||
# Script for automated gitlab-ci creation
|
||||
# Assembles the gitlab ci from master template file:
|
||||
master_file = 'ci-master.yml'
|
||||
# Lines in the master file are copied to the resulting
|
||||
# assemblied gitlab ci file
|
||||
target_file = '../../.gitlab-ci.yml'
|
||||
# Lines containing the String {xxx} are interpreted
|
||||
# as import statement. Therefore the file xxx is imported
|
||||
# into that line.
|
||||
error_on_path_redirection = True
|
||||
# Notice that xxx can not contain path redirections
|
||||
# like .. and /
|
||||
|
||||
|
||||
# Prefix to prepend to master file
|
||||
autogenerated_notice = """#############################################################
|
||||
# #
|
||||
# This is an auto generated file. Do not make #
|
||||
# changes to this file. They possible will be overriden. #
|
||||
# #
|
||||
# To make persistent changes changes files in #
|
||||
# ./CI/gitlab-ci/ ... #
|
||||
# and regenerate this file with the configuration tool #
|
||||
# #
|
||||
#############################################################
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# Checks if an import filename is valid - free of path redirections
|
||||
def isValidImportFilename(filenameToImport):
|
||||
if not error_on_path_redirection:
|
||||
return True
|
||||
else:
|
||||
filterRegex = r"(\/|\\|\.\.+)"
|
||||
filtered = re.sub(filterRegex, '', filenameToImport)
|
||||
return filenameToImport == filtered
|
||||
|
||||
# Returns the directory to work on
|
||||
def findCIAssemblyDirectory():
|
||||
pathname = os.path.dirname(sys.argv[0])
|
||||
return os.path.abspath(pathname)
|
||||
|
||||
# Returns file content as string
|
||||
def readFile(filename):
|
||||
file = open(filename, "r")
|
||||
content = file.read()
|
||||
file.close()
|
||||
return content
|
||||
|
||||
# Assembles the file in memory and returns file content as string
|
||||
def assembleTarget(master, depth=3):
|
||||
if depth < 0:
|
||||
raise "Max depth reached. Possible circular import?"
|
||||
|
||||
master_content = readFile(master)
|
||||
regex_import_stmt = r"^\ *\{([^\}\n]+)\}\ *$"
|
||||
regex_import_comp = re.compile(regex_import_stmt)
|
||||
master_content_list = master_content.splitlines()
|
||||
|
||||
# Walk through file looking for import statements
|
||||
cur_index = 0
|
||||
while cur_index < len(master_content_list):
|
||||
cur_line = master_content_list[cur_index]
|
||||
match = regex_import_comp.match(cur_line)
|
||||
|
||||
if match:
|
||||
importFile = match.groups()[0]
|
||||
if importFile:
|
||||
# Found import statement
|
||||
print("Importing file: "+importFile)
|
||||
|
||||
if not isValidImportFilename(importFile):
|
||||
raise "Invalid filename "+importFile+ ". Do not include path redirections"
|
||||
|
||||
import_content = assembleTarget(importFile, depth=depth-1)
|
||||
import_content_list = import_content.splitlines()
|
||||
master_content_list.pop(cur_index)
|
||||
for new_line in reversed(import_content_list):
|
||||
master_content_list.insert(cur_index, new_line)
|
||||
|
||||
cur_index += 1
|
||||
|
||||
# Assemble result
|
||||
master_content = ''.join(str(e)+'\n' for e in master_content_list)
|
||||
return master_content
|
||||
|
||||
# Main function
|
||||
def main():
|
||||
print("Starting config assembly")
|
||||
os.chdir(findCIAssemblyDirectory())
|
||||
target_content = autogenerated_notice
|
||||
target_content += assembleTarget(master_file)
|
||||
print("Writing config to file "+target_file)
|
||||
|
||||
target_file_handle = open(target_file, "w")
|
||||
target_file_handle.write(target_content)
|
||||
target_file_handle.write("\n")
|
||||
target_file_handle.flush()
|
||||
target_file_handle.close()
|
||||
|
||||
print("Finished.")
|
||||
|
||||
|
||||
# Execute main function
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
37
CI/gitlab-ci/ci-master.yml
Normal file
37
CI/gitlab-ci/ci-master.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
|
||||
{linux.yml}
|
||||
|
||||
{mac.yml}
|
||||
|
||||
{windows.yml}
|
||||
|
||||
Doc-publish:
|
||||
stage: deploy
|
||||
only:
|
||||
- master
|
||||
script: "CI/ci-doc.sh"
|
||||
tags:
|
||||
- Linux
|
||||
- stretch
|
||||
|
||||
Sources:
|
||||
stage: deploy
|
||||
only:
|
||||
- master
|
||||
script: "CI/ci-source.sh"
|
||||
tags:
|
||||
- Linux
|
||||
- stretch
|
||||
artifacts:
|
||||
paths:
|
||||
- OpenMesh*.zip
|
||||
- OpenMesh*.tar.bz2
|
||||
- OpenMesh*.tar.gz
|
||||
|
||||
133
CI/gitlab-ci/linux.yml
Normal file
133
CI/gitlab-ci/linux.yml
Normal file
@@ -0,0 +1,133 @@
|
||||
# -----------------
|
||||
# Linux tasks
|
||||
# -----------------
|
||||
|
||||
cppcheck:
|
||||
stage: build
|
||||
script: "CI/ci-cppcheck.sh"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- cppcheck.log
|
||||
|
||||
gcc-c++11-test-debug:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh gcc C++11 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
|
||||
gcc-c++11-test-release:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh gcc C++11 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
gcc-c++11-build-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh gcc C++11 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-debug-gcc-cpp11-Vector-Checks/
|
||||
|
||||
gcc-c++11-build-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh gcc C++11 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-gcc-cpp11-Vector-Checks/
|
||||
|
||||
clang-c++11-test-debug:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh clang C++11 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
clang-c++11-test-release:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh clang C++11 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
clang-c++11-build-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh clang C++11 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-debug-clang-cpp11-Vector-Checks/
|
||||
|
||||
clang-c++11-build-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh clang C++11 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-clang-cpp11-Vector-Checks/
|
||||
|
||||
gcc-c++14-test-debug:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh gcc C++14 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
gcc-c++14-test-release:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh gcc C++14 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
gcc-c++14-build-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh gcc C++14 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-debug-gcc-cpp14-Vector-Checks/
|
||||
|
||||
gcc-c++14-build-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh gcc C++14 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-gcc-cpp14-Vector-Checks/
|
||||
|
||||
clang-c++14-test-debug:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh clang C++14 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
clang-c++14-test-release:
|
||||
stage: test
|
||||
script: "CI/ci-linux-test.sh clang C++14 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
|
||||
clang-c++14-build-debug:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh clang C++14 debug"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-debug-clang-cpp14-Vector-Checks/
|
||||
|
||||
clang-c++14-build-release:
|
||||
stage: build
|
||||
script: "CI/ci-linux-build.sh clang C++14 release"
|
||||
image: graphics.rwth-aachen.de:4567/docker/docker/docker-openmesh-container
|
||||
tags: [Docker]
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-clang-cpp14-Vector-Checks/
|
||||
35
CI/gitlab-ci/mac.yml
Normal file
35
CI/gitlab-ci/mac.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
# -----------------
|
||||
# Apple tasks
|
||||
# -----------------
|
||||
|
||||
macos-cpp11-debug:
|
||||
stage: build
|
||||
script: "CI/ci-mac-build.sh C++11 debug ; CI/ci-mac-test.sh C++11 debug"
|
||||
tags:
|
||||
- Apple
|
||||
|
||||
macos-cpp14-debug:
|
||||
stage: build
|
||||
script: "CI/ci-mac-build.sh C++14 debug ; CI/ci-mac-test.sh C++14 debug"
|
||||
tags:
|
||||
- Apple
|
||||
|
||||
macos-cpp11-release:
|
||||
stage: build
|
||||
script: "CI/ci-mac-build.sh C++11 release ; CI/ci-mac-test.sh C++11 release"
|
||||
tags:
|
||||
- Apple
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-cpp11/*.dmg
|
||||
- build-release-cpp11/*.tar.gz
|
||||
|
||||
macos-cpp14-release:
|
||||
stage: build
|
||||
script: "CI/ci-mac-build.sh C++14 release ; CI/ci-mac-test.sh C++14 release"
|
||||
tags:
|
||||
- Apple
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release-cpp14/*.dmg
|
||||
- build-release-cpp14/*.tar.gz
|
||||
206
CI/gitlab-ci/windows.yml
Normal file
206
CI/gitlab-ci/windows.yml
Normal file
@@ -0,0 +1,206 @@
|
||||
# -----------------
|
||||
# Windows tasks
|
||||
# -----------------
|
||||
|
||||
VS2017-64-bit-shared-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2017"
|
||||
ARCHITECTURE: "x64"
|
||||
SHARED: "TRUE"
|
||||
APPS: "ON"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2017
|
||||
- Qt5101
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
VS2017-64-bit-static-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2017"
|
||||
ARCHITECTURE: "x64"
|
||||
SHARED: "FALSE"
|
||||
APPS: "ON"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2017
|
||||
- Qt5101
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
|
||||
VS2017-64-bit-shared-no-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2017"
|
||||
ARCHITECTURE: "x64"
|
||||
SHARED: "TRUE"
|
||||
APPS: "OFF"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2017
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
|
||||
VS2017-32-bit-shared-no-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2017"
|
||||
ARCHITECTURE: "x32"
|
||||
SHARED: "TRUE"
|
||||
APPS: "OFF"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2017
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
|
||||
VS2017-64-bit-static-no-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2017"
|
||||
ARCHITECTURE: "x64"
|
||||
SHARED: "FALSE"
|
||||
APPS: "OFF"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2017
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
|
||||
VS2017-32-bit-static-no-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2017"
|
||||
ARCHITECTURE: "x32"
|
||||
SHARED: "FALSE"
|
||||
APPS: "OFF"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2017
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
VS2015-64-bit-shared-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2015"
|
||||
ARCHITECTURE: "x64"
|
||||
SHARED: "TRUE"
|
||||
APPS: "ON"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2015
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
|
||||
VS2015-64-bit-shared-no-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2015"
|
||||
ARCHITECTURE: "x64"
|
||||
SHARED: "TRUE"
|
||||
APPS: "OFF"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2015
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
VS2015-32-bit-shared-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2015"
|
||||
ARCHITECTURE: "x32"
|
||||
SHARED: "TRUE"
|
||||
APPS: "ON"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2015
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
VS2015-32-bit-shared-no-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2015"
|
||||
ARCHITECTURE: "x32"
|
||||
SHARED: "TRUE"
|
||||
APPS: "OFF"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2015
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
VS2015-64-bit-static-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2015"
|
||||
ARCHITECTURE: "x64"
|
||||
SHARED: "FALSE"
|
||||
APPS: "ON"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2015
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
VS2015-64-bit-static-no-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2015"
|
||||
ARCHITECTURE: "x64"
|
||||
SHARED: "FALSE"
|
||||
APPS: "OFF"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2015
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
VS2015-32-bit-static-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2015"
|
||||
ARCHITECTURE: "x32"
|
||||
SHARED: "FALSE"
|
||||
APPS: "ON"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2015
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
|
||||
VS2015-32-bit-static-no-apps:
|
||||
stage: build
|
||||
variables:
|
||||
BUILD_PLATFORM: "VS2015"
|
||||
ARCHITECTURE: "x32"
|
||||
SHARED: "FALSE"
|
||||
APPS: "OFF"
|
||||
script: "CI\\Windows.bat"
|
||||
tags:
|
||||
- VS2015
|
||||
artifacts:
|
||||
paths:
|
||||
- build-release/*.exe
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <OpenMesh/Core/IO/MeshIO.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
#include <OpenMesh/Core/Mesh/DefaultTriMesh.hh>
|
||||
#include <OpenMesh/Core/Utils/PropertyManager.hh>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using MyMesh = OpenMesh::TriMesh_ArrayKernelT<>;
|
||||
using MyMesh = OpenMesh::TriMesh;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
@@ -27,7 +27,7 @@ int main(int argc, char** argv)
|
||||
|
||||
{
|
||||
// Add a vertex property storing the computed centers of gravity
|
||||
auto cog = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, MyMesh::Point>(mesh);
|
||||
auto cog = OpenMesh::VProp<MyMesh::Point>(mesh);
|
||||
|
||||
// Smooth the mesh several times
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
|
||||
@@ -11,12 +11,15 @@
|
||||
<b>Core</b>
|
||||
<ul>
|
||||
<li>Property System: Get rid of the OM_FORCE_STATIC_CAST defines. We use the type ids to check if the cast is valid or not. This will add more type safety. </li>
|
||||
<li>Default Traits: Added DefaultTraitsDouble as a version of the default traits that uses double precision for positions and normals as well as float for colors. </li>
|
||||
<li>Default Mesh Types: Added typdefs for a Triangle Mesh and a PolyMesh which use DefaultTraitsDouble and can be used as default mesh type be the user. </li>
|
||||
<li>Template Programming Convenience: Added n_elements which returns the number of elements corresponding to the handle type given as template argument. Also added elements and all_elements methods returning ranges of the elements corresponding to the handle type given as template argument.
|
||||
</ul>
|
||||
|
||||
|
||||
<b>Tools</b>
|
||||
<ul>
|
||||
<li>Subdivider: Fixed crash in Loop subdivider</li>
|
||||
<li>Subdivider: Fixed crash in Loop subdivider</li>
|
||||
<li>Subdivider: Fixed crash in ModifiedButterfly subdivider</li>
|
||||
</ul>
|
||||
|
||||
@@ -25,6 +28,7 @@
|
||||
<ul>
|
||||
<li>Change PropertyManager::operator* to access the property value for mesh properties</li>
|
||||
<li>PropertyManager: add hasProperty function</li>
|
||||
<li>PropertyManager rework: The behavior of the PropertyManager has been changed, hoepfully making it more usable. See tutoial.
|
||||
</ul>
|
||||
|
||||
<b>IO</b>
|
||||
|
||||
@@ -11,34 +11,33 @@ let %OpenMesh manage the data.
|
||||
It would be even more helpful if we could attach such properties
|
||||
dynamically to the mesh.
|
||||
|
||||
Custom properties can be conveniently created and attached to meshes with the following functions:
|
||||
- makeTemporaryProperty() creates a property that is temporary to the current scope.
|
||||
- getOrMakeProperty() is used for creating and accessing permanent named properties on a mesh.
|
||||
- getProperty() is used for accessing an existing permanent named property on a mesh.
|
||||
Custom properties can be conveniently created and attached to meshes by creating an object of type OpenMesh::PropertyManager. A PropertyManager manages the lifetime of the property and provides read / write access to its values.
|
||||
|
||||
All three functions take two template arguments:
|
||||
- First, the type of the mesh element that the property is attached to (i.e. OpenMesh::VertexHandle, OpenMesh::HalfedgeHandle, OpenMesh::EdgeHandle, or OpenMesh::FaceHandle). <em>Mesh properties</em> (i.e. singleton properties that are attached to an entire mesh instead of individual elements) are accessed by passing \c void instead of a handle type.
|
||||
- Second, the type of the property value that is attached to each element (e.g., \p int, \p double, etc.).
|
||||
You can use the typedefs VProp, HProp, EProp, FProp, and MProp in order to create a PropertyManager attached to vertices, halfedge, edges, faces and the mesh respectively. Each of these takes as template argument the type of the property value that is attached to each element (e.g., \p int, \p double, etc.).
|
||||
|
||||
We differentiate between two kinds of properties. <em>Named</em> and <em>temporary</em> properties. Temporary properties are created by just providing the constructor with a mesh on which the property should be created. These properties will be removed as soon as the PropertyManager goes out of scope. If in addition to the mesh a property name is provided, a named property will be created which will stay alive even after the PropertyManager goes out of scope. If a PropertyManager is given a name of an already existing property, it will provide read and write access to the same property.
|
||||
|
||||
Finally, an optional first parameter can be given containing a value that will be used to initialize the property for all elements if the property is freshly created (i.e. always for temporary properties, and only the first time a specific name is used).
|
||||
|
||||
All three functions return a handle object (of type OpenMesh::PropertyManager) that manages the lifetime of the property and provides read / write access to its values.
|
||||
|
||||
Here are a few examples of how to create and access mesh properties:
|
||||
|
||||
\code
|
||||
// Add a temporary mesh property that stores a double value for every vertex
|
||||
auto temperature = OpenMesh::getOrMakeProperty<OpenMesh::VertexHandle, double>(mesh, "temperature");
|
||||
auto temperature = OpenMesh::VProp<double>(mesh);
|
||||
OpenMesh::VertexHandle vh = ...;
|
||||
temperature[vh] = 1.0;
|
||||
// The temperature property will be removed from the mesh when the handle reaches the end of the scope.
|
||||
|
||||
// Obtain an existing mesh property that stores a 2D vector for every halfedge
|
||||
// (Beware: the next line might throw if the expected property doesn't exist.)
|
||||
auto uv = OpenMesh::getProperty<OpenMesh::HalfedgeHandle, OpenMesh::Vec2d>(mesh, "uv");
|
||||
// Obtain an existing property that stores a 2D vector for every halfedge
|
||||
// (or create that property if it does not exist already) and initilize it with the Vector(1,1))
|
||||
auto uv = OpenMesh::HProp<OpenMesh::Vec2d>(mesh, "uv", OpenMesh::Vec2d(1,1));
|
||||
OpenMesh::VertexHandle heh = ...;
|
||||
std::cout << temperature[heh][0] << " " << temperature[heh][1] << std::endl;
|
||||
|
||||
// Add a permanent mesh property containing a description string
|
||||
auto desc = OpenMesh::getOrMakeProperty<void, std::string>(mesh, "desc");
|
||||
// Obtain an existing mesh property (or create that property if it does not exist already)
|
||||
// containing a description string
|
||||
auto desc = OpenMesh::MProp<std::string>(mesh, "desc");
|
||||
*desc = "This is a very nice mesh.";
|
||||
\endcode
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/** \page tutorial_09 Using custom properties
|
||||
/** \page tutorial_09 Using custom properties (old style)
|
||||
|
||||
This small code example shows how to attach andaccess additional properties on a mesh.
|
||||
This small code example shows how to attach and access additional properties on a mesh.
|
||||
|
||||
<em>Note that this is an old style of using properties. Nowadays you should use the OpenMesh::PropertyManager instead.</em>
|
||||
|
||||
When you want to add an additional properties you have to attach it to a primitive of the
|
||||
mesh. You can attach to verticies, halfedges, edges, faces or to the mesh itself. Use the
|
||||
|
||||
@@ -105,10 +105,26 @@ public:
|
||||
FAttribs = MeshItems::FAttribs
|
||||
};
|
||||
|
||||
typedef VPropHandleT<VertexData> DataVPropHandle;
|
||||
typedef HPropHandleT<HalfedgeData> DataHPropHandle;
|
||||
typedef EPropHandleT<EdgeData> DataEPropHandle;
|
||||
typedef FPropHandleT<FaceData> DataFPropHandle;
|
||||
typedef VPropHandleT<VertexData> DataVPropHandle;
|
||||
typedef HPropHandleT<HalfedgeData> DataHPropHandle;
|
||||
typedef EPropHandleT<EdgeData> DataEPropHandle;
|
||||
typedef FPropHandleT<FaceData> DataFPropHandle;
|
||||
|
||||
typedef VPropHandleT<Point> PointsPropertyHandle;
|
||||
typedef VPropHandleT<Normal> VertexNormalsPropertyHandle;
|
||||
typedef VPropHandleT<Color> VertexColorsPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord1D> VertexTexCoords1DPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord2D> VertexTexCoords2DPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord3D> VertexTexCoords3DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord1D> HalfedgeTexCoords1DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord2D> HalfedgeTexCoords2DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord3D> HalfedgeTexCoords3DPropertyHandle;
|
||||
typedef EPropHandleT<Color> EdgeColorsPropertyHandle;
|
||||
typedef HPropHandleT<Normal> HalfedgeNormalsPropertyHandle;
|
||||
typedef HPropHandleT<Color> HalfedgeColorsPropertyHandle;
|
||||
typedef FPropHandleT<Normal> FaceNormalsPropertyHandle;
|
||||
typedef FPropHandleT<Color> FaceColorsPropertyHandle;
|
||||
typedef FPropHandleT<TextureIndex> FaceTextureIndexPropertyHandle;
|
||||
|
||||
public:
|
||||
|
||||
@@ -240,6 +256,9 @@ public:
|
||||
void set_point(VertexHandle _vh, const Point& _p)
|
||||
{ this->property(points_, _vh) = _p; }
|
||||
|
||||
PointsPropertyHandle& points_property_handle()
|
||||
{ return points_; }
|
||||
|
||||
|
||||
//------------------------------------------------------------ vertex normals
|
||||
|
||||
@@ -592,24 +611,6 @@ public:
|
||||
bool has_face_colors() const { return face_colors_.is_valid(); }
|
||||
bool has_face_texture_index() const { return face_texture_index_.is_valid(); }
|
||||
|
||||
public:
|
||||
|
||||
typedef VPropHandleT<Point> PointsPropertyHandle;
|
||||
typedef VPropHandleT<Normal> VertexNormalsPropertyHandle;
|
||||
typedef VPropHandleT<Color> VertexColorsPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord1D> VertexTexCoords1DPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord2D> VertexTexCoords2DPropertyHandle;
|
||||
typedef VPropHandleT<TexCoord3D> VertexTexCoords3DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord1D> HalfedgeTexCoords1DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord2D> HalfedgeTexCoords2DPropertyHandle;
|
||||
typedef HPropHandleT<TexCoord3D> HalfedgeTexCoords3DPropertyHandle;
|
||||
typedef EPropHandleT<Color> EdgeColorsPropertyHandle;
|
||||
typedef HPropHandleT<Normal> HalfedgeNormalsPropertyHandle;
|
||||
typedef HPropHandleT<Color> HalfedgeColorsPropertyHandle;
|
||||
typedef FPropHandleT<Normal> FaceNormalsPropertyHandle;
|
||||
typedef FPropHandleT<Color> FaceColorsPropertyHandle;
|
||||
typedef FPropHandleT<TextureIndex> FaceTextureIndexPropertyHandle;
|
||||
|
||||
public:
|
||||
//standard vertex properties
|
||||
PointsPropertyHandle points_pph() const
|
||||
|
||||
@@ -516,7 +516,7 @@ public:
|
||||
// Copy all properties, if build in is true
|
||||
// Otherwise, copy only properties without build in specifier
|
||||
if ( *p_it && ( _copyBuildIn || (*p_it)->name().substr(0,2) != "v:" ) )
|
||||
(*p_it)->copy(_vh_from.idx(), _vh_to.idx());
|
||||
(*p_it)->copy(static_cast<size_t>(_vh_from.idx()), static_cast<size_t>(_vh_to.idx()));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -690,6 +690,9 @@ public: //----------------------------------------------------- element numbers
|
||||
virtual size_t n_edges() const { return 0; }
|
||||
virtual size_t n_faces() const { return 0; }
|
||||
|
||||
template <typename HandleT>
|
||||
size_t n_elements() const;
|
||||
|
||||
|
||||
protected: //------------------------------------------- synchronize properties
|
||||
|
||||
@@ -814,6 +817,16 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
inline size_t BaseKernel::n_elements<VertexHandle>() const { return n_vertices(); }
|
||||
template <>
|
||||
inline size_t BaseKernel::n_elements<HalfedgeHandle>() const { return n_halfedges(); }
|
||||
template <>
|
||||
inline size_t BaseKernel::n_elements<EdgeHandle>() const { return n_edges(); }
|
||||
template <>
|
||||
inline size_t BaseKernel::n_elements<FaceHandle>() const { return n_faces(); }
|
||||
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
|
||||
66
src/OpenMesh/Core/Mesh/DefaultPolyMesh.hh
Normal file
66
src/OpenMesh/Core/Mesh/DefaultPolyMesh.hh
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ========================================================================= *
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (c) 2001-2019, RWTH-Aachen University *
|
||||
* Department of Computer Graphics and Multimedia *
|
||||
* All rights reserved. *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* This file is part of OpenMesh. *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer. *
|
||||
* *
|
||||
* 2. 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. *
|
||||
* *
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER *
|
||||
* 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. *
|
||||
* *
|
||||
* ========================================================================= */
|
||||
|
||||
|
||||
#ifndef OPENMESH_DEFAULTPOLYMESH_HH
|
||||
#define OPENMESH_DEFAULTPOLYMESH_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
//== TYPEDEFS =================================================================
|
||||
|
||||
typedef PolyMesh_ArrayKernelT<DefaultTraitsDouble> PolyMesh;
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_DEFAULTPOLYMESH_HH defined
|
||||
//=============================================================================
|
||||
66
src/OpenMesh/Core/Mesh/DefaultTriMesh.hh
Normal file
66
src/OpenMesh/Core/Mesh/DefaultTriMesh.hh
Normal file
@@ -0,0 +1,66 @@
|
||||
/* ========================================================================= *
|
||||
* *
|
||||
* OpenMesh *
|
||||
* Copyright (c) 2001-2019, RWTH-Aachen University *
|
||||
* Department of Computer Graphics and Multimedia *
|
||||
* All rights reserved. *
|
||||
* www.openmesh.org *
|
||||
* *
|
||||
*---------------------------------------------------------------------------*
|
||||
* This file is part of OpenMesh. *
|
||||
*---------------------------------------------------------------------------*
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions *
|
||||
* are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer. *
|
||||
* *
|
||||
* 2. 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. *
|
||||
* *
|
||||
* 3. Neither the name of the copyright holder 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 HOLDER *
|
||||
* 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. *
|
||||
* *
|
||||
* ========================================================================= */
|
||||
|
||||
|
||||
#ifndef OPENMESH_DEFAULTTRIMESH_HH
|
||||
#define OPENMESH_DEFAULTTRIMESH_HH
|
||||
|
||||
|
||||
//== INCLUDES =================================================================
|
||||
|
||||
#include <OpenMesh/Core/Mesh/Traits.hh>
|
||||
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
|
||||
|
||||
//== NAMESPACES ===============================================================
|
||||
|
||||
namespace OpenMesh {
|
||||
|
||||
//== TYPEDEFS =================================================================
|
||||
|
||||
typedef TriMesh_ArrayKernelT<DefaultTraitsDouble> TriMesh;
|
||||
|
||||
//=============================================================================
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_DEFAULTTRIMESH_HH defined
|
||||
//=============================================================================
|
||||
@@ -1099,6 +1099,9 @@ public:
|
||||
&PolyConnectivity::faces_end>> ConstFaceRangeSkipping;
|
||||
|
||||
|
||||
template <typename HandleType>
|
||||
struct ElementRange;
|
||||
|
||||
/**
|
||||
* @return The vertices as a range object suitable
|
||||
* for C++11 range based for loops. Will skip deleted vertices.
|
||||
@@ -1147,12 +1150,26 @@ public:
|
||||
*/
|
||||
ConstFaceRange all_faces() const;
|
||||
|
||||
/**
|
||||
* @return The elements corresponding to the template type as a range object suitable
|
||||
* for C++11 range based for loops. Will skip deleted faces.
|
||||
*/
|
||||
template <typename HandleType>
|
||||
typename ElementRange<HandleType>::RangeSkipping elements() const;
|
||||
|
||||
/**
|
||||
* @return The elements corresponding to the template type as a range object suitable
|
||||
* for C++11 range based for loops. Will include deleted faces.
|
||||
*/
|
||||
template <typename HandleType>
|
||||
typename ElementRange<HandleType>::Range all_elements() const;
|
||||
|
||||
|
||||
typedef CirculatorRange<CirculatorRangeTraitT<
|
||||
PolyConnectivity,
|
||||
ConstVertexVertexCWIter,
|
||||
VertexHandle,
|
||||
VertexHandle,
|
||||
VertexHandle,
|
||||
VertexHandle,
|
||||
&PolyConnectivity::cvv_cwbegin,
|
||||
&PolyConnectivity::cvv_cwend>> ConstVertexVertexRange;
|
||||
typedef CirculatorRange<CirculatorRangeTraitT<
|
||||
@@ -1524,6 +1541,34 @@ private: // Working storage for add_face()
|
||||
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PolyConnectivity::ElementRange<VertexHandle>
|
||||
{
|
||||
using Range = ConstVertexRange;
|
||||
using RangeSkipping = ConstVertexRangeSkipping;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PolyConnectivity::ElementRange<HalfedgeHandle>
|
||||
{
|
||||
using Range = ConstHalfedgeRange;
|
||||
using RangeSkipping = ConstHalfedgeRangeSkipping;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PolyConnectivity::ElementRange<EdgeHandle>
|
||||
{
|
||||
using Range = ConstEdgeRange;
|
||||
using RangeSkipping = ConstEdgeRangeSkipping;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PolyConnectivity::ElementRange<FaceHandle>
|
||||
{
|
||||
using Range = ConstFaceRange;
|
||||
using RangeSkipping = ConstFaceRangeSkipping;
|
||||
};
|
||||
|
||||
}//namespace OpenMesh
|
||||
|
||||
|
||||
@@ -1569,6 +1614,7 @@ class EntityRange : public SmartRangeT<EntityRange<RangeTraitT>, typename RangeT
|
||||
typename RangeTraitT::CONTAINER_TYPE &container_;
|
||||
};
|
||||
|
||||
|
||||
/// Generic class for iterator ranges.
|
||||
template <typename CirculatorRangeTraitT>
|
||||
//class CirculatorRange : public SmartRangeT<CirculatorRange<CirculatorRangeTraitT>, decltype (make_smart(std::declval<typename CirculatorRangeTraitT::TO_ENTITYE_TYPE>(), std::declval<PolyConnectivity>()))>{
|
||||
@@ -1592,7 +1638,6 @@ class CirculatorRange : public SmartRangeT<CirculatorRange<CirculatorRangeTraitT
|
||||
CENTER_ENTITY_TYPE center_;
|
||||
};
|
||||
|
||||
|
||||
inline PolyConnectivity::ConstVertexRangeSkipping PolyConnectivity::vertices() const { return ConstVertexRangeSkipping(*this); }
|
||||
inline PolyConnectivity::ConstVertexRange PolyConnectivity::all_vertices() const { return ConstVertexRange(*this); }
|
||||
inline PolyConnectivity::ConstHalfedgeRangeSkipping PolyConnectivity::halfedges() const { return ConstHalfedgeRangeSkipping(*this); }
|
||||
@@ -1602,6 +1647,15 @@ inline PolyConnectivity::ConstEdgeRange PolyConnectivity::all_edges(
|
||||
inline PolyConnectivity::ConstFaceRangeSkipping PolyConnectivity::faces() const { return ConstFaceRangeSkipping(*this); }
|
||||
inline PolyConnectivity::ConstFaceRange PolyConnectivity::all_faces() const { return ConstFaceRange(*this); }
|
||||
|
||||
template <> inline PolyConnectivity::ConstVertexRangeSkipping PolyConnectivity::elements<VertexHandle>() const { return vertices(); }
|
||||
template <> inline PolyConnectivity::ConstVertexRange PolyConnectivity::all_elements<VertexHandle>() const { return all_vertices(); }
|
||||
template <> inline PolyConnectivity::ConstHalfedgeRangeSkipping PolyConnectivity::elements<HalfedgeHandle>() const { return halfedges(); }
|
||||
template <> inline PolyConnectivity::ConstHalfedgeRange PolyConnectivity::all_elements<HalfedgeHandle>() const { return all_halfedges(); }
|
||||
template <> inline PolyConnectivity::ConstEdgeRangeSkipping PolyConnectivity::elements<EdgeHandle>() const { return edges(); }
|
||||
template <> inline PolyConnectivity::ConstEdgeRange PolyConnectivity::all_elements<EdgeHandle>() const { return all_edges(); }
|
||||
template <> inline PolyConnectivity::ConstFaceRangeSkipping PolyConnectivity::elements<FaceHandle>() const { return faces(); }
|
||||
template <> inline PolyConnectivity::ConstFaceRange PolyConnectivity::all_elements<FaceHandle>() const { return all_faces(); }
|
||||
|
||||
inline PolyConnectivity::ConstVertexVertexRange PolyConnectivity::vv_range(VertexHandle _vh) const {
|
||||
return ConstVertexVertexRange(*this, _vh);
|
||||
}
|
||||
|
||||
@@ -152,6 +152,24 @@ struct DefaultTraits
|
||||
FaceAttributes(0);
|
||||
};
|
||||
|
||||
/** \class DefaultTraitsDouble Traits.hh <OpenMesh/Mesh/Traits.hh>
|
||||
|
||||
Version of Default Traits that uses double precision for points and
|
||||
normals as well as floating point vectors for colors
|
||||
|
||||
\see The Mesh docu section on \ref mesh_type.
|
||||
\see Traits.hh for a list of macros for traits classes.
|
||||
*/
|
||||
struct DefaultTraitsDouble : public DefaultTraits
|
||||
{
|
||||
/// Use double precision points
|
||||
typedef OpenMesh::Vec3d Point;
|
||||
/// Use double precision Normals
|
||||
typedef OpenMesh::Vec3d Normal;
|
||||
/// Use RGBA Color
|
||||
typedef OpenMesh::Vec4f Color;
|
||||
};
|
||||
|
||||
|
||||
//== CLASS DEFINITION =========================================================
|
||||
|
||||
|
||||
@@ -485,6 +485,7 @@ struct VPropHandleT : public BasePropHandleT<T>
|
||||
{
|
||||
typedef T Value;
|
||||
typedef T value_type;
|
||||
typedef VertexHandle Handle;
|
||||
|
||||
explicit VPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
|
||||
explicit VPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
|
||||
@@ -499,6 +500,7 @@ struct HPropHandleT : public BasePropHandleT<T>
|
||||
{
|
||||
typedef T Value;
|
||||
typedef T value_type;
|
||||
typedef HalfedgeHandle Handle;
|
||||
|
||||
explicit HPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
|
||||
explicit HPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
|
||||
@@ -513,6 +515,7 @@ struct EPropHandleT : public BasePropHandleT<T>
|
||||
{
|
||||
typedef T Value;
|
||||
typedef T value_type;
|
||||
typedef EdgeHandle Handle;
|
||||
|
||||
explicit EPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
|
||||
explicit EPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
|
||||
@@ -527,6 +530,7 @@ struct FPropHandleT : public BasePropHandleT<T>
|
||||
{
|
||||
typedef T Value;
|
||||
typedef T value_type;
|
||||
typedef FaceHandle Handle;
|
||||
|
||||
explicit FPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
|
||||
explicit FPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
|
||||
@@ -541,11 +545,39 @@ struct MPropHandleT : public BasePropHandleT<T>
|
||||
{
|
||||
typedef T Value;
|
||||
typedef T value_type;
|
||||
typedef void Handle;
|
||||
|
||||
explicit MPropHandleT(int _idx=-1) : BasePropHandleT<T>(_idx) {}
|
||||
explicit MPropHandleT(const BasePropHandleT<T>& _b) : BasePropHandleT<T>(_b) {}
|
||||
};
|
||||
|
||||
template <typename HandleT>
|
||||
struct PropHandle;
|
||||
|
||||
template <>
|
||||
struct PropHandle<VertexHandle> {
|
||||
template <typename T>
|
||||
using type = VPropHandleT<T>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PropHandle<HalfedgeHandle> {
|
||||
template <typename T>
|
||||
using type = HPropHandleT<T>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PropHandle<EdgeHandle> {
|
||||
template <typename T>
|
||||
using type = EPropHandleT<T>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct PropHandle<FaceHandle> {
|
||||
template <typename T>
|
||||
using type = FPropHandleT<T>;
|
||||
};
|
||||
|
||||
} // namespace OpenMesh
|
||||
//=============================================================================
|
||||
#endif // OPENMESH_PROPERTY_HH defined
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#include <OpenMesh/Core/System/config.h>
|
||||
#include <OpenMesh/Core/Utils/HandleToPropHandle.hh>
|
||||
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
@@ -59,6 +60,8 @@ namespace OpenMesh {
|
||||
* makeTemporaryProperty(), getProperty(), and getOrMakeProperty()
|
||||
* to construct a PropertyManager, e.g.
|
||||
*
|
||||
* Note that the second template parameter is depcretated.
|
||||
*
|
||||
* \code
|
||||
* {
|
||||
* TriMesh mesh;
|
||||
@@ -73,27 +76,54 @@ namespace OpenMesh {
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
template<typename PROPTYPE, typename MeshT>
|
||||
template<typename PROPTYPE, typename MeshT = int>
|
||||
class PropertyManager {
|
||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
|
||||
public:
|
||||
PropertyManager(const PropertyManager&) = delete;
|
||||
PropertyManager& operator=(const PropertyManager&) = delete;
|
||||
#else
|
||||
using Value = typename PROPTYPE::Value;
|
||||
using value_type = typename PROPTYPE::value_type;
|
||||
using Handle = typename PROPTYPE::Handle;
|
||||
using Self = PropertyManager<PROPTYPE, MeshT>;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Noncopyable because there aren't no straightforward copy semantics.
|
||||
*/
|
||||
PropertyManager(const PropertyManager&);
|
||||
// Mesh properties (MPropHandleT<...>) are stored differently than the other properties.
|
||||
// This class implements different behavior when copying or swapping data from one
|
||||
// property manager to a another one.
|
||||
template <typename PropertyManager2, typename PropHandleT>
|
||||
struct StorageT;
|
||||
|
||||
/**
|
||||
* Noncopyable because there aren't no straightforward copy semantics.
|
||||
*/
|
||||
PropertyManager& operator=(const PropertyManager&);
|
||||
#endif
|
||||
// specialization for Mesh Properties
|
||||
template <typename PropertyManager2>
|
||||
struct StorageT<PropertyManager2, MPropHandleT<Value>> {
|
||||
static void copy(const PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
|
||||
*to = *from;
|
||||
}
|
||||
static void swap(PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
|
||||
std::swap(*to, *from);
|
||||
}
|
||||
};
|
||||
|
||||
// definition for other Mesh Properties
|
||||
template <typename PropertyManager2, typename PropHandleT>
|
||||
struct StorageT {
|
||||
static void copy(const PropertyManager<PROPTYPE, MeshT>& from, PropertyManager2& to) {
|
||||
from.copy_to(from.mesh_.template all_elements<Handle>(), to, to.mesh_.template all_elements<Handle>());
|
||||
}
|
||||
static void swap(PropertyManager<PROPTYPE, MeshT>& lhs, PropertyManager2& rhs) {
|
||||
std::swap(lhs.mesh_.property(lhs.prop_).data_vector(), rhs.mesh_.property(rhs.prop_).data_vector());
|
||||
// resize the property to the correct size
|
||||
lhs.mesh_.property(lhs.prop_).resize(lhs.mesh_.template n_elements<Handle>());
|
||||
rhs.mesh_.property(rhs.prop_).resize(rhs.mesh_.template n_elements<Handle>());
|
||||
}
|
||||
};
|
||||
|
||||
using Storage = StorageT<Self, PROPTYPE>;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @deprecated Use a constructor without \p existing and check existance with hasProperty() instead.
|
||||
*
|
||||
* Constructor.
|
||||
*
|
||||
* Throws an \p std::runtime_error if \p existing is true and
|
||||
@@ -107,22 +137,114 @@ class PropertyManager {
|
||||
* the instance merely acts as a convenience wrapper around an existing property with no
|
||||
* lifecycle management whatsoever.
|
||||
*
|
||||
* @see PropertyManager::createIfNotExists, makePropertyManagerFromNew,
|
||||
* makePropertyManagerFromExisting, makePropertyManagerFromExistingOrNew
|
||||
* @see PropertyManager::getOrMakeProperty, PropertyManager::getProperty,
|
||||
* PropertyManager::makeTemporaryProperty
|
||||
*/
|
||||
PropertyManager(MeshT &mesh, const char *propname, bool existing = false) : mesh_(&mesh), retain_(existing), name_(propname) {
|
||||
OM_DEPRECATED("Use the constructor without parameter 'existing' instead. Check for existance with hasProperty") // As long as this overload exists, initial value must be first parameter due to ambiguity for properties of type bool
|
||||
PropertyManager(PolyConnectivity& mesh, const char *propname, bool existing) : mesh_(mesh), retain_(existing), name_(propname) {
|
||||
if (existing) {
|
||||
if (!mesh_->get_property_handle(prop_, propname)) {
|
||||
if (!mesh_.get_property_handle(prop_, propname)) {
|
||||
std::ostringstream oss;
|
||||
oss << "Requested property handle \"" << propname << "\" does not exist.";
|
||||
throw std::runtime_error(oss.str());
|
||||
}
|
||||
} else {
|
||||
mesh_->add_property(prop_, propname);
|
||||
mesh_.add_property(prop_, propname);
|
||||
}
|
||||
}
|
||||
|
||||
PropertyManager() : mesh_(0), retain_(false) {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Asks for a property with name propname and creates one if none exists. Lifetime is not managed.
|
||||
*
|
||||
* @param mesh The mesh on which to create the property.
|
||||
* @param propname The name of the property.
|
||||
*/
|
||||
PropertyManager(PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
|
||||
if (!mesh_.get_property_handle(prop_, propname)) {
|
||||
mesh_.add_property(prop_, propname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Asks for a property with name propname and creates one if none exists. Lifetime is not managed.
|
||||
*
|
||||
* @param initial_value If the proeprty is newly created, it will be initialized with intial_value.
|
||||
* If the property already existed, nothing is changes.
|
||||
* @param mesh The mesh on which to create the property.
|
||||
* @param propname The name of the property.
|
||||
*/
|
||||
PropertyManager(const Value& intial_value, PolyConnectivity& mesh, const char *propname) : mesh_(mesh), retain_(true), name_(propname) {
|
||||
if (!mesh_.get_property_handle(prop_, propname)) {
|
||||
mesh_.add_property(prop_, propname);
|
||||
set_range(mesh_.all_elements<Handle>(), intial_value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Create an anonymous property. Lifetime is managed.
|
||||
*
|
||||
* @param mesh The mesh on which to create the property.
|
||||
*/
|
||||
PropertyManager(PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
||||
mesh_.add_property(prop_, name_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Create an anonymous property. Lifetime is managed.
|
||||
*
|
||||
* @param initial_value The property will be initialized with intial_value.
|
||||
* @param mesh The mesh on which to create the property.
|
||||
*/
|
||||
PropertyManager(const Value& intial_value, PolyConnectivity& mesh) : mesh_(mesh), retain_(false), name_("") {
|
||||
mesh_.add_property(prop_, name_);
|
||||
set_range(mesh_.all_elements<Handle>(), intial_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Create a wrapper around an existing property. Lifetime is not managed.
|
||||
*
|
||||
* @param mesh The mesh on which to create the property.
|
||||
*/
|
||||
PropertyManager(PolyConnectivity& mesh, PROPTYPE property_handle) : mesh_(mesh), prop_(property_handle), retain_(true), name_() {
|
||||
}
|
||||
|
||||
PropertyManager() = delete;
|
||||
|
||||
PropertyManager(const PropertyManager& rhs)
|
||||
:
|
||||
mesh_(rhs.mesh_),
|
||||
prop_(),
|
||||
retain_(rhs.retain_),
|
||||
name_(rhs.name_)
|
||||
{
|
||||
if (rhs.retain_) // named property -> create a property manager referring to the same
|
||||
{
|
||||
prop_ = rhs.prop_;
|
||||
}
|
||||
else // unnamed property -> create a property manager refering to a new property and copy the contents
|
||||
{
|
||||
mesh_.add_property(prop_, name_);
|
||||
Storage::copy(rhs, *this);
|
||||
}
|
||||
}
|
||||
|
||||
PropertyManager& operator=(const PropertyManager& rhs)
|
||||
{
|
||||
if (&mesh_ == &rhs.mesh_ && prop_ == rhs.prop_)
|
||||
; // nothing to do
|
||||
else
|
||||
Storage::copy(rhs, *this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~PropertyManager() {
|
||||
@@ -130,49 +252,75 @@ class PropertyManager {
|
||||
}
|
||||
|
||||
void swap(PropertyManager &rhs) {
|
||||
std::swap(mesh_, rhs.mesh_);
|
||||
std::swap(prop_, rhs.prop_);
|
||||
std::swap(retain_, rhs.retain_);
|
||||
std::swap(name_, rhs.name_);
|
||||
// swap the data stored in the properties
|
||||
Storage::swap(rhs, *this);
|
||||
}
|
||||
|
||||
static bool propertyExists(MeshT &mesh, const char *propname) {
|
||||
static bool propertyExists(PolyConnectivity &mesh, const char *propname) {
|
||||
PROPTYPE dummy;
|
||||
return mesh.get_property_handle(dummy, propname);
|
||||
}
|
||||
|
||||
bool isValid() const { return mesh_ != 0; }
|
||||
bool isValid() const { return prop_.is_valid(); }
|
||||
operator bool() const { return isValid(); }
|
||||
|
||||
const PROPTYPE &getRawProperty() const { return prop_; }
|
||||
|
||||
const std::string &getName() const { return name_; }
|
||||
|
||||
MeshT &getMesh() const { return *mesh_; }
|
||||
/**
|
||||
* Get the mesh corresponding to the property.
|
||||
*
|
||||
* If you use PropertyManager without second template parameter (recommended)
|
||||
* you need to specify the actual mesh type when using this function, e.g.:
|
||||
* \code
|
||||
* {
|
||||
* TriMesh mesh;
|
||||
* auto visited = VProp<bool>(mesh);
|
||||
* TriMesh& mesh_ref = visited.getMesh<TriMesh>();
|
||||
* }
|
||||
*
|
||||
*/
|
||||
template <typename MeshType >
|
||||
MeshType& getMesh() const { return dynamic_cast<MeshType&>(mesh_); }
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
/// Only for pre C++11 compatibility.
|
||||
|
||||
typedef PropertyManager<PROPTYPE, MeshT> Proxy;
|
||||
MeshT& getMesh() const { return dynamic_cast<MeshT&>(mesh_); }
|
||||
|
||||
/**
|
||||
* Move constructor. Transfers ownership (delete responsibility).
|
||||
*/
|
||||
PropertyManager(PropertyManager &&rhs) : mesh_(rhs.mesh_), prop_(rhs.prop_), retain_(rhs.retain_), name_(rhs.name_) {
|
||||
rhs.retain_ = true;
|
||||
PropertyManager(PropertyManager &&rhs)
|
||||
:
|
||||
mesh_(rhs.mesh_),
|
||||
prop_(rhs.prop_),
|
||||
retain_(rhs.retain_),
|
||||
name_(rhs.name_)
|
||||
{
|
||||
if (!rhs.retain_)
|
||||
rhs.prop_.invalidate(); // only invalidate unnamed properties
|
||||
}
|
||||
|
||||
/**
|
||||
* Move assignment. Transfers ownership (delete responsibility).
|
||||
*/
|
||||
PropertyManager &operator=(PropertyManager &&rhs) {
|
||||
if (&rhs != this) {
|
||||
deleteProperty();
|
||||
mesh_ = rhs.mesh_;
|
||||
prop_ = rhs.prop_;
|
||||
retain_ = rhs.retain_;
|
||||
name_ = rhs.name_;
|
||||
rhs.retain_ = true;
|
||||
PropertyManager& operator=(PropertyManager&& rhs)
|
||||
{
|
||||
if ((&mesh_ != &rhs.mesh_) || (prop_ != rhs.prop_))
|
||||
{
|
||||
if (rhs.retain_)
|
||||
{
|
||||
// retained properties cannot be invalidated. Copy instead
|
||||
Storage::copy(rhs, *this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// swap the data stored in the properties
|
||||
Storage::swap(rhs, *this);
|
||||
// remove the property from rhs
|
||||
rhs.mesh_.remove_property(rhs.prop_);
|
||||
// invalidate prop_
|
||||
rhs.prop_.invalidate();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -184,11 +332,8 @@ class PropertyManager {
|
||||
*
|
||||
* @see makePropertyManagerFromExistingOrNew
|
||||
*/
|
||||
static PropertyManager createIfNotExists(MeshT &mesh, const char *propname) {
|
||||
PROPTYPE dummy_prop;
|
||||
PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
|
||||
pm.retain();
|
||||
return std::move(pm);
|
||||
static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname) {
|
||||
return PropertyManager(mesh, propname);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +346,7 @@ class PropertyManager {
|
||||
* @see makePropertyManagerFromExistingOrNew
|
||||
*/
|
||||
template<typename PROP_VALUE, typename ITERATOR_TYPE>
|
||||
static PropertyManager createIfNotExists(MeshT &mesh, const char *propname,
|
||||
static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
|
||||
const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
|
||||
const PROP_VALUE &init_value) {
|
||||
const bool exists = propertyExists(mesh, propname);
|
||||
@@ -222,15 +367,15 @@ class PropertyManager {
|
||||
* @see makePropertyManagerFromExistingOrNew
|
||||
*/
|
||||
template<typename PROP_VALUE, typename ITERATOR_RANGE>
|
||||
static PropertyManager createIfNotExists(MeshT &mesh, const char *propname,
|
||||
static PropertyManager createIfNotExists(PolyConnectivity &mesh, const char *propname,
|
||||
const ITERATOR_RANGE &range, const PROP_VALUE &init_value) {
|
||||
return createIfNotExists(
|
||||
mesh, propname, range.begin(), range.end(), init_value);
|
||||
}
|
||||
|
||||
PropertyManager duplicate(const char *clone_name) {
|
||||
PropertyManager pm(*mesh_, clone_name, false);
|
||||
pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
|
||||
PropertyManager pm(mesh_, clone_name, false);
|
||||
pm.mesh_.property(pm.prop_) = mesh_.property(prop_);
|
||||
return pm;
|
||||
}
|
||||
|
||||
@@ -241,89 +386,6 @@ class PropertyManager {
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
#else
|
||||
class Proxy {
|
||||
private:
|
||||
Proxy(MeshT *mesh_, PROPTYPE prop_, bool retain_, const std::string &name_) :
|
||||
mesh_(mesh_), prop_(prop_), retain_(retain_), name_(name_) {}
|
||||
MeshT *mesh_;
|
||||
PROPTYPE prop_;
|
||||
bool retain_;
|
||||
std::string name_;
|
||||
|
||||
friend class PropertyManager;
|
||||
};
|
||||
|
||||
operator Proxy() {
|
||||
Proxy p(mesh_, prop_, retain_, name_);
|
||||
mesh_ = 0;
|
||||
retain_ = true;
|
||||
return p;
|
||||
}
|
||||
|
||||
Proxy move() {
|
||||
return (Proxy)*this;
|
||||
}
|
||||
|
||||
PropertyManager(Proxy p) : mesh_(p.mesh_), prop_(p.prop_), retain_(p.retain_), name_(p.name_) {}
|
||||
|
||||
PropertyManager &operator=(Proxy p) {
|
||||
PropertyManager(p).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a property manager for the supplied property and mesh.
|
||||
* If the property doesn't exist, it is created. In any case,
|
||||
* lifecycle management is disabled.
|
||||
*
|
||||
* @see makePropertyManagerFromExistingOrNew
|
||||
*/
|
||||
static Proxy createIfNotExists(MeshT &mesh, const char *propname) {
|
||||
PROPTYPE dummy_prop;
|
||||
PropertyManager pm(mesh, propname, mesh.get_property_handle(dummy_prop, propname));
|
||||
pm.retain();
|
||||
return (Proxy)pm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like createIfNotExists() with two parameters except, if the property
|
||||
* doesn't exist, it is initialized with the supplied value over
|
||||
* the supplied range after creation. If the property already exists,
|
||||
* this method has the exact same effect as the two parameter version.
|
||||
* Lifecycle management is disabled in any case.
|
||||
*
|
||||
* @see makePropertyManagerFromExistingOrNew
|
||||
*/
|
||||
template<typename PROP_VALUE, typename ITERATOR_TYPE>
|
||||
static Proxy createIfNotExists(MeshT &mesh, const char *propname,
|
||||
const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
|
||||
const PROP_VALUE &init_value) {
|
||||
const bool exists = propertyExists(mesh, propname);
|
||||
PropertyManager pm(mesh, propname, exists);
|
||||
pm.retain();
|
||||
if (!exists)
|
||||
pm.set_range(begin, end, init_value);
|
||||
return (Proxy)pm;
|
||||
}
|
||||
|
||||
Proxy duplicate(const char *clone_name) {
|
||||
PropertyManager pm(*mesh_, clone_name, false);
|
||||
pm.mesh_->property(pm.prop_) = mesh_->property(prop_);
|
||||
return (Proxy)pm;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Disable lifecycle management for this property.
|
||||
*
|
||||
* If this method is called, the encapsulated property will not be deleted
|
||||
* upon destruction of the PropertyManager instance.
|
||||
*/
|
||||
inline void retain(bool doRetain = true) {
|
||||
retain_ = doRetain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the value of the encapsulated mesh property.
|
||||
*
|
||||
@@ -337,7 +399,7 @@ class PropertyManager {
|
||||
* @note This method is only used for mesh properties.
|
||||
*/
|
||||
typename PROPTYPE::reference& operator*() {
|
||||
return mesh_->mproperty(prop_)[0];
|
||||
return mesh_.mproperty(prop_)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,7 +415,7 @@ class PropertyManager {
|
||||
* @note This method is only used for mesh properties.
|
||||
*/
|
||||
typename PROPTYPE::const_reference& operator*() const {
|
||||
return mesh_->mproperty(prop_)[0];
|
||||
return mesh_.mproperty(prop_)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -365,7 +427,7 @@ class PropertyManager {
|
||||
*/
|
||||
template<typename HandleType>
|
||||
inline typename PROPTYPE::reference operator[] (const HandleType &handle) {
|
||||
return mesh_->property(prop_, handle);
|
||||
return mesh_.property(prop_, handle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,7 +439,7 @@ class PropertyManager {
|
||||
*/
|
||||
template<typename HandleType>
|
||||
inline typename PROPTYPE::const_reference operator[] (const HandleType &handle) const {
|
||||
return mesh_->property(prop_, handle);
|
||||
return mesh_.property(prop_, handle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -389,7 +451,7 @@ class PropertyManager {
|
||||
*/
|
||||
template<typename HandleType>
|
||||
inline typename PROPTYPE::reference operator() (const HandleType &handle) {
|
||||
return mesh_->property(prop_, handle);
|
||||
return mesh_.property(prop_, handle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,7 +463,7 @@ class PropertyManager {
|
||||
*/
|
||||
template<typename HandleType>
|
||||
inline typename PROPTYPE::const_reference operator() (const HandleType &handle) const {
|
||||
return mesh_->property(prop_, handle);
|
||||
return mesh_.property(prop_, handle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -410,7 +472,7 @@ class PropertyManager {
|
||||
* Examples:
|
||||
* \code
|
||||
* MeshT mesh;
|
||||
* PropertyManager<VPropHandleT<double>, MeshT> distance(
|
||||
* PropertyManager<VPropHandleT<double>> distance(
|
||||
* mesh, "distance.plugin-example.i8.informatik.rwth-aachen.de");
|
||||
* distance.set_range(
|
||||
* mesh.vertices_begin(), mesh.vertices_end(),
|
||||
@@ -458,9 +520,9 @@ class PropertyManager {
|
||||
* Will be used with dst_propmanager. Used to double check the bounds.
|
||||
*/
|
||||
template<typename HandleTypeIterator, typename PROPTYPE_2,
|
||||
typename MeshT_2, typename HandleTypeIterator_2>
|
||||
typename HandleTypeIterator_2>
|
||||
void copy_to(HandleTypeIterator begin, HandleTypeIterator end,
|
||||
PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
|
||||
PropertyManager<PROPTYPE_2> &dst_propmanager,
|
||||
HandleTypeIterator_2 dst_begin, HandleTypeIterator_2 dst_end) const {
|
||||
|
||||
for (; begin != end && dst_begin != dst_end; ++begin, ++dst_begin) {
|
||||
@@ -469,14 +531,15 @@ class PropertyManager {
|
||||
}
|
||||
|
||||
template<typename RangeType, typename PROPTYPE_2,
|
||||
typename MeshT_2, typename RangeType_2>
|
||||
typename RangeType_2>
|
||||
void copy_to(const RangeType &range,
|
||||
PropertyManager<PROPTYPE_2, MeshT_2> &dst_propmanager,
|
||||
PropertyManager<PROPTYPE_2> &dst_propmanager,
|
||||
const RangeType_2 &dst_range) const {
|
||||
copy_to(range.begin(), range.end(), dst_propmanager,
|
||||
dst_range.begin(), dst_range.end());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the values of a property from a source range to
|
||||
* a target range. The source range must not be smaller than the
|
||||
@@ -491,15 +554,15 @@ class PropertyManager {
|
||||
* @param dst_mesh Destination mesh on which to copy.
|
||||
* @param dst_range Destination range.
|
||||
*/
|
||||
template<typename RangeType, typename MeshT_2, typename RangeType_2>
|
||||
template<typename RangeType, typename RangeType_2>
|
||||
static void copy(const char *prop_name,
|
||||
MeshT &src_mesh, const RangeType &src_range,
|
||||
MeshT_2 &dst_mesh, const RangeType_2 &dst_range) {
|
||||
PolyConnectivity &src_mesh, const RangeType &src_range,
|
||||
PolyConnectivity &dst_mesh, const RangeType_2 &dst_range) {
|
||||
|
||||
typedef OpenMesh::PropertyManager<PROPTYPE, MeshT> DstPM;
|
||||
typedef OpenMesh::PropertyManager<PROPTYPE> DstPM;
|
||||
DstPM dst(DstPM::createIfNotExists(dst_mesh, prop_name));
|
||||
|
||||
typedef OpenMesh::PropertyManager<PROPTYPE, MeshT_2> SrcPM;
|
||||
typedef OpenMesh::PropertyManager<PROPTYPE> SrcPM;
|
||||
SrcPM src(src_mesh, prop_name, true);
|
||||
|
||||
src.copy_to(src_range, dst, dst_range);
|
||||
@@ -507,18 +570,20 @@ class PropertyManager {
|
||||
|
||||
private:
|
||||
void deleteProperty() {
|
||||
if (!retain_)
|
||||
mesh_->remove_property(prop_);
|
||||
if (!retain_ && prop_.is_valid())
|
||||
mesh_.remove_property(prop_);
|
||||
}
|
||||
|
||||
private:
|
||||
MeshT *mesh_;
|
||||
PolyConnectivity& mesh_;
|
||||
PROPTYPE prop_;
|
||||
bool retain_;
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
/** @relates PropertyManager
|
||||
*
|
||||
* @deprecated Temporary properties should not have a name.
|
||||
*
|
||||
* Creates a new property whose lifetime is limited to the current scope.
|
||||
*
|
||||
@@ -541,13 +606,72 @@ class PropertyManager {
|
||||
* @param propname (optional) The name of the created property
|
||||
* @tparam ElementT Element type of the created property, e.g. VertexHandle, HalfedgeHandle, etc.
|
||||
* @tparam T Value type of the created property, e.g., \p double, \p int, etc.
|
||||
* @tparam MeshT Type of the mesh. Can often be inferred from \p mesh
|
||||
* @returns A PropertyManager handling the lifecycle of the property
|
||||
*/
|
||||
template<typename ElementT, typename T, typename MeshT>
|
||||
PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>
|
||||
makeTemporaryProperty(MeshT &mesh, const char *propname = "") {
|
||||
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>(mesh, propname, false);
|
||||
template<typename ElementT, typename T>
|
||||
PropertyManager<typename HandleToPropHandle<ElementT, T>::type>
|
||||
OM_DEPRECATED("Named temporary properties are deprecated. Either create a temporary without name or a non-temporary with name")
|
||||
makeTemporaryProperty(PolyConnectivity &mesh, const char *propname) {
|
||||
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>(mesh, propname, false);
|
||||
}
|
||||
|
||||
/** @relates PropertyManager
|
||||
*
|
||||
* Creates a new property whose lifetime is limited to the current scope.
|
||||
*
|
||||
* Used for temporary properties. Shadows any existing properties of
|
||||
* matching name and type.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* PolyMesh m;
|
||||
* {
|
||||
* auto is_quad = makeTemporaryProperty<FaceHandle, bool>(m);
|
||||
* for (auto& fh : m.faces()) {
|
||||
* is_quad[fh] = (m.valence(fh) == 4);
|
||||
* }
|
||||
* // The property is automatically removed from the mesh at the end of the scope.
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param mesh The mesh on which the property is created
|
||||
* @tparam ElementT Element type of the created property, e.g. VertexHandle, HalfedgeHandle, etc.
|
||||
* @tparam T Value type of the created property, e.g., \p double, \p int, etc.
|
||||
* @returns A PropertyManager handling the lifecycle of the property
|
||||
*/
|
||||
template<typename ElementT, typename T>
|
||||
PropertyManager<typename HandleToPropHandle<ElementT, T>::type>
|
||||
makeTemporaryProperty(PolyConnectivity &mesh) {
|
||||
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>(mesh);
|
||||
}
|
||||
|
||||
|
||||
/** @relates PropertyManager
|
||||
*
|
||||
* Tests whether a property with the given element type, value type, and name is
|
||||
* present on the given mesh.
|
||||
*
|
||||
* * Example:
|
||||
* @code
|
||||
* PolyMesh m;
|
||||
* if (hasProperty<FaceHandle, bool>(m, "is_quad")) {
|
||||
* // We now know the property exists: getProperty won't throw.
|
||||
* auto is_quad = getProperty<FaceHandle, bool>(m, "is_quad");
|
||||
* // Use is_quad here.
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param mesh The mesh in question
|
||||
* @param propname The property name of the expected property
|
||||
* @tparam ElementT Element type of the expected property, e.g. VertexHandle, HalfedgeHandle, etc.
|
||||
* @tparam T Value type of the expected property, e.g., \p double, \p int, etc.
|
||||
* @tparam MeshT Type of the mesh. Can often be inferred from \p mesh
|
||||
*/
|
||||
template<typename ElementT, typename T>
|
||||
bool
|
||||
hasProperty(const PolyConnectivity &mesh, const char *propname) {
|
||||
typename HandleToPropHandle<ElementT, T>::type ph;
|
||||
return mesh.get_property_handle(ph, propname);
|
||||
}
|
||||
|
||||
/** @relates PropertyManager
|
||||
@@ -575,13 +699,18 @@ makeTemporaryProperty(MeshT &mesh, const char *propname = "") {
|
||||
* @param propname The name of the created property
|
||||
* @tparam ElementT Element type of the created property, e.g. VertexHandle, HalfedgeHandle, etc.
|
||||
* @tparam T Value type of the created property, e.g., \p double, \p int, etc.
|
||||
* @tparam MeshT Type of the mesh. Can often be inferred from \p mesh
|
||||
* @returns A PropertyManager wrapping the property
|
||||
*/
|
||||
template<typename ElementT, typename T, typename MeshT>
|
||||
PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>
|
||||
getProperty(MeshT &mesh, const char *propname) {
|
||||
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>(mesh, propname, true);
|
||||
template<typename ElementT, typename T>
|
||||
PropertyManager<typename HandleToPropHandle<ElementT, T>::type>
|
||||
getProperty(PolyConnectivity &mesh, const char *propname) {
|
||||
if (!hasProperty<ElementT, T>(mesh, propname))
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Requested property handle \"" << propname << "\" does not exist.";
|
||||
throw std::runtime_error(oss.str());
|
||||
}
|
||||
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>(mesh, propname);
|
||||
}
|
||||
|
||||
/** @relates PropertyManager
|
||||
@@ -611,41 +740,12 @@ getProperty(MeshT &mesh, const char *propname) {
|
||||
* @param propname The name of the created property
|
||||
* @tparam ElementT Element type of the created property, e.g. VertexHandle, HalfedgeHandle, etc.
|
||||
* @tparam T Value type of the created property, e.g., \p double, \p int, etc.
|
||||
* @tparam MeshT Type of the mesh. Can often be inferred from \p mesh
|
||||
* @returns A PropertyManager wrapping the property
|
||||
*/
|
||||
template<typename ElementT, typename T, typename MeshT>
|
||||
PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>
|
||||
getOrMakeProperty(MeshT &mesh, const char *propname) {
|
||||
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type, MeshT>::createIfNotExists(mesh, propname);
|
||||
}
|
||||
|
||||
/** @relates PropertyManager
|
||||
*
|
||||
* Tests whether a property with the given element type, value type, and name is
|
||||
* present on the given mesh.
|
||||
*
|
||||
* * Example:
|
||||
* @code
|
||||
* PolyMesh m;
|
||||
* if (hasProperty<FaceHandle, bool>(m, "is_quad")) {
|
||||
* // We now know the property exists: getProperty won't throw.
|
||||
* auto is_quad = getProperty<FaceHandle, bool>(m, "is_quad");
|
||||
* // Use is_quad here.
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @param mesh The mesh in question
|
||||
* @param propname The property name of the expected property
|
||||
* @tparam ElementT Element type of the expected property, e.g. VertexHandle, HalfedgeHandle, etc.
|
||||
* @tparam T Value type of the expected property, e.g., \p double, \p int, etc.
|
||||
* @tparam MeshT Type of the mesh. Can often be inferred from \p mesh
|
||||
*/
|
||||
template<typename ElementT, typename T, typename MeshT>
|
||||
bool
|
||||
hasProperty(const MeshT &mesh, const char *propname) {
|
||||
typename HandleToPropHandle<ElementT, T>::type ph;
|
||||
return mesh.get_property_handle(ph, propname);
|
||||
template<typename ElementT, typename T>
|
||||
PropertyManager<typename HandleToPropHandle<ElementT, T>::type>
|
||||
getOrMakeProperty(PolyConnectivity &mesh, const char *propname) {
|
||||
return PropertyManager<typename HandleToPropHandle<ElementT, T>::type>::createIfNotExists(mesh, propname);
|
||||
}
|
||||
|
||||
/** @relates PropertyManager
|
||||
@@ -657,11 +757,11 @@ hasProperty(const MeshT &mesh, const char *propname) {
|
||||
* Intended for temporary properties. Shadows any existing properties of
|
||||
* matching name and type.
|
||||
*/
|
||||
template<typename PROPTYPE, typename MeshT>
|
||||
template<typename PROPTYPE>
|
||||
OM_DEPRECATED("Use makeTemporaryProperty instead.")
|
||||
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromNew(MeshT &mesh, const char *propname)
|
||||
PropertyManager<PROPTYPE> makePropertyManagerFromNew(PolyConnectivity &mesh, const char *propname)
|
||||
{
|
||||
return PropertyManager<PROPTYPE, MeshT>(mesh, propname, false);
|
||||
return PropertyManager<PROPTYPE>(mesh, propname, false);
|
||||
}
|
||||
|
||||
/** \relates PropertyManager
|
||||
@@ -676,11 +776,11 @@ PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromNew(MeshT &mesh, const c
|
||||
* @throws std::runtime_error if no property with the name \p propname of
|
||||
* matching type exists.
|
||||
*/
|
||||
template<typename PROPTYPE, typename MeshT>
|
||||
template<typename PROPTYPE>
|
||||
OM_DEPRECATED("Use getProperty instead.")
|
||||
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExisting(MeshT &mesh, const char *propname)
|
||||
PropertyManager<PROPTYPE> makePropertyManagerFromExisting(PolyConnectivity &mesh, const char *propname)
|
||||
{
|
||||
return PropertyManager<PROPTYPE, MeshT>(mesh, propname, true);
|
||||
return PropertyManager<PROPTYPE>(mesh, propname, true);
|
||||
}
|
||||
|
||||
/** @relates PropertyManager
|
||||
@@ -691,11 +791,11 @@ PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExisting(MeshT &mesh, co
|
||||
*
|
||||
* Intended for creating or accessing persistent properties.
|
||||
*/
|
||||
template<typename PROPTYPE, typename MeshT>
|
||||
template<typename PROPTYPE>
|
||||
OM_DEPRECATED("Use getOrMakeProperty instead.")
|
||||
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(MeshT &mesh, const char *propname)
|
||||
PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(PolyConnectivity &mesh, const char *propname)
|
||||
{
|
||||
return PropertyManager<PROPTYPE, MeshT>::createIfNotExists(mesh, propname);
|
||||
return PropertyManager<PROPTYPE>::createIfNotExists(mesh, propname);
|
||||
}
|
||||
|
||||
/** @relates PropertyManager
|
||||
@@ -709,14 +809,14 @@ PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(MeshT &mes
|
||||
*
|
||||
* Intended for creating or accessing persistent properties.
|
||||
*/
|
||||
template<typename PROPTYPE, typename MeshT,
|
||||
template<typename PROPTYPE,
|
||||
typename ITERATOR_TYPE, typename PROP_VALUE>
|
||||
OM_DEPRECATED("Use getOrMakeProperty instead.")
|
||||
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
|
||||
MeshT &mesh, const char *propname,
|
||||
PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(
|
||||
PolyConnectivity &mesh, const char *propname,
|
||||
const ITERATOR_TYPE &begin, const ITERATOR_TYPE &end,
|
||||
const PROP_VALUE &init_value) {
|
||||
return PropertyManager<PROPTYPE, MeshT>::createIfNotExists(
|
||||
return PropertyManager<PROPTYPE>::createIfNotExists(
|
||||
mesh, propname, begin, end, init_value);
|
||||
}
|
||||
|
||||
@@ -731,16 +831,45 @@ PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
|
||||
*
|
||||
* Intended for creating or accessing persistent properties.
|
||||
*/
|
||||
template<typename PROPTYPE, typename MeshT,
|
||||
template<typename PROPTYPE,
|
||||
typename ITERATOR_RANGE, typename PROP_VALUE>
|
||||
OM_DEPRECATED("Use getOrMakeProperty instead.")
|
||||
PropertyManager<PROPTYPE, MeshT> makePropertyManagerFromExistingOrNew(
|
||||
MeshT &mesh, const char *propname,
|
||||
PropertyManager<PROPTYPE> makePropertyManagerFromExistingOrNew(
|
||||
PolyConnectivity &mesh, const char *propname,
|
||||
const ITERATOR_RANGE &range,
|
||||
const PROP_VALUE &init_value) {
|
||||
return makePropertyManagerFromExistingOrNew<PROPTYPE, MeshT>(
|
||||
return makePropertyManagerFromExistingOrNew<PROPTYPE>(
|
||||
mesh, propname, range.begin(), range.end(), init_value);
|
||||
}
|
||||
|
||||
|
||||
/** @relates PropertyManager
|
||||
* Returns a convenience wrapper around the points property of a mesh.
|
||||
*/
|
||||
template<typename MeshT>
|
||||
PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>
|
||||
getPointsProperty(MeshT &mesh) {
|
||||
return PropertyManager<OpenMesh::VPropHandleT<typename MeshT::Point>>(mesh, mesh.points_property_handle());
|
||||
}
|
||||
|
||||
template <typename HandleT, typename T>
|
||||
using Prop = PropertyManager<typename PropHandle<HandleT>::template type<T>>;
|
||||
|
||||
template <typename T>
|
||||
using VProp = PropertyManager<OpenMesh::VPropHandleT<T>>;
|
||||
|
||||
template <typename T>
|
||||
using HProp = PropertyManager<OpenMesh::HPropHandleT<T>>;
|
||||
|
||||
template <typename T>
|
||||
using EProp = PropertyManager<OpenMesh::EPropHandleT<T>>;
|
||||
|
||||
template <typename T>
|
||||
using FProp = PropertyManager<OpenMesh::FPropHandleT<T>>;
|
||||
|
||||
template <typename T>
|
||||
using MProp = PropertyManager<OpenMesh::MPropHandleT<T>>;
|
||||
|
||||
|
||||
} /* namespace OpenMesh */
|
||||
#endif /* PROPERTYMANAGER_HH_ */
|
||||
|
||||
@@ -51,8 +51,8 @@ protected: // SubdividerT interface
|
||||
_m.request_edge_status();
|
||||
_m.request_vertex_status();
|
||||
_m.request_face_status();
|
||||
PropertyManager<EPropHandleT<typename mesh_t::VertexHandle>, mesh_t> edge_midpoint(_m, "edge_midpoint");
|
||||
PropertyManager<VPropHandleT<bool>, mesh_t> is_original_vertex(_m, "is_original_vertex");
|
||||
PropertyManager<EPropHandleT<typename mesh_t::VertexHandle>> edge_midpoint(_m, "edge_midpoint");
|
||||
PropertyManager<VPropHandleT<bool>> is_original_vertex(_m, "is_original_vertex");
|
||||
|
||||
for (size_t iteration = 0; iteration < _n; ++iteration) {
|
||||
is_original_vertex.set_range(_m.vertices_begin(), _m.vertices_end(), true);
|
||||
|
||||
@@ -41,20 +41,25 @@ if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
# Create unittest executable
|
||||
acg_add_executable(unittests ${UNITTEST_SRC})
|
||||
acg_add_executable(unittests_customvec ${UNITTEST_SRC})
|
||||
acg_add_executable(unittests_doublevec ${UNITTEST_SRC})
|
||||
target_compile_definitions(unittests_customvec PRIVATE TEST_CUSTOM_TRAITS)
|
||||
target_compile_definitions(unittests_doublevec PRIVATE TEST_DOUBLE_TRAITS)
|
||||
|
||||
# For the unittest we don't want the install rpath as set by acg_add_executable
|
||||
set_target_properties ( unittests PROPERTIES BUILD_WITH_INSTALL_RPATH 0 )
|
||||
set_target_properties ( unittests PROPERTIES BUILD_WITH_INSTALL_RPATH 0 )
|
||||
set_target_properties ( unittests_customvec PROPERTIES BUILD_WITH_INSTALL_RPATH 0 )
|
||||
set_target_properties ( unittests_doublevec PROPERTIES BUILD_WITH_INSTALL_RPATH 0 )
|
||||
|
||||
# Set output directory to ${BINARY_DIR}/Unittests
|
||||
set (OUTPUT_DIR "${CMAKE_BINARY_DIR}/Unittests")
|
||||
set_target_properties(unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||
set_target_properties(unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||
set_target_properties(unittests_customvec PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||
set_target_properties(unittests_doublevec PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})
|
||||
foreach(CONFIG ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER ${CONFIG} UPCONFIG)
|
||||
set_target_properties(unittests PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${UPCONFIG} ${OUTPUT_DIR})
|
||||
set_target_properties(unittests_customvec PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${UPCONFIG} ${OUTPUT_DIR})
|
||||
set_target_properties(unittests_doublevec PROPERTIES RUNTIME_OUTPUT_DIRECTORY_${UPCONFIG} ${OUTPUT_DIR})
|
||||
endforeach()
|
||||
|
||||
|
||||
@@ -62,6 +67,7 @@ if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
# Link against all necessary libraries
|
||||
target_link_libraries(unittests OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
|
||||
target_link_libraries(unittests_customvec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
|
||||
target_link_libraries(unittests_doublevec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
|
||||
|
||||
|
||||
|
||||
@@ -71,8 +77,9 @@ if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
add_definitions( -DOPENMESHDLL )
|
||||
|
||||
endif()
|
||||
target_link_libraries(unittests OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
target_link_libraries(unittests OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
target_link_libraries(unittests_customvec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
target_link_libraries(unittests_doublevec OpenMeshCore OpenMeshTools ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -81,10 +88,12 @@ if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
# Set compiler flags
|
||||
set_target_properties(unittests PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long")
|
||||
set_target_properties(unittests_customvec PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long")
|
||||
set_target_properties(unittests_doublevec PROPERTIES COMPILE_FLAGS "-g -pedantic -Wno-long-long")
|
||||
else()
|
||||
# Set compiler flags
|
||||
set_target_properties(unittests PROPERTIES COMPILE_FLAGS "" )
|
||||
set_target_properties(unittests_customvec PROPERTIES COMPILE_FLAGS "" )
|
||||
set_target_properties(unittests_doublevec PROPERTIES COMPILE_FLAGS "" )
|
||||
endif()
|
||||
|
||||
if ( OPENMESH_BUILD_SHARED )
|
||||
@@ -103,14 +112,21 @@ if ( OPENMESH_BUILD_UNIT_TESTS )
|
||||
"$<TARGET_FILE:${TAR}>"
|
||||
"${CMAKE_BINARY_DIR}/Unittests/$<TARGET_FILE_NAME:${TAR}>"
|
||||
COMMENT "Copying OpenMesh targets to unittests directory")
|
||||
add_custom_command(TARGET unittests_doublevec POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||
"$<TARGET_FILE:${TAR}>"
|
||||
"${CMAKE_BINARY_DIR}/Unittests/$<TARGET_FILE_NAME:${TAR}>"
|
||||
COMMENT "Copying OpenMesh targets to unittests directory")
|
||||
endforeach(TAR)
|
||||
endif()
|
||||
|
||||
acg_copy_after_build(unittests ${CMAKE_CURRENT_SOURCE_DIR}/TestFiles ${CMAKE_BINARY_DIR}/Unittests/)
|
||||
acg_copy_after_build(unittests_customvec ${CMAKE_CURRENT_SOURCE_DIR}/TestFiles ${CMAKE_BINARY_DIR}/Unittests/)
|
||||
acg_copy_after_build(unittests_doublevec ${CMAKE_CURRENT_SOURCE_DIR}/TestFiles ${CMAKE_BINARY_DIR}/Unittests/)
|
||||
|
||||
add_test(NAME AllTestsIn_OpenMesh_tests WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/Unittests" COMMAND "${CMAKE_BINARY_DIR}/Unittests/unittests")
|
||||
add_test(NAME AllTestsIn_OpenMesh_tests_with_minimal_vector WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/Unittests" COMMAND "${CMAKE_BINARY_DIR}/Unittests/unittests_customvec")
|
||||
add_test(NAME AllTestsIn_OpenMesh_tests_with_double_vector WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/Unittests" COMMAND "${CMAKE_BINARY_DIR}/Unittests/unittests_doublevec")
|
||||
|
||||
else(GTEST_FOUND)
|
||||
message(STATUS "Google testing framework was not found, unittests disabled.")
|
||||
|
||||
@@ -62,7 +62,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
|
||||
{
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::VPropHandleT<bool>, Mesh> pm_v_bool(mesh_, "pm_v_bool");
|
||||
OpenMesh::VPropHandleT<bool>> pm_v_bool(mesh_, "pm_v_bool");
|
||||
pm_v_bool.set_range(mesh_.vertices_begin(), mesh_.vertices_end(), false);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
ASSERT_FALSE(pm_v_bool[vhandle[i]]);
|
||||
@@ -71,7 +71,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_v_bool[vhandle[i]]);
|
||||
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::EPropHandleT<bool>, Mesh> pm_e_bool(mesh_, "pm_e_bool");
|
||||
OpenMesh::EPropHandleT<bool>> pm_e_bool(mesh_, "pm_e_bool");
|
||||
pm_e_bool.set_range(mesh_.edges_begin(), mesh_.edges_end(), false);
|
||||
for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
|
||||
e_it != f_end; ++e_it)
|
||||
@@ -82,7 +82,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_e_bool[*e_it]);
|
||||
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::FPropHandleT<bool>, Mesh> pm_f_bool(mesh_, "pm_f_bool");
|
||||
OpenMesh::FPropHandleT<bool>> pm_f_bool(mesh_, "pm_f_bool");
|
||||
pm_f_bool.set_range(mesh_.faces_begin(), mesh_.faces_end(), false);
|
||||
for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
|
||||
f_it != f_end; ++f_it)
|
||||
@@ -98,7 +98,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
*/
|
||||
{
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::VPropHandleT<bool>, Mesh> pm_v_bool(mesh_, "pm_v_bool2");
|
||||
OpenMesh::VPropHandleT<bool>> pm_v_bool(mesh_, "pm_v_bool2");
|
||||
pm_v_bool.set_range(mesh_.vertices(), false);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
ASSERT_FALSE(pm_v_bool[vhandle[i]]);
|
||||
@@ -107,7 +107,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_v_bool[vhandle[i]]);
|
||||
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::EPropHandleT<bool>, Mesh> pm_e_bool(mesh_, "pm_e_bool2");
|
||||
OpenMesh::EPropHandleT<bool>> pm_e_bool(mesh_, "pm_e_bool2");
|
||||
pm_e_bool.set_range(mesh_.edges(), false);
|
||||
for (Mesh::EdgeIter e_it = mesh_.edges_begin(), f_end = mesh_.edges_end();
|
||||
e_it != f_end; ++e_it)
|
||||
@@ -118,7 +118,7 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
ASSERT_TRUE(pm_e_bool[*e_it]);
|
||||
|
||||
OpenMesh::PropertyManager<
|
||||
OpenMesh::FPropHandleT<bool>, Mesh> pm_f_bool(mesh_, "pm_f_bool2");
|
||||
OpenMesh::FPropHandleT<bool>> pm_f_bool(mesh_, "pm_f_bool2");
|
||||
pm_f_bool.set_range(mesh_.faces(), false);
|
||||
for (Mesh::FaceIter f_it = mesh_.faces_begin(), f_end = mesh_.faces_end();
|
||||
f_it != f_end; ++f_it)
|
||||
@@ -130,62 +130,6 @@ TEST_F(OpenMeshPropertyManager, set_range_bool) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ====================================================================
|
||||
* Factory Functions
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
template<typename PropHandle, typename Mesh>
|
||||
bool has_property(const Mesh& _mesh, const std::string& _name) {
|
||||
auto dummy_handle = PropHandle{};
|
||||
return _mesh.get_property_handle(dummy_handle, _name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Temporary property
|
||||
*/
|
||||
TEST_F(OpenMeshPropertyManager, cpp11_temp_property) {
|
||||
using handle_type = OpenMesh::VPropHandleT<int>;
|
||||
const auto prop_name = "pm_v_test_property";
|
||||
ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
|
||||
|
||||
{
|
||||
auto vprop = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
|
||||
static_cast<void>(vprop); // Unused variable
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
}
|
||||
|
||||
ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Two temporary properties on a mesh using the same name and type. The second
|
||||
* (inner) one shadows the first (outer) one instead of aliasing.
|
||||
*/
|
||||
TEST_F(OpenMeshPropertyManager, cpp11_temp_property_shadowing) {
|
||||
auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to
|
||||
|
||||
using handle_type = OpenMesh::VPropHandleT<int>;
|
||||
const auto prop_name = "pm_v_test_property";
|
||||
|
||||
auto outer_prop = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
|
||||
outer_prop[vh] = 100;
|
||||
ASSERT_EQ(100, outer_prop[vh]);
|
||||
|
||||
{
|
||||
// inner_prop uses same type and name as outer_prop
|
||||
auto inner_prop = OpenMesh::makeTemporaryProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
|
||||
inner_prop[vh] = 200;
|
||||
ASSERT_EQ(200, inner_prop[vh]);
|
||||
// End of scope: inner_prop is removed from mesh_
|
||||
}
|
||||
|
||||
// Ensure outer_prop still exists and its data has not been overwritten by inner_prop
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_EQ(100, outer_prop[vh]);
|
||||
}
|
||||
|
||||
/*
|
||||
* In sequence:
|
||||
* - add a persistent property to a mesh
|
||||
@@ -196,10 +140,9 @@ TEST_F(OpenMeshPropertyManager, cpp11_temp_property_shadowing) {
|
||||
TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
|
||||
auto vh = mesh_.add_vertex({0,0,0}); // Dummy vertex to attach properties to
|
||||
|
||||
using handle_type = OpenMesh::VPropHandleT<int>;
|
||||
const auto prop_name = "pm_v_test_property";
|
||||
|
||||
ASSERT_FALSE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_FALSE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
|
||||
{
|
||||
auto prop = OpenMesh::getOrMakeProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name);
|
||||
@@ -207,7 +150,7 @@ TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
|
||||
// End of scope, property persists
|
||||
}
|
||||
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
|
||||
{
|
||||
// Since a property of the same name and type already exists, this refers to the existing property.
|
||||
@@ -217,7 +160,7 @@ TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
|
||||
// End of scope, property persists
|
||||
}
|
||||
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
|
||||
{
|
||||
// Acquire non-owning handle to the property, knowing it exists
|
||||
@@ -225,7 +168,7 @@ TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
|
||||
ASSERT_EQ(200, prop[vh]);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
|
||||
{
|
||||
// Attempt to acquire non-owning handle for a non-existing property
|
||||
@@ -235,7 +178,630 @@ TEST_F(OpenMeshPropertyManager, cpp11_persistent_and_non_owning_properties) {
|
||||
ASSERT_THROW(code_that_throws(), std::runtime_error);
|
||||
}
|
||||
|
||||
ASSERT_TRUE(has_property<handle_type>(mesh_, prop_name));
|
||||
ASSERT_TRUE((OpenMesh::hasProperty<OpenMesh::VertexHandle, int>(mesh_, prop_name)));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_copy_construction) {
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto prop2 = prop1; // prop1 and prop2 should be two different properties with the same content
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13);
|
||||
}
|
||||
|
||||
// named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto prop2 = prop1; // prop1 and prop2 should refere to the same property
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13);
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_move_construction) {
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
auto prop2 = std::move(prop1);
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "move constructing property from temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_FALSE(prop1.isValid()) << "prop1 should have been invalidated";
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13);
|
||||
}
|
||||
|
||||
// named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
auto prop2 = std::move(prop1); // prop1 and prop2 should refere to the same property
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "move constructing from named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_TRUE(prop1.isValid()) << "named properties cannot be invalidated";
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "property is not valid anymore";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "did not copy property correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_copying_same_mesh) {
|
||||
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(3, mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(0, mesh_);
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 3) << "Property not initialized correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1;
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// unnamed to named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(0, mesh_, "ids");
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1;
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], -13) << "property with name 'ids' was not correctly changed";
|
||||
}
|
||||
|
||||
// named to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids2");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1;
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
}
|
||||
|
||||
// named to named (different names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids3");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids4");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1;
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// named to named (same names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1; // this should be a no op
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 42);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
{
|
||||
auto prop1 = OpenMesh::MProp<int>(mesh_);
|
||||
*prop1 = 43;
|
||||
auto prop2 = prop1;
|
||||
|
||||
prop2 = prop1;
|
||||
|
||||
prop2 = std::move(prop1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_moving_same_mesh) {
|
||||
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1); // this should be cheap
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// unnamed to named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1);
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], -13) << "property with name 'ids' was not correctly changed";
|
||||
}
|
||||
|
||||
// named to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids2");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
}
|
||||
|
||||
// named to named (different names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids3");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids4");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// named to named (same names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
auto prop2 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1); // this should be a no op
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_copying_different_mesh) {
|
||||
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
auto copy = mesh_;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
copy.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(3, mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(0, copy);
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 3) << "Property not initialized correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1;
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 0) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_NO_FATAL_FAILURE(prop2[OpenMesh::VertexHandle(static_cast<int>(copy.n_vertices())-1)]) << "Property not correctly resized";
|
||||
}
|
||||
|
||||
// unnamed to named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(0, copy, "ids");
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1;
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Temporary property got destroyed";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(copy, "ids");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], -13) << "property with name 'ids' was not correctly changed";
|
||||
}
|
||||
|
||||
// named to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids2");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1;
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
}
|
||||
|
||||
// named to named (different names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids3");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids4");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1;
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// named to named (same names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids5");
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = prop1; // this should be a no op
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "copying property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 42);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
auto prop4 = OpenMesh::VProp<int>(copy, "ids5");
|
||||
EXPECT_EQ(prop4[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_F(OpenMeshPropertyManager, property_moving_different_mesh) {
|
||||
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
mesh_.add_vertex(Mesh::Point());
|
||||
|
||||
auto copy = mesh_;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
copy.add_vertex(Mesh::Point());
|
||||
|
||||
// unnamed to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(copy);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1); // this should be cheap
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property temporary to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_NO_FATAL_FAILURE(prop2[OpenMesh::VertexHandle(static_cast<int>(copy.n_vertices())-1)]) << "Property not correctly resized";
|
||||
}
|
||||
|
||||
// unnamed to named
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_);
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1);
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property temporary to named took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_FALSE(prop1.isValid()) << "prop1 not invalidated after moving";
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(copy, "ids");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], -13) << "property with name 'ids' was not correctly changed";
|
||||
}
|
||||
|
||||
// named to unnamed
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids2");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy);
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property named to temporary took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
}
|
||||
|
||||
// named to named (different names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids3");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids4");
|
||||
prop2.set_range(mesh_.vertices(), 0);
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], 0) << "Property not initialized correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1); // moving named properties will not invalidate the property and will copy the data
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property named to named with different name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 0);
|
||||
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
|
||||
// named to named (same names)
|
||||
{
|
||||
auto prop1 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
auto prop2 = OpenMesh::VProp<int>(copy, "ids5");
|
||||
|
||||
auto prop6 = OpenMesh::Prop<OpenMesh::VertexHandle, int>(mesh_);
|
||||
prop6 = prop1;
|
||||
|
||||
for (auto vh : mesh_.vertices())
|
||||
prop1[vh] = vh.idx()*2-13;
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto t_start = std::chrono::high_resolution_clock::now();
|
||||
prop2 = std::move(prop1); // should copy
|
||||
auto t_end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "moving property named to named with same name took " << std::chrono::duration_cast<std::chrono::milliseconds>(t_end-t_start).count() << "ms" << std::endl;
|
||||
|
||||
EXPECT_TRUE(prop1.isValid()) << "named prop1 should not be invalidated by moving";
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
prop1.set_range(mesh_.vertices(), 42);
|
||||
|
||||
EXPECT_EQ(prop1[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
EXPECT_EQ(prop2[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
|
||||
auto prop3 = OpenMesh::VProp<int>(mesh_, "ids5");
|
||||
EXPECT_EQ(prop3[OpenMesh::VertexHandle(0)], 42) << "Property not copied correctly";
|
||||
auto prop4 = OpenMesh::VProp<int>(copy, "ids5");
|
||||
EXPECT_EQ(prop4[OpenMesh::VertexHandle(0)], -13) << "Property not copied correctly";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user